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

499

Quelle est la différence entre git mergeet git rebase?

Daniel Peñalba
la source
14
puisque ma réponse a été supprimée, visitez ce lien pour obtenir la bonne réponse à cette question: git-scm.com/book/en/Git-Branching-Rebasing#The-Basic-Rebase
HiB
6
Au fait, j'ajouterai ce site. Tout ce que vous devez savoir sur git learn en jouant: pcottle.github.io/learnGitBranching
Rollyng
Lisez d'abord ceci: git-scm.com/book/en/v2/… Ensuite: git-scm.com/book/en/v2/Git-Branching-Rebasing Vous comprendrez vraiment.
Liber

Réponses:

867

Supposons que l' origine il y avait 3 commits, A, B, C:

abc

Ensuite, le développeur Dan a créé la validation Det le développeur Ed a créé la validation E:

ABCDE

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

MERGE :

ABCDEM

Les deux validations Det Esont toujours là, mais nous créons une validation de fusion Mqui hérite des modifications des deux Det E. Cependant, cela crée une forme de diamant , ce que beaucoup de gens trouvent très déroutant.

REBASE :

ABCDER

Nous créons un commit R, dont le contenu réel du fichier est identique à celui du commit de fusion Mci-dessus. Mais, nous nous débarrassons du commit E, comme il n'a jamais existé (indiqué par des points - ligne de fuite). En raison de cette oblitération, Edevrait être local pour le développeur Ed et n'aurait jamais dû être poussé vers un autre référentiel. L'avantage du rebase est que la forme de diamant est évitée et que l'histoire reste belle en ligne droite - la plupart des développeurs adorent ça!

mvp
la source
53
Belles illustrations. Cependant, je ne suis pas entièrement d'accord avec le ton positif que le rebase est géré. Dans les deux fusionner et rebaser des conflits peuvent se produire qui nécessitent une résolution manuelle. Et comme toujours lorsque les programmeurs sont impliqués, il y a un risque non négligeable d'erreurs aka bugs. Si une erreur de fusion se produit, toute l'équipe ou la communauté peut voir la fusion et vérifier si un bogue y a été introduit. L'histoire du rebase reste dans le repo d'un développeur et même là, il n'a qu'une durée de vie limitée dans le reflog. Cela pourrait sembler plus joli, mais personne d'autre ne peut voir aussi facilement ce qui s'est mal passé.
Uwe Geuder
> "Cependant, cela crée une forme de diamant, ce que beaucoup de gens trouvent très déroutant." Um ... pouvez-vous élaborer?
Greg Maletic
@GregMaletic: La forme du diamant est une histoire non linéaire. Je ne sais pas pour vous, mais je n'aime pas les choses non linéaires en général. Cela dit, vous pouvez utiliser la fusion avec des diamants si vous le préférez vraiment - personne ne vous force.
mvp
1
Bien que cette réponse soit extrêmement utile, il serait préférable que vous ajoutiez des commandes git réelles avec de simples fichiers foo.txt pour les reproduire localement. Comme l'a dit le dernier utilisateur, il n'est pas évident de savoir qui fait le rebase.
Vortex
1
@pferrel: Je ne pense pas que vous l'ayez correctement compris. git mergen'entrelace pas les commits (mais cela peut apparaître ainsi en regardant git log). Au lieu de cela, git mergeconserve les deux histoires de développement de Dan et Ed intactes, comme cela a été vu de chaque point de vue à la fois. git rebasedonne l'impression que Dan y a travaillé en premier, et Ed l'a suivi. Dans les deux cas (fusion et rebase), l'arborescence de fichiers résultante réelle est absolument identique.
mvp
158

J'adore 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 merdique

Les pages de manuel sont un tout-puissant «f *** you» 1 . Ils décrivent les commandes du point de vue d'un informaticien, pas d'un utilisateur. Exemple concret:

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é dans l'original

mvw
la source
Le problème n'est pas la langue ou si l'utilisateur est un informaticien ou non. Si le reformuler d'une autre manière aide à clarifier les fins (c'est-à-dire ce qui se passe), il ne parvient pas à expliquer les moyens (comment cela se produit). Git nécessite de comprendre les moyens pour comprendre les fins. C'est précisément comprendre les moyens qui rendent Git si difficile. En tant qu'outil, quelque chose utilisé pour simplifier ou réduire l'effort requis dans la tâche, Git échoue horriblement. Malheureusement, trop de développeurs ne le réalisent pas.
ATL_DEV
128

Personnellement, je ne trouve pas la technique de diagramme standard 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, qui finit par être en arrière dans le temps, ce qui est bizarre).

Pour l'expliquer avec des mots:

  • Lorsque vous rebasez votre branche sur sa branche, vous dites à Git de donner l' impression que vous avez bien extrait sa branche, puis avez fait tout votre travail à partir de là. Cela fait un ensemble de changements propre et conceptuellement simple que quelqu'un peut examiner. Vous pouvez répéter ce processus à nouveau lorsqu'il y a de nouveaux changements sur leur branche, et vous vous retrouverez toujours avec un ensemble propre de changements "sur la pointe" de leur branche.
  • Lorsque vous fusionnez leur branche dans votre branche, vous liez les deux historiques de branche ensemble à ce stade. Si vous recommencez plus tard avec plus de changements, vous commencez à créer un fil d'histoires entrelacées: certains de leurs changements, certains de mes changements, certains de leurs changements. Certaines personnes trouvent cela désordonné ou indésirable.

Pour des raisons que je ne comprends pas, les outils GUI pour Git n'ont jamais fait beaucoup d'efforts pour présenter les histoires de fusion plus proprement, en faisant abstraction des fusions individuelles. Donc, si vous voulez un "historique propre", vous devez utiliser le rebase.

Je me souviens d' avoir lu les messages du blog de programmeurs qui n'utilisent rebasage et d' autres qui n'utilisent rebasage.

Exemple

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

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 de l'interface utilisateur au milieu de vos validations de documentation.

Si vous rebasiez 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 masterbranche.

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

Steve Bennett
la source
42

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

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

rebaser

  • «Donnez les modifications de la branche principale (quel que soit son nom) à ma branche de fonctionnalité. 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." (besoin de les forcer, car normalement le versioning consiste à ne pas altérer l'historique donné)
  • "Probablement - si les changements que j'ai ratifiés ont peu à voir avec mon travail - l'histoire ne changera pas grand-chose, si je regarde mes commits diff par diff (vous pouvez aussi penser à des" patchs ")."

résumé: Lorsque cela est possible, le rebasage est presque toujours meilleur. Faciliter la réintégration dans la branche principale.

Parce que? Work votre travail de fonctionnalité peut être présenté comme un gros `` fichier patch '' (alias diff) en ce qui concerne la branche principale, sans avoir à `` expliquer '' plusieurs parents: au moins deux, provenant d'une fusion, mais probablement beaucoup plus, s'il y a étaient plusieurs fusions. Contrairement aux fusions, plusieurs rebases ne s'additionnent pas. (un autre gros avantage)

Frank Nocke
la source
18

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

  • les commits locaux sont supprimés temporairement de la branche.
  • exécuter le git pull
  • réinsérez tous vos commits locaux.

Cela signifie donc que toutes vos validations locales sont déplacées à la fin, après toutes les validations distantes. Si vous avez un conflit de fusion, vous devez également le résoudre.

Willem Franco
la source
7

Pour une compréhension facile peut voir ma figure.

Rebase changera le hachage de validation, de sorte que si vous voulez éviter beaucoup de conflits, utilisez simplement rebase lorsque cette branche est terminée / terminée comme stable.

entrez la description de l'image ici

Nhan Cao
la source
0

J'ai trouvé un article vraiment intéressant sur git rebase vs merge , j'ai pensé le partager ici

  • Si vous voulez voir l'historique complètement comme il s'est produit, vous devez utiliser la fusion. La fusion préserve l'historique tandis que le rebase le réécrit.
  • La fusion ajoute un nouveau commit à votre historique
  • Le rebasage est préférable pour rationaliser un historique complexe, vous pouvez modifier l'historique de validation par rebase interactif.
nagendra547
la source