Que signifie choisir un commit avec Git?


2340

Récemment, on m'a demandé de cherry-pickvalider.

Alors, que signifie choisir un commit dans git? Comment faites-vous?


13
Au lieu de fusionner, il est plus facile de recommencer à partir d'une branche vers la branche cible (ex: master).
Levent Divilioglu

Réponses:


2859

Cherry picking dans Git signifie choisir un commit dans une branche et l'appliquer sur une autre.

Ceci est en contraste avec d'autres manières telles que mergeet rebasequi appliquent normalement de nombreux commits sur une autre branche.

  1. Assurez-vous que vous êtes sur la branche à laquelle vous souhaitez appliquer le commit.

    git checkout master
    
  2. Exécutez ce qui suit:

    git cherry-pick <commit-hash>
    

NB:

  1. Si vous choisissez parmi une branche publique, vous devriez envisager d'utiliser

    git cherry-pick -x <commit-hash>
    

    Cela générera un message de validation standardisé. De cette façon, vous (et vos collègues) pouvez toujours garder une trace de l'origine du commit et éviter à l'avenir des conflits de fusion.

  2. Si vous avez des notes attachées au commit, elles ne suivent pas la sélection. Pour les amener également, vous devez utiliser:

    git notes copy <from> <to>
    

Liens supplémentaires:


247
Si vous choisissez parmi une branche publique, vous devriez envisager d'utiliser git cherry-pick -x <commit-hash>. Cela générera un message de validation standardisé. De cette façon, vous (et vos collègues) pouvez toujours garder une trace de l'origine du commit et éviter à l'avenir des conflits de fusion.
MBober

2
La cueillette des cerises est-elle vraiment nécessaire? Une réinitialisation mixte ou une réinitialisation logicielle ne fera-t-elle pas un travail similaire?
Nav

10
Notez que si vous avez des notes attachées au commit, elles ne suivent pas la sélection. Vous devez également les utiliser git notes copy <from> <to>.
Zitrax

5
git push est la dernière étape pour apporter des modifications au master
sentir bien et programmer le

58
Pour votre information: Une livraison contient sémantiquement tous les fichiers de l'arborescence de travail de ce moment (et commit hachage de la précédente livraison ), de sorte que vous ne demandez pas l' ensemble engager à un autre engagement, mais les changements un commettras fait sur la précédente livraison "cherry-pick commit applies the changes introduced by the named commit on the current branch"plus ppl a tendance à considérer le commit comme des changements (comme svn était iirc), mais ce n'est pas le cas, chaque commit fait référence à l'arborescence de travail complète. Bien que cela ne fasse aucune différence dans ce cas, cela peut aider à comprendre pourquoi git fonctionne comme il le fait.
Emile Vrijdags

314

Cette citation est tirée de; Contrôle de version avec Git (livre vraiment génial, je vous encourage à l'acheter si vous êtes intéressé par git)

Edit: Étant donné que cette réponse fait toujours bonne impression, je voudrais ajouter un très joli didacticiel vidéo en action à ce sujet:

Youtube: Introduction à Git Cherry-Pick

Utilisation de git cherry-pick La commande git cherry-pick commit applique les changements introduits par le commit nommé sur la branche courante. Il introduira un nouveau commit distinct. À strictement parler, l'utilisation de git cherry-pick ne modifie pas l'historique existant dans un référentiel; au lieu de cela, il ajoute à l'histoire. Comme pour les autres opérations Git qui introduisent des modifications via le processus d'application d'un diff, vous devrez peut-être résoudre les conflits pour appliquer pleinement les modifications de la validation donnée . La commande git cherry-pick est généralement utilisée pour introduire des validations particulières d'une branche dans un référentiel sur une branche différente. Une utilisation courante consiste à transmettre ou à rétrospecter les commits d'une branche de maintenance à une branche de développement.

$ git checkout rel_2.3
$ git cherry-pick dev~2 # commit F, above

avant: avant

après: après


12
lorsque des commits triés sur le volet sont pris sur une branche (b1) et livrés ultérieurement au maître. Et si la branche b1 (à partir de laquelle les validations ont été initialement sélectionnées) est également tentée d'être livrée au maître. Et les conflits? Est-ce pris en charge ou comment ça marche?
parasrish

3
@parasrish Oui, ils sont déjà pris en charge lors de vos précédentes fusions. Vous avez donc modifié a, b, c, d à partir de la branche (b1). Vous n'avez choisi que "c". Ensuite, à l'avenir, une fois que vous aurez fusionné de (b1) à master, puisque les changements "c" sont les mêmes, il ne fera que fusionner a, b, d et restera les changements "c". Mais si vous annulez votre fusion, vous reviendrez aux modifications avec "c" dedans. Vous devrez les restaurer séparément.
Teoman shipahi

12
Il convient de souligner: dans l'exemple donné, seule la différence (F - E) est appliquée à Z. C'est un cas étroit. Cherry-pick peut être utilisé pour appliquer les différences de plusieurs validations, disons, toutes les différences entre deux validations non adjacentes. Par exemple, en partant du dessus, (F - E), (E - D), (D - C) et (C - B). Cela revient à appliquer la différence (F - B).
Thomas Bitonti

2
De plus, que se passe-t-il si la validation sélectionnée (F dans l'exemple) a plusieurs prédécesseurs immédiats?
Thomas Bitonti

2
@ j2emanue en d'autres termes, cherry-pick n'acceptera que les changements de last-commit. Si vous vous engagez 3 fois différents, et si vous choisissez la dernière, il n'y aura pas de modifications sur les premier et deuxième commit. La commande Fusionner prendra toutes vos modifications et s'appliquera à votre branche cible (maître).
Teoman shipahi

157

La sélection de cerises dans Git est conçue pour appliquer une validation d'une branche à une autre. Cela peut être fait si vous par exemple. fait une erreur et commis un changement dans une mauvaise branche, mais ne souhaitez pas fusionner la branche entière. Vous pouvez simplement par exemple. annuler le commit et le sélectionner sur une autre branche.

Pour l'utiliser, vous avez juste besoin git cherry-pick hash, où hashest un hachage de validation d'une autre branche.

Pour la procédure complète, voir: http://technosophos.com/2009/12/04/git-cherry-picking-move-small-code-patches-across-branches.html


96

Petit exemple de situation, lorsque vous avez besoin d'un choix de cerise

Envisagez le scénario suivant. Vous avez deux branches.

a) release1 - Cette branche va à votre client, mais il y a encore quelques bugs à corriger.

b) master - Branche master classique, où vous pouvez par exemple ajouter des fonctionnalités pour release2.

MAINTENANT : Vous réparer quelque chose dans RELEASE1 . Bien sûr, vous avez également besoin de ce correctif dans Master . Et c'est un cas d'utilisation typique pour la cueillette des cerises. Donc, cerise sur le gâteau dans ce scénario signifie que vous prenez un commit de la branche release1 et que vous l'incluez dans la branche master .


3
Vous pourriez avoir juste besoin de l'autre sens. Vous avez corrigé un bogue dans master et vous devriez choisir celui à libérer1. Ils peuvent également être des référentiels plutôt que des succursales
canbax

1
Pourquoi ne pas utiliser la fusion pour cela?
FreeLightman

Je voudrais: créer une branche hors version, la corriger dans la branche, fusionner la branche dans la version, fusionner la version dans le maître.
Jasper-M

57

cherry-pick est une fonctionnalité de Git. Si quelqu'un veut valider des validations spécifiques dans une branche vers une branche cible, alors le choix de cerise est utilisé.
Les étapes de git cherry-pick sont les suivantes.

  1. extraire (basculer vers) la branche cible.
  2. git cherry-pick <commit id>
    

    Ici, l'ID de validation est l'ID d'activité d'une autre branche.

    git cherry-pick 9772dd546a3609b06f84b680340fb84c5463264f
    
  3. pousser vers la branche cible

Visitez https://git-scm.com/docs/git-cherry-pick


44

J'ai préparé des illustrations étape par étape de ce que fait la sélection de cerises - et une animation de ces illustrations (vers la fin).

  1. Avant la cueillette des cerises
    (nous allons faire un sélection du commit Lde la branche feature): entrez la description de l'image ici

  1. Démarrage de la commande git cherry-pick feature~2
    ( feature~2est le 2 e commit avant
    feature, c'est-à-dire le commit L): entrez la description de l'image ici

  1. Après avoir exécuté la commande ( git cherry-pick feature~2): entrez la description de l'image ici

Le même animé: entrez la description de l'image ici


Remarque:

Le commit L'est du point de vue de l'utilisateur (commit = snapshot) la copie exacte du commitL .

Techniquement (en interne), il s'agit d'un nouveau commit différent (car par exemple Lcontient un pointeur vers K(comme son parent), tandis qu'il L'contient un pointeur vers E).


Est-ce à dire que L 'sera N -> M -> L sur le maître de branche? ou il apportera exclusivement commit L sur la branche principale
Priyank Thakkar

1
@PriyankThakkar, oui, exclusivement L , rien d'autre (comme vous pouvez le voir sur les photos / animations).
MarianD

22

Vous pouvez penser si un choix de cerise ressemble à un rebase, ou plutôt il est géré comme un rebase. Par cela, je veux dire qu'il prend un commit existant et le régénère en prenant, comme point de départ, le chef de la branche sur laquelle vous vous trouvez actuellement.

A rebaseprend un commit qui avait un parent X et régénère le commit comme s'il avait réellement un parent Y, et c'est précisément ce que cherry-pickfait a.

Le choix de cerise est plus sur la façon dont vous sélectionnez les commits. Avec pull(rebase), git régénère implicitement vos commits locaux en plus de ce qui est tiré dans votre branche, mais aveccherry-pick vous choisissez explicitement des validations, et régénérez-les implicitement au-dessus de votre branche actuelle.

Donc, la façon dont vous le faites diffère, mais sous le capot, ce sont des opérations très similaires - la régénération des commits.


1
Je trouve que c'est une vue assez utile des choses. Cela implique pourquoi cherry-pickse comporte comme il le fait lorsque la branche cible est fusionnée par la suite dans la branche source. Merci Monsieur.
Aluan Haddad

3
J'aimerais utiliser Cherry Pick au lieu de Git Merge après la fin d'une fonctionnalité. tout le monde fait toujours fusionner feature_branch quand ils ont terminé une fonctionnalité. pourquoi ne pas utiliser la commande cherry-pick? avez-vous des idées? pourquoi s'embêter à écraser si je peux faire le choix
j2emanue

11

C'est un peu comme copier (de quelque part) et coller (vers quelque part), mais pour des commits spécifiques.

Si vous souhaitez effectuer un correctif, par exemple, vous pouvez utiliser la cherry-pickfonction.

Faites votre cherry-pickdans une branche de développement et mergeengagez-vous dans une branche de publication. De même, effectuez une opération cherry-pickdepuis une branche de publication vers master. Voila


11

Lorsque vous travaillez avec une équipe de développeurs sur un projet, la gestion des changements entre plusieurs branches git peut devenir une tâche complexe. Parfois, vous ne voulez pas fusionner une branche entière dans une autre et vous n'avez qu'à choisir un ou deux commits spécifiques. Ce processus est appelé «cueillette des cerises».

Trouvé un excellent article sur la cueillette des cerises, consultez-le pour plus de détails: https://www.previousnext.com.au/blog/intro-cherry-picking-git


7

Si vous souhaitez fusionner sans ID de validation, vous pouvez utiliser cette commande

git cherry-pick master~2 master~0

La commande ci-dessus fusionnera les trois derniers commits de master de 1 à 3

Si vous voulez le faire pour un commit unique, supprimez simplement la dernière option

git cherry-pick master~2

De cette façon, vous fusionnerez le 3e commit à partir de la fin du master.


Ceci est déroutant. Je pense que vous êtes ici sur une branche autre que maître, non? Et lorsque vous avez mentionné deux validations, vous faites référence aux validations <from> et <to> pour définir la plage que vous souhaitez sélectionner. Correct? Il serait très utile que le scénario soit décrit. Bon ajout cependant. Merci.
Saurabh Patil

6

Il appliquera un commit particulier à votre branche actuelle.

Ça signifie :

  • tous les fichiers ajoutés par ce commit seront ajoutés
  • tous les fichiers supprimés par ce commit seront supprimés
  • tous les fichiers modifiés par ce commit seront fusionnés. Cela signifie que le fichier entier de la validation, pas seulement les modifications de cette validation!

Ex: pensez à valider A

added newFileA
modified main:
+ import './newFileA'

commit B

added newFileB
modified main:
+ import './newFileB'

Si vous choisissez le commit B sur une autre branche, vous vous retrouverez avec:

/newFileB
/main :
   import './newFileA'
   import './newFileB'

puisque la validation B contient newFileB et main , mais pas de newFileA , ce qui entraîne un bogue, donc utilisez-le avec prudence.


0

Extrait des documents officiels:

Étant donné une ou plusieurs validations existantes, appliquez le changement que chacune introduit, en enregistrant une nouvelle validation pour chacune. Cela nécessite que votre arborescence de travail soit propre (aucune modification de la validation HEAD).

Lorsqu'il n'est pas évident de savoir comment appliquer une modification, les événements suivants se produisent:

  1. La branche actuelle et le pointeur HEAD restent sur la dernière validation effectuée avec succès.

  2. La référence CHERRY_PICK_HEAD est définie pour pointer sur la validation qui a introduit la modification difficile à appliquer.

  3. Les chemins dans lesquels la modification appliquée proprement sont mis à jour à la fois dans le fichier d'index et dans votre arborescence de travail.

  4. Pour les chemins conflictuels, le fichier d'index enregistre jusqu'à trois versions, comme décrit dans la section "TRUE MERGE" de git-merge. Les fichiers de l'arborescence de travail comprendront une description du conflit entre crochets par les marqueurs de conflit habituels <<<<<<< et >>>>>>>.

Aucune autre modification n'est apportée.

Lire la suite...

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.