web-dev-qa-db-fra.com

Quelle est la différence entre 'git merge' et 'git rebase'?

Quelle est la différence entre git merge et git rebase?

463
Daniel Peñalba

Supposons qu’il y avait initialement 3 commits, A, B, C:

A-B-C

Ensuite, le développeur Dan a créé commit D et le développeur Ed a créé commit E:

A-B-C-D-E

De toute évidence, ce conflit devrait être résolu d’une manière ou d’une autre. Pour cela, il y a 2 façons:

FUSION:

A-B-C-D-E-M

Les deux commits D et E sont toujours présents, mais nous créons un commit de fusion M qui hérite des modifications de D et E. Cependant, cela crée un losange , que beaucoup de gens trouvent très déroutant.

REBASE:

A-B-C-D-E-R

Nous créons commit R, dont le contenu du fichier est identique à celui de merge commit M ci-dessus. Mais nous nous débarrassons de commit E, comme il n’a jamais existé (noté par des points - ligne de fuite). En raison de cette suppression, E devrait être local pour le développeur Ed et n'aurait jamais dû être déplacé vers un autre référentiel. L'avantage de rebase est que le diamant est évité, et que l'histoire reste belle ligne droite - la plupart des développeurs adorent ça!

821
mvp

J'aime vraiment cet extrait de 10 choses que je déteste à propos de git (il donne une brève explication de rebase dans son deuxième exemple):

3. documentation de merde

Les pages de manuel sont un tout-puissant "f *** you"1. Ils décrivent les commandes du point de vue d'un informaticien et non d'un utilisateur. Exemple:

git-Push – Update remote refs along with associated objects

Voici une description pour les humains:

git-Push – Upload changes from your local repository into a remote repository

Mise à jour, un autre exemple: (merci cgd)

git-rebase – Forward-port local commits to the updated upstream head

Traduction:

git-rebase – Sequentially regenerate a series of commits so they can be 
             applied directly to the head node

Et puis nous avons

git-merge - Join two or more development histories together

ce qui est une bonne description.


1. non censurée dans l'original

144
mvw

Personnellement, je ne trouve pas la technique standard de création de diagrammes très utile - les flèches semblent toujours indiquer le mauvais sens pour moi. (Ils pointent généralement vers le "parent" de chaque commit, ce qui finit par être en arrière dans le temps, ce qui est étrange).

Pour l'expliquer avec des mots:

  • Lorsque vous rebasez votre branche sur leur branche, vous dites à Git de donner l’impression que vous avez regardé leur branche proprement, puis fait tout votre travail à partir de là. Cela crée un ensemble de modifications simples et conceptuellement simples que quelqu'un peut réviser. Vous pouvez répéter ce processus lorsque de nouvelles modifications sont apportées à leur branche et vous obtiendrez toujours un ensemble propre de modifications "au bout" de leur branche.
  • Lorsque vous fusionnez leur branche dans votre branche, vous associez les historiques des deux branches ensemble à ce stade. Si vous faites cela à nouveau plus tard avec d'autres modifications, vous commencez à créer un fil d'histoires entrelacées: certaines de leurs modifications, certaines de mes modifications, certaines de leurs modifications. Certaines personnes trouvent cela désordonné ou indésirable.

Pour des raisons que je ne comprends pas, les outils d'interface graphique de Git n'ont jamais fait beaucoup d'efforts pour présenter les historiques de fusion plus clairement, en résumant les fusions individuelles. Donc, si vous voulez un "historique propre", vous devez utiliser rebase.

Je semble me souvenir d’avoir lu des articles de blog de programmeurs qui seulement utilisent rebase et d’autres qui jamais utilisent rebase.

Exemple

Je vais essayer d'expliquer cela avec un exemple juste. Supposons que d'autres personnes de votre projet travaillent sur l'interface utilisateur et que vous rédigiez de la documentation. Sans rebase, votre historique pourrait ressembler à quelque chose comme:

Write tutorial
Merge remote-tracking branch 'Origin/master' into fixdocs
Bigger buttons
Drop down list
Extend README
Merge remote-tracking branch 'Origin/master' into fixdocs
Make window larger
Fix a mistake in howto.md

Autrement dit, les fusions et les validations d’UI se situent au milieu des validations de votre documentation.

Si vous rebasez votre code sur master au lieu de le fusionner, cela ressemblerait à ceci:

Write tutorial
Extend README
Fix a mistake in howto.md
Bigger buttons
Drop down list
Make window larger

Tous vos commits sont en haut (les plus récents), suivis du reste de la branche master.

( Disclaimer: Je suis l'auteur du message "10 choses que je déteste à propos de Git" mentionné dans une autre réponse )

115
Steve Bennett

Bien que la réponse acceptée et la plus votée soit excellente, je trouve également utile d'essayer d'expliquer la différence uniquement par des mots:

fusionner

  • “Ok, nous avons deux états développés différemment de notre référentiel. Fusionnons-les ensemble. Deux parents, un enfant résultant. "

rebase

  • “Confiez les modifications de la branche principale (quel que soit son nom) à ma branche principale. Faites-le en prétendant que mon travail sur les longs métrages a commencé plus tard, en fait sur l'état actuel de la branche principale. "
  • "Réécrivez l'historique de mes modifications pour refléter cela." (nécessité de forcer-Push, car le versionnage concerne normalement et non la modification de l'historique donné) =
  • "Probablement - si les changements que j'ai apportés ont peu à voir avec mon travail - l'histoire ne changera pas beaucoup, si je regarde mes commits diff par diff (vous pouvez aussi penser à des" correctifs ")."

summary: Lorsque cela est possible, rebase est presque toujours préférable. Faciliter la réintégration dans la branche principale.

Parce que? Work votre travail de fonctionnalité peut être présenté comme n gros 'fichier de correctif' (diff aussi) en ce qui concerne la branche principale, sans avoir à 'expliquer' plusieurs parents: au moins deux, venant d'une fusion, mais probablement beaucoup plus, s'il y avait plusieurs fusions. Contrairement aux fusions, les répétitions multiples ne s'additionnent pas. (autre atout majeur)

38
Frank Nocke

Git Rebase est plus proche d'une fusion. La différence de rebase est la suivante:

  • les commits locaux sont supprimés temporairement de la branche.
  • courir le git pull
  • insérez à nouveau tous vos commits locaux.

Cela signifie donc que tous vos commits locaux sont déplacés à la fin, après tous les commits distants. Si vous avez un conflit de fusion, vous devez le résoudre aussi.

14
Willem Franco

Pour faciliter la compréhension peut voir ma figure.

Rebase changera le commit de hachage, donc si vous voulez éviter beaucoup de conflits, utilisez simplement rebase lorsque cette branche est terminée/complète de manière stable.

enter image description here

5
Nhan Cao