Git Cherry-pick vs Merge Workflow

302

En supposant que je suis le responsable d'un dépôt et que je souhaite retirer des modifications d'un contributeur, il existe quelques flux de travail possibles:

  1. Je cherry-pickm'engage chacun à distance (dans l'ordre). Dans ce cas, git enregistre la validation comme indépendante de la branche distante.
  2. Je mergebranche, en tirant toutes les modifications et en ajoutant un nouveau commit "conflit" (si nécessaire).
  3. Je mergevalide individuellement chacun de la branche distante (encore une fois dans l'ordre), permettant aux conflits d'être enregistrés pour chaque validation, au lieu d'être regroupés en un seul.
  4. Pour être complet, vous pouvez faire une rebase(même chose que l' cherry-pickoption?), Mais je crois comprendre que cela peut créer de la confusion pour le contributeur. Peut-être que cela élimine l'option 1.

Dans les deux cas 2 et 3, git enregistre l'historique des branches des validations, contrairement à 1.

Quels sont les avantages et les inconvénients entre l'utilisation de l'une cherry-pickou l' autre des mergeméthodes décrites? D'après ce que je comprends, la méthode 2 est la norme, mais je pense que résoudre un gros commit avec une seule fusion "conflictuelle" n'est pas la solution la plus claire.

cmcginty
la source

Réponses:

297

Les deux rebase(et cherry-pick) mergeont leurs avantages et leurs inconvénients. Je plaide pour mergeici, mais cela vaut la peine de comprendre les deux. (Recherchez ici une autre réponse bien argumentée énumérant les cas où cela rebaseest préférable.)

mergeest préférable à cherry-picket rebasepour plusieurs raisons.

  1. Robustesse . L'identifiant SHA1 d'un commit l'identifie non seulement en lui-même mais également par rapport à tous les autres commits qui le précèdent. Cela vous offre une garantie que l'état du référentiel à un SHA1 donné est identique pour tous les clones. Il n'y a (en théorie) aucune chance que quelqu'un ait fait ce qui ressemble au même changement, mais qu'il corrompe ou détourne votre référentiel. Vous pouvez choisir parmi les modifications individuelles et elles sont probablement les mêmes, mais vous n'avez aucune garantie. (En tant que problème secondaire mineur, les nouveaux commits sélectionnés par les cerises prendront de l'espace supplémentaire si quelqu'un d'autre sélectionne par les cerises dans le même commit, car ils seront tous deux présents dans l'historique même si vos copies de travail finissent par être identiques.)
  2. Facilité d'utilisation . Les gens ont tendance à comprendre mergeassez facilement le flux de travail. rebasea tendance à être considéré comme plus avancé. Il est préférable de comprendre les deux, mais les personnes qui ne veulent pas être des experts en contrôle de version (ce qui, selon mon expérience, a inclus de nombreux collègues qui sont sacrément bons dans ce qu'ils font, mais ne veulent pas passer du temps supplémentaire) ont plus facilement le temps fusionnant.

Même avec un workflow lourd de fusion rebaseet cherry-picksont toujours utiles dans des cas particuliers:

  1. Un inconvénient mergeest l'histoire encombrée. rebaseempêche une longue série de commits d'être dispersés dans votre histoire, comme ils le seraient si vous fusionniez périodiquement dans les changements des autres. C'est en fait son objectif principal lorsque je l'utilise. Ce que vous voulez faire très attention, ce n'est jamais rebasecoder que vous avez partagé avec d'autres référentiels. Une fois la validation effectuée, pushquelqu'un d'autre aurait pu commettre dessus, et le rebasage entraînerait au mieux le type de duplication décrit ci-dessus. Au pire, vous pouvez vous retrouver avec un référentiel très confus et des erreurs subtiles qu'il vous faudra beaucoup de temps pour dénicher.
  2. cherry-pick est utile pour échantillonner un petit sous-ensemble de modifications à partir d'une branche de sujet que vous avez décidé de supprimer, mais vous avez réalisé qu'il y a quelques éléments utiles.

Quant à préférer la fusion de nombreux changements à un seul: c'est juste beaucoup plus simple. Il peut être très fastidieux de fusionner des ensembles de modifications individuels une fois que vous en avez beaucoup. La résolution de fusion dans git (et dans Mercurial et dans Bazaar) est très très bonne. Vous ne rencontrerez pas de problèmes majeurs lors de la fusion de branches même longues la plupart du temps. Je fusionne généralement tout en une seule fois et ce n'est que si j'obtiens un grand nombre de conflits que je sauvegarde et réexécute la fusion au coup par coup. Même alors, je le fais en gros morceaux. Comme exemple très réel, j'ai eu un collègue qui avait 3 mois de modifications à fusionner, et a obtenu quelque 9000 conflits dans 250000 lignes de code. Ce que nous avons fait de fixer est faire la fusion d' un mois de la valeur d'à la fois: les conflits ne construisent pas de façon linéaire, et de faire en morceaux dans les résultats bienmoins de 9 000 conflits. C'était encore beaucoup de travail, mais pas autant que d'essayer de le faire un commit à la fois.

quark
la source
1
En fait, en théorie, il y a une chance que Mallory puisse corrompre votre référentiel en créant des commits avec le même contenu SHA1 mais différent, cela n'arrivera probablement jamais dans la pratique. :)
Bombe
1
Ha :) Je voulais dire "en théorie, les chances sont si faibles que vous pouvez compter sur le fait que cela ne se produise pas", mais vous avez raison de dire que c'est à l'envers.
quark
Que pensez-vous de "merge --squash"?
cmcginty
@Bombe Si Mallory veut réussir, elle devra construire spécifiquement le commit d'origine et le second commit avec le même SHA1. Une autre question pourrait donc être: quelles sont les chances que deux (un peu) faux engagements apparaissent et que vous ne remarquiez pas? ;)
João Portela
64
9000 conflits? Je quitterais mon travail et deviendrais apiculteur.
Sebastian Patten
95

À mon avis, la sélection des cerises devrait être réservée aux rares situations où elle est requise, par exemple si vous avez effectué une correction directement sur la branche `` principale '' (tronc, branche principale de développement) et que vous vous êtes ensuite rendu compte qu'elle devrait également être appliquée à `` maint '. Vous devez baser le workflow soit sur la fusion, soit sur le rebase (ou "git pull --rebase").

N'oubliez pas que la validation sélectionnée ou rebasée est différente du point de vue de Git (a un identifiant SHA-1 différent) de l'original, elle est donc différente de la validation dans le référentiel distant. (Rebase peut généralement gérer cela, car il vérifie l'ID du patch, c'est-à-dire les modifications, pas un ID de validation).

Également dans git, vous pouvez fusionner de nombreuses branches à la fois: ce que l'on appelle la fusion des poulpes . Notez que la fusion de poulpe doit réussir sans conflits. Cela pourrait néanmoins être utile.

HTH.

Jakub Narębski
la source
19
+1 pour le point que rebase / picking "copie" les commits et perd donc le lien avec le commit d'origine.
studgeek
1
Nous utilisons la sélection de cerises de cette manière, exclusivement pour déplacer les commits de corrections de bugs (peut-être des fonctionnalités TRÈS PETITES) dans une branche de version existante pour préparer un patch. Les fonctionnalités qui s'étendent sur plusieurs validations justifient généralement d'entrer dans une branche de publication basée sur le maître.
foxxtrot
3
@foxxtrot: Une autre solution consiste à créer une branche distincte pour un correctif de bogue, basée sur le plus ancien commit qui présente ce bogue, et à le fusionner dans 'maint' et dans 'master' ... bien que dans ce cas, vous devez savoir que ledit correctif de bogue s'applique aux deux branches.
Jakub Narębski
4
@Jakub Deux commandes indispensables pour créer et fusionner une branche de correction de git blamebogues : pour trouver le commit qui a introduit le bogue, et git branch --containspour déterminer où fusionner la branche. Décrit plus en détail dans cet article
gcbenison
-10

Rebase et Cherry-pick sont le seul moyen de conserver l'historique des validations. Évitez d'utiliser la fusion et évitez de créer un conflit de fusion. Si vous utilisez gerrit, définissez un projet sur Fusionner si nécessaire et un projet sur le mode de sélection et essayez vous-même.

Nagaraj Magadum
la source
pas clair du tout comment cela répond à la question, peut-être que quelques exemples apporteraient un peu de lumière.
Adrian Nasui
1
Le fait que votre histoire semble droite ne signifie pas qu'elle serait plus facile à comprendre.
nicolimo86
La fusion est la façon habituelle d'avoir une histoire propre. Cherry-pick and rebase est principalement utilisé dans les situations où vous devez modifier l'historique. Ce qui signifie que la fusion devrait toujours être le premier choix. Parce que rebaser le comit modifié est ce qui est très dangereux lorsque vous travaillez avec des télécommandes et plusieurs personnes.
Radon8472
Ce gars ici mérite une médaille. Il sait qu'il continuera à être rejeté, mais c'est la bonne réponse. Gloire.
PW Kad
Désolé, je n'ai pas vu ces commentaires jusqu'à présent, veuillez l'essayer dans votre environnement de test avant de conclure et faites ce qui fonctionne pour vous! J'ai environ 600 développeurs contribuant à plusieurs branches de produits, peu importe ce que font les développeurs dans cet espace de travail local, lorsqu'un changement est soumis pour intégration, il devrait être possible de choisir la branche de développement ou parfois de publier ou de corriger une branche de correction de bogues. Pour info ... J'utilise Gerrit.
Nagaraj Magadum