373 votes

Quels modèles de branchement Git fonctionnent pour vous ?

Notre entreprise utilise actuellement un modèle de branchement simple trunk/release/hotfixes et aimerait avoir des conseils sur les modèles de branchement qui fonctionnent le mieux pour votre entreprise ou votre processus de développement.

  1. Flux de travail / modèles de branchement

    Voici les trois principales descriptions que j'ai vues à ce sujet, mais elles se contredisent partiellement ou ne vont pas assez loin pour résoudre les problèmes que nous avons rencontrés par la suite (comme décrit ci-dessous). Par conséquent, notre équipe a opté par défaut pour des solutions pas très bonnes. Faites-vous quelque chose de mieux ?

  2. Fusionner ou rebaser (historique enchevêtré ou séquentiel)

    Devrait-on pull --rebase ou attendre avec la fusion de retour à la ligne principale jusqu'à ce que votre tâche soit terminée ? Personnellement, je penche pour la fusion car cela préserve une illustration visuelle de la base sur laquelle une tâche a été commencée et terminée, et je préfère même merge --no-ff à cette fin. Elle présente toutefois d'autres inconvénients. En outre, beaucoup n'ont pas réalisé la propriété utile de la fusion, à savoir qu'elle n'est pas commutatif (fusionner une branche topic dans master ne signifie pas fusionner master dans la branche topic).

  3. Je recherche un flux de travail naturel

    Parfois, des erreurs se produisent parce que nos procédures ne tiennent pas compte d'une situation spécifique avec des règles simples. Par exemple, un correctif nécessaire pour les versions antérieures devrait bien sûr être basé suffisamment en aval pour pouvoir être fusionné en amont dans toutes les branches nécessaires (l'utilisation de ces termes est-elle suffisamment claire ?). Cependant, il arrive qu'un correctif se retrouve dans le master avant que le développeur ne réalise qu'il aurait dû être placé plus en aval, et si ce correctif est déjà poussé (ou pire, fusionné ou quelque chose basé dessus), alors l'option restante est le cherry-picking, avec les périls associés. Quelles règles simples de ce type utilisez-vous ? Cela inclut également la maladresse d'une branche de sujet excluant nécessairement d'autres branches de sujet (en supposant qu'elles soient branchées à partir d'une base commune). Les développeurs ne veulent pas terminer une fonctionnalité pour en commencer une autre en ayant l'impression que le code qu'ils viennent d'écrire n'existe plus.

  4. Comment éviter de créer des conflits de fusion (à cause du cherry-pick) ?

    Ce qui semble être un moyen sûr de créer un conflit de fusion est de choisir entre les branches, elles ne peuvent jamais être fusionnées à nouveau ? Est-ce que l'application du même commit en revert (comment faire ?) dans l'une ou l'autre branche pourrait résoudre cette situation ? C'est une des raisons pour lesquelles je n'ose pas pousser pour un flux de travail largement basé sur la fusion.

  5. Comment se décomposer en branches topiques ?

    Nous réalisons qu'il serait génial d'assembler une intégration finie à partir de branches de sujets, mais souvent le travail de nos développeurs n'est pas clairement défini (parfois aussi simple que de "fouiner") et si du code a déjà été placé dans un sujet "misc", il ne peut pas en être retiré à nouveau, selon la question ci-dessus ? Comment travaillez-vous avec la définition/approvisionnement/graduation/libération de vos branches de sujet ?

  6. Des procédures appropriées comme la révision du code et la graduation serait bien sûr charmant.

    Mais nous n'arrivons tout simplement pas à démêler les choses pour gérer cela - des suggestions ? branches d'intégration, illustrations ?

Vous trouverez ci-dessous une liste de questions connexes :

Consultez également les articles de Plastic SCM sur développement axé sur les tâches et si le plastique n'est pas votre choix, étudier le modèle de ramification de nvie et son scripts de soutien .

90voto

VonC Points 414372

La caractéristique la plus troublante dont les nouveaux développeurs de DVCS doivent se rendre compte concerne la processus de publication :

  • Vous pouvez importer (récupérer/tirer) n'importe quel dépôt distant dont vous avez besoin.
  • vous pouvez publier (pousser) vers n'importe quel dépôt (nu) que vous voulez

A partir de là, vous pouvez respecter quelques règles pour faciliter vos questions :

Maintenant :

Flux de travail / modèles de branchement :

chaque flux de travail est là pour soutenir un processus de gestion des versions et qui est adapté à chaque projet.
Ce que je peux ajouter au flux de travail que vous mentionnez est que chaque développeur ne devrait pas créer une branche de fonctionnalité, mais seulement une branche "current dev", parce que la vérité est que le développeur ne sait souvent pas ce que sa branche produira exactement : une fonctionnalité, plusieurs (parce qu'elle s'est avérée être une fonctionnalité trop complexe), aucune (parce qu'elle n'est pas prête à temps pour la sortie), une autre fonctionnalité (parce que la première s'est "transformée"),...

Seul un "intégrateur" devrait établir des branches de fonctionnalités officielles sur un dépôt "central", qui peut ensuite être récupéré par les développeurs pour rebaser/fusionner la partie de leur travail qui correspond à cette fonctionnalité.

Fusion et rebasage (historique enchevêtré ou séquentiel) :

J'aime la réponse que vous mentionnez (" Description du flux de travail pour l'utilisation de git pour le développement interne ")

Je recherche un flux de travail naturel :

pour les corrections, il peut être utile d'associer chaque correction à un ticket de suivi de bogue, ce qui aide le développeur à se rappeler où (c'est-à-dire sur quelle branche, c'est-à-dire une branche dédiée "pour les corrections") il/elle doit commettre ces modifications.
Les hooks peuvent alors aider à protéger un repo central contre les poussées de corrections de bogues non validées ou de branches à partir desquelles il ne faut pas pousser. (pas de solution spécifique ici, tout ceci doit être adapté à votre environnement)

Comment éviter de créer des conflits de fusion (à cause du cherry-pick) ?

Comme indiqué par Jakub Narębski sur sa réponse Dans le cas de l'UE, le "cherry picking" devrait être réservé aux rares situations où il est nécessaire.
Si votre configuration implique un grand nombre de choix (c'est-à-dire "ce n'est pas rare"), c'est que quelque chose ne va pas.

Est-ce que l'application du même commit en revert (comment faire ?)

git revert devrait s'en charger, mais ce n'est pas idéal.

Comment se décomposer en branches topiques ?

Tant qu'une branche n'a pas encore été poussée partout, un développeur devrait réorganiser son historique de commits (une fois qu'il/elle voit enfin que le développement prend une forme plus définitive et stable) dans :

  • plusieurs branches si nécessaire (une par caractéristique clairement identifiée)
  • un ensemble cohérent de commits au sein d'une branche (voir Réduire les vérifications de Git )

Des procédures appropriées comme la révision du code et la graduation ?

Les branches d'intégration (dans un repo dédié à l'intégration) peuvent aider le développeur à :

  • rebase son développement sur cette branche d'intégration à distance (pull --rebase)
  • résoudre localement
  • pousser le développement vers ce dépôt
  • vérifier avec l'intégrateur que cela ne donne pas lieu à une pagaille ;)

21voto

Ninefingers Points 18767

Je pense, et je peux me tromper, que l'une des choses les plus mal comprises à propos de git est sa nature distribuée. Cela le rend très différent de subversion, par exemple, dans la façon dont vous pouvez travailler, bien que vous puissiez imiter le comportement de SVN si vous le souhaitez. Le problème est que pratiquement n'importe quel flux de travail fera l'affaire, ce qui est formidable mais aussi trompeur.

Si je comprends bien le développement du noyau (je me concentrerai là-dessus), chacun a son propre dépôt git pour développer le noyau. Il y a un dépôt, linux-2.6.git, géré par Torvalds, qui agit comme le dépôt de version. Les gens clonent à partir d'ici s'ils souhaitent commencer à développer une fonctionnalité par rapport à la branche "release".

D'autres dépôts font du développement. L'idée est de cloner à partir de linux-2.6, de se ramifier autant de fois que vous le souhaitez jusqu'à ce que vous ayez une "nouvelle" fonctionnalité fonctionnelle. Ensuite, lorsque celle-ci est prête, vous pouvez la mettre à disposition de quelqu'un de confiance, qui tirera cette branche de votre dépôt dans le sien et la fusionnera dans le courant principal. Dans le noyau linux, cela se produit à plusieurs niveaux (lieutenants de confiance) jusqu'à ce qu'il atteigne linux-2.6.git, où il devient "le noyau".

Maintenant, c'est là que ça devient confus. Les noms de branches n'ont pas besoin d'être cohérents entre les dépôts. Donc je peux git pull origin master:vanilla-code et obtenir une branche de la origin dans une branche de mon dépôt appelée vanilla-code . Pour autant que je sache ce qui se passe, cela n'a pas vraiment d'importance - il est distribué dans le sens où tous les dépôts sont pairs entre eux et non pas simplement partagés entre plusieurs ordinateurs comme SVN.

Donc, avec tout ça en tête :

  1. Je pense que c'est à chaque programmeur de décider comment il effectue ses branchements. Tout ce dont vous avez besoin est un référentiel central pour gérer les versions, etc. Le tronc pourrait être head . Les versions peuvent être des tags ou des branches et les hotfix sont probablement des branches en elles-mêmes. En fait, je ferais probablement les releases comme des branches pour que vous puissiez garder Parcheando eux.
  2. Je fusionnerais et ne rebaserais pas. Si par exemple vous prenez un dépôt, le clonez, le branchez et faites un peu de développement, puis tirez de votre origin vous devriez, dans votre référentiel, probablement créer une autre branche et fusionner la dernière master en yourbranch afin que quelqu'un d'autre puisse reprendre vos modifications avec le moins d'efforts possible. D'après mon expérience, il est très rarement nécessaire d'effectuer un véritable rebasement.
  3. Je pense qu'il s'agit de comprendre le fonctionnement de Git et ce qu'il peut faire. Cela prend un certain temps et beaucoup de bonne communication - je n'ai vraiment commencé à comprendre ce qui se passe que lorsque j'ai commencé à utiliser git avec d'autres développeurs et même maintenant, il y a des choses dont je ne suis pas sûr.
  4. Les conflits de fusion sont utiles. Je sais, je sais, vous voulez que tout fonctionne, mais le fait est que le code change et que vous devez fusionner les résultats en quelque chose qui fonctionne. Les conflits de fusion ne sont en fait que de la programmation supplémentaire. Je n'ai jamais trouvé d'explication facile sur ce qu'il faut faire à leur sujet, alors la voici : notez les fichiers qui ont des conflits de fusion, allez les changer pour ce qu'ils devraient être, git add . y luego git commit .
  5. Mais cela convient. Comme je l'ai dit, chaque utilisateur dispose de son propre dépôt git pour jouer avec les noms de branches. n'ont pas besoin d'être les mêmes . Si vous aviez un dépôt de transit, par exemple, vous pourriez appliquer un schéma de nommage, mais vous n'avez pas besoin de le faire pour chaque développeur, seulement dans le dépôt de version.
  6. C'est l'étape de la fusion. Vous ne fusionnez avec les branches de la version, etc., que lorsque vous considérez que le code a été revu et a passé les tests de qualité.

J'espère que cela vous aidera. Je réalise que VonC vient de poster une explication très similaire... Je ne peux pas taper assez vite !

Modifier quelques réflexions supplémentaires sur la façon d'utiliser git dans un cadre commercial, car cela semble pertinent pour le PO d'après les commentaires :

  • Le dépôt de la version, nous l'appellerons product.git est accessible par un certain nombre de programmeurs principaux et de techniciens responsables de la gestion du produit lui-même. Ils sont analogues au rôle des mainteneurs dans les logiciels libres.
  • Ces programmeurs dirigent probablement aussi en partie le développement des nouvelles versions, et peuvent donc coder eux-mêmes et maintenir divers dépôts. Ils peuvent gérer des dépôts de transit pour les nouvelles fonctionnalités et peuvent également avoir leurs propres dépôts.
  • En dessous d'eux se trouvent les programmeurs chargés de développer les différents bits. Par exemple, quelqu'un peut être responsable de l'interface utilisateur. Ils gèrent donc le dépôt UI.git.
  • En dessous d'eux se trouvent les programmeurs qui développent les fonctionnalités dans le cadre de leur travail quotidien.

Alors, que se passe-t-il ? Eh bien, tout le monde tire au début de chaque journée de la source "amont", c'est-à-dire le dépôt de la version (qui contient probablement aussi les derniers éléments du développement du jour précédent). Tout le monde fait cela, directement. Cela va aller sur une branche dans leur dépôt, probablement appelée "master" ou peut-être si vous êtes moi appelé "latest". Le programmeur va alors faire un peu de travail. Ce travail peut être quelque chose dont il n'est pas sûr, alors il crée une branche, fait le travail. Si cela ne fonctionne pas, il peut supprimer la branche et revenir en arrière. Si cela fonctionne, ils devront fusionner avec la branche principale sur laquelle ils travaillent actuellement. Nous dirons que c'est un programmeur d'interface utilisateur qui travaille sur latest-ui donc il le fait git checkout latest-ui suivi par git merge abc-ui-mywhizzynewfeature . Il dit ensuite à son responsable technique (le responsable de l'interface utilisateur) : "J'ai accompli une telle tâche, prenez-en de la graine". Le responsable de l'interface utilisateur fait donc git pull user-repo lastest-ui:lastest-ui-suchafeature-abc . Le responsable de l'interface utilisateur l'examine ensuite sur cette branche et dit : "C'est très bien, je vais le fusionner avec la branche de l'interface utilisateur. ui-latest . Il pourrait alors dire à tous ceux qui sont en dessous de lui de s'éloigner de lui sur leur ui-latest ou tout autre nom qu'ils leur ont donné, et ainsi la fonctionnalité est explorée par les développeurs. Si l'équipe est satisfaite, le responsable de l'interface utilisateur peut demander au responsable des tests de s'inspirer de lui et de fusionner les changements. Cela se propage à tout le monde (en aval du changement) qui le teste et soumet des rapports de bogue, etc. Enfin, si la fonctionnalité réussit les tests, etc., l'un des principaux responsables techniques peut la fusionner dans la copie de travail actuelle du programme, et toutes les modifications sont alors propagées en aval. Et ainsi de suite.

Ce n'est pas une méthode de travail "traditionnelle" et elle est conçue pour être "dirigée par les pairs" plutôt que "hiérarchique" comme SVN/CVS. En substance, tout le monde a accès aux commit, mais seulement localement. C'est l'accès au référentiel et le référentiel que vous désignez comme référentiel de publication qui vous permet d'utiliser la hiérarchie.

9voto

John Nilsson Points 4650

Un modèle que j'ai utilisé avec de bons résultats est le suivant.

Un repo "béni" vers lequel tout le monde pousse et tire (en fait, une topologie client-serveur).

Il n'y a pas de branche principale, donc aucun développeur ne peut pousser du code dans la "mainline".

Tous les développements se produisent sur les branches du sujet. Nous avons donné des noms aux branches afin de détecter facilement qui en est responsable : jn/newFeature ou jn/issue-1234.

Il existe également une correspondance presque parfaite entre les branches et les cartes kanban/scrum sur le tableau blanc.

Pour publier une branche, elle est poussée vers le dépôt de référence (repo) et la carte Kanban est déplacée vers " prêt pour révision ".

Si la branche est acceptée par la révision, elle est candidate à la publication.

Une version est créée lorsqu'un ensemble de branches acceptées sont fusionnées et étiquetées avec un numéro de version.

En poussant le nouveau tag vers le repo béni, il y a une nouvelle base possible pour de nouvelles fonctionnalités.

Pour éviter les conflits de fusion, les développeurs sont priés de mettre à jour (fusionner) leurs branches non publiées avec la dernière version.

3voto

Gaurav Kumar Points 173

Jetez un coup d'œil à ce Article étonnant et approfondi qui explique très bien le modèle de branchement de Git.

Nous présentons ici un bref résumé : En gros, vous avez 2 branches principales- master y develop et vous créez de nouvelles branches, au fur et à mesure des besoins, à des fins diverses telles que Feature , Release y Hotfix branches. L'article explique également l'origine de chaque branche et l'endroit où chaque branche doit être fusionnée.

Vous trouverez également quelques bonnes pratiques telles que le balisage de vos communiqués de production et le -no-ff option pour préserver l'histoire locale de la branche.

Référence :

  1. Modèle Git Bracnhing

Git branching model

2voto

xero Points 1449

Personnellement, j'essaie de garder uniquement le code prêt à être publié dans la branche master. Quand je travaille sur une nouvelle fonctionnalité ou une correction de bogue, je le fais dans une branche. Je fais également des tests unitaires dans la branche. Si tout fonctionne bien, ce n'est qu'à ce moment-là que je fusionne/rebase dans master.

J'essaie également d'utiliser des conventions de dénomination communes aux branches, telles que

  • correction de la boucle récursive
  • correction du bugfix/sql_timeout
  • fonctionnalité/new_layout
  • fonctionnalité/recherche avancée

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X