Git Cherry-pick vs Merge Workflow
en supposant que je suis le mainteneur d'une pension, et je veux tirer dans les changements d'un contributeur, il y a quelques workflows possibles:
- I
cherry-pick
chaque commit depuis la télécommande (dans l'ordre). Dans ce cas, git enregistre la propagation sans lien avec la branche distante. - je
merge
la branche, en tirant dans tous les changements, et l'ajout d'un nouveau "conflit" commit (si nécessaire). - I
merge
chaque la branche distante individuellement (encore une fois dans l'ordre), permettant d'enregistrer les conflits pour chaque propagation, au lieu de les regrouper tous en un seul. - pour être complet, vous pouvez faire un
rebase
(même quecherry-pick
option?), mais je crois comprendre que cela peut être source de confusion pour le donateur. Peut-être que ça élimine l'option 1.
dans les deux cas 2 et 3, git enregistre l'historique de la branche des commits, contrairement à 1.
Quels sont les avantages et les inconvénients entre l'utilisation des méthodes cherry-pick
ou merge
décrites? ma compréhension est que la méthode 2 est la norme, mais je pense que la résolution d'un grand commit avec un seul "conflit" Fusion, n'est pas la solution la plus propre.
3 réponses
les deux rebase
(et cherry-pick
) et merge
ont leurs avantages et inconvénients. Je plaide pour merge
ici, mais ça vaut la peine de comprendre les deux. (Voir ici pour une alternative, bien argumentée réponse énumérant les cas où rebase
est préférable.)
merge
est préférable à cherry-pick
et rebase
pour plusieurs raisons.
- Robustesse . L'identifiant SHA1 d'une commit l'identifie non seulement en lui-même mais aussi par rapport à toutes les autres commits qui le précèdent. Cela vous offre la garantie que L'état du dépôt à 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 qui corrompt ou détourne votre dépôt. Vous pouvez choisir dans les changements individuels et ils sont même, mais vous n'avez aucune garantie. (Le mineur comme une question secondaire de la nouvelle cerise cueillies s'engage prendra de l'espace supplémentaire si quelqu'un d'autre à la cerise se ramasse dans la même livraison, ils seront tous deux présents dans l'histoire, même si vos copies de travail finissent par être identiques.)
- facilité d'utilisation . Les gens ont tendance à comprendre le flux de travail
merge
assez facilement.rebase
tend à être considéré comme plus avancé. Il est préférable de comprendre les deux, mais les gens qui ne veulent pas être des experts dans le contrôle de version (qui dans mon expérience a inclus De nombreux collègues qui sont sacrément bons à ce qu'ils font, mais ne veulent pas passer le temps supplémentaire) ont un temps plus facile juste la fusion.
même avec une fusion-flux de travail lourd rebase
et cherry-pick
sont encore utiles pour des cas particuliers:
- un des inconvénients de
merge
est l'histoire encombrée.rebase
empêche une longue série de commits d'être dispersés dans votre histoire, comme ils le seraient si vous périodiquement fusionné à d'autres changements. C'est en fait son principal objectif que je l'utilise. Ce que vous voulez être très prudent de, n'est jamaisrebase
code que vous avez partagé avec d'autres dépôts. Une fois qu'un commit estpush
ed quelqu'un d'autre pourrait avoir commis sur elle, et rebaser sera au mieux cause du type de duplication discuté ci-dessus. Au pire, vous pouvez vous retrouver avec un un dépôt très confus et des erreurs subtiles il vous faudra beaucoup de temps pour les débusquer. -
cherry-pick
est utile pour échantillonner un petit sous-ensemble de changements d'une branche de sujet que vous avez essentiellement décidé de jeter, mais réalisé qu'il ya un couple de pièces utiles sur.
quant à la préférence de fusionner plusieurs changements plutôt qu'un seul: c'est juste beaucoup plus simple. Il peut devenir très fastidieux de faire des fusions de changesets individuels une fois que vous commencez à avoir beaucoup d'entre eux. La résolution de fusion dans git (et dans Mercurial, et dans Bazaar) est très bonne. Vous ne rencontrerez pas de problèmes majeurs en fusionnant même les longues branches la plupart du temps. Je fusionne généralement tout en une seule fois et seulement si je reçois un grand nombre de conflits que je sauvegarder et relancer la fusion au coup par coup. Même alors, je n'en gros morceaux. Comme un exemple très réel, j'ai eu un collègue qui avait 3 mois de changements à fusionner, et a obtenu quelque 9000 conflits dans 250000 ligne base de code. Ce que nous avons fait pour corriger est de faire la fusion un mois de valeur à la fois: les conflits ne s'accumulent pas de façon linéaire, et le faire en morceaux résulte en loin moins de 9000 conflits. Il avait encore beaucoup de travail, mais pas autant que d'essayer de faire un commit à la fois.
à mon avis, la cueillette de cerises devrait être réservée à des situations rares où elle est nécessaire, par exemple si vous avez fait quelques fixations directement sur la branche 'master' (tronc, branche principale de développement) et que vous avez ensuite réalisé qu'elle devrait être appliquée aussi à 'maint'. Vous devez baser le flux de travail soit sur la fusion, soit sur rebase (ou "git pull --rebase").
s'il vous Plaît rappelez-vous que la cerise cueillies ou relocalisée commettre est différents du point de vue de Git (a différent de L'identifiant SHA-1) que l'original, il est donc différent de la propagation dans le dépôt distant. (Rebase peut généralement gérer cela, car il vérifie le patch id, c'est-à-dire les modifications, pas un commit id).
aussi dans git vous pouvez fusionner plusieurs branches à la fois: ainsi appelé Octopus merge . Notez que octopus merge doit réussir sans conflits. Néanmoins, il pourrait être utile.
HTH.
Rebase et Cherry-pick est le seul moyen de garder propre l'histoire de commit. Évitez d'utiliser la fusion et évitez de créer un conflit de fusion. Si vous utilisez gerrit, définissez un projet pour fusionner si nécessaire et un projet pour choisir le mode et essayer vous-même.