web-dev-qa-db-fra.com

Comment se fait la fusion de git après la sélection de cerises?

Imaginons que nous ayons une branche master.

Ensuite, nous créons un newbranch

git checkout -b newbranch

et effectue deux nouveaux commits vers newbranch: commit1 et commit2

Ensuite, nous passons à master et faisons cherry-pick

git checkout master
git cherry-pick hash_of_commit1

En regardant dans gitk, nous voyons que commit1 et sa version choisie par le cherry ont des hachages différents, donc techniquement ce sont deux commits différents.

Finalement, nous fusionnons newbranch dans master:

git merge newbranch

et voyez que ces deux commits avec des hachages différents ont été fusionnés sans problème bien qu'ils impliquent que les mêmes modifications doivent être appliquées deux fois, de sorte qu'un d'entre eux doit échouer.

Est-ce que git effectue réellement une analyse intelligente du contenu de commit tout en fusionnant et décide que les modifications ne doivent pas être appliquées deux fois ou que ces commits sont marqués en interne comme liés les uns aux autres?

176
Paul

Réponse courte

Ne vous inquiétez pas, Git s'en occupera.

Longue réponse

Contrairement à ex. SVN1, Git ne stocke pas les commits au format delta, mais est basé sur un instantané 2,3. Alors que SVN tenterait naïvement d’appliquer chaque validation fusionnée en tant que correctif (et échouerait, pour la raison exacte que vous avez décrite), Git est généralement capable de gérer ce scénario.

Lors de la fusion, Git essaiera de combiner les instantanés des deux HEAD sera validé dans un nouvel instantané. Si une partie du code ou un fichier est identique dans les deux instantanés (c’est-à-dire qu’un commit était déjà cher) choisi), Git ne le touchera pas.

Sources

1 Skip-Deltas in Subversion
2 bases de Git
3 Le modèle d'objet Git

123
helmbert

Après une telle fusion, vous aurez peut-être deux fois choisi des commits dans l’histoire.

Solution pour éviter cela, je cite article qui recommande les branches avec des commits en double (cherry-pick), utilise rebase avant la fusion:

fusion de git après git cherry-pick: éviter les doublons

Imaginons que nous ayons la branche master et une branche b:

   o---X   <-- master
    \
     b1---b2---b3---b4   <-- b

Maintenant, nous avons un besoin urgent des commits b1 et b3 en master, mais pas des commits restants en b. Donc, ce que nous faisons est de vérifier la branche principale et de sélectionner les commits b1 et b3:

$ git checkout master
$ git cherry-pick "b1's SHA"
$ git cherry-pick "b3's SHA"

Le résultat serait:

   o---X---b1'---b3'   <-- master
    \
     b1---b2---b3---b4   <-- b

Disons que nous faisons un autre engagement sur master et nous obtenons:

   o---X---b1'---b3'---Y   <-- master
    \
     b1---b2---b3---b4   <-- b

Si nous souhaitons maintenant fusionner la branche b en maître:

$ git merge b

Nous aurions ce qui suit:

   o---X---b1'---b3'---Y--- M  <-- master
     \                     /
      b1----b2----b3----b4   <-- b

Cela signifie que les modifications introduites par b1 et b3 apparaissent deux fois dans l'historique. Pour éviter cela, nous pouvons rebaser au lieu de fusionner:

$ git rebase master b

Ce qui donnerait:

   o---X---b1'---b3'---Y   <-- master
                        \
                         b2'---b4'   <-- b

Finalement:

$ git checkout master
$ git merge b

nous donne:

   o---X---b1'---b3'---Y---b2'---b4'   <-- master, b

[~ # ~] éditer [~ # ~] Corrections supposées par le commentaire de David Lemon

35
ephemerr