Différence entre git pull et git pull --rebase

311

J'ai commencé à utiliser git il y a quelque temps et je ne comprends pas bien les subtilités. Ma question fondamentale ici est de découvrir la différence entre a git pullet git pull --rebase, car l'ajout de l' --rebaseoption ne semble pas faire quelque chose de très différent: fait juste un pull.

Veuillez m'aider à comprendre la différence.

Rndm
la source
3
Copie
TJ
Lien utile
Taras Melnyk

Réponses:

326

git pull= git fetch+ git mergecontre le suivi de la branche amont

git pull --rebase= git fetch+ git rebasecontre le suivi de la branche amont

Si vous voulez savoir comment git mergeet git rebasedifférez, lire .

mvp
la source
12
Il vaut la peine de noter que dire git pull --rebaseest la même chose git fetchet git rebaseest fondamentalement comment c'est, mais ce n'est pas exactement sémantiquement équivalent. Il existe certaines différences, dont certaines sont expliquées ici. gitolite.com/git-pull--rebase
w0rp
8
C'est ce que j'appellerais un «mensonge commode», pour emprunter une phrase à Scott Meyers. C'est un bon moyen de l'expliquer malgré tout.
w0rp
Très brièvement. Je ne peux pas comprendre la différence. Qu'est-ce qui est si important fetch?
Vert
240

Parfois, nous avons un amont qui a rebasé / rembobiné une branche dont nous dépendons. Cela peut être un gros problème - provoquant des conflits désordonnés pour nous si nous sommes en aval.

La magie est git pull --rebase

Un git pull normal est, en gros, quelque chose comme ça (nous utiliserons une télécommande appelée origine et une branche appelée foo dans tous ces exemples):

# assume current checked out branch is "foo"
git fetch origin
git merge origin/foo

À première vue, vous pourriez penser qu'un git pull --rebase fait exactement cela:

git fetch origin
git rebase origin/foo

Mais cela n'aidera pas si le rebase en amont impliquait un "écrasement" (ce qui signifie que les patch-id des commits ont changé, pas seulement leur ordre).

Ce qui signifie que git pull --rebase doit faire un peu plus que cela. Voici une explication de ce qu'il fait et comment.

Disons que votre point de départ est le suivant:

a---b---c---d---e  (origin/foo) (also your local "foo")

Le temps passe et vous avez fait quelques commits en plus de votre propre "foo":

a---b---c---d---e---p---q---r (foo)

Pendant ce temps, dans une crise de rage antisociale, le mainteneur en amont a non seulement rebasé son "foo", il a même utilisé une ou deux courges. Sa chaîne de validation ressemble maintenant à ceci:

a---b+c---d+e---f  (origin/foo)

Un git pull à ce stade entraînerait le chaos. Même un git fetch; git rebase origin / foo ne le couperait pas, car les commits "b" et "c" d'un côté, et le commit "b + c" de l'autre, seraient en conflit. (Et de même avec d, e et d + e).

Qu'est git pull --rebase- ce que, dans ce cas, c'est:

git fetch origin
git rebase --onto origin/foo e foo

Cela vous donne:

 a---b+c---d+e---f---p'---q'---r' (foo)

Vous pouvez toujours avoir des conflits, mais ce seront de véritables conflits (entre p / q / r et a / b + c / d + e / f), et non des conflits causés par b / c en conflit avec b + c, etc.

Réponse tirée de (et légèrement modifiée):
http://gitolite.com/git-pull--rebase

Mauri Lopez
la source
9
C'est la meilleure réponse. Vous souhaiterez peut-être modifier le résultat final a---b+c---d+e---f---p'---q'---r' (foo)car le rebase change les hachages.
Bastien
22
Cette réponse a été copiée et collée mot pour mot à partir de gitolite.com/git-pull--rebase et doit inclure l'attribution par la licence sur cette page.
Wildcard
Ceci est une excellente explication. Mais j'ai eu une situation, où j'avais commis A, et j'ai envoyé un PR au repo en amont qui a été accepté. Ensuite, quand j'ai fait git pull --rebasecontre le dépôt en amont, je n'ai pas obtenu de nouveau A'commit au-dessus du dépôt en amont tiré. En fait, il n'en A'existait pas du tout. Est-ce parce que Ale système a été fusionné? Ou est-ce parce qu'il n'y avait pas de différence entre l'amont et ma version rebasée?
CMCDragonkai
Je suis en train de parcourir le didacticiel Git et j'utilisais cette réponse pour mieux comprendre a git pull --rebase. Mais une chose qui m'embrouille dans cette situation hypothétique est que le mainteneur en amont a modifié l'historique du projet qui a déjà été intégré dans les référentiels du développeur local. N'est-ce pas simplement une mauvaise pratique en général? S'il voulait écraser l'historique des validations / réécritures, cela aurait dû être fait avant de l'intégrer dans le référentiel central pour éviter ce type de conflits.
bmcentee148
44

Supposons que vous ayez deux validations dans la branche locale:

      D---E master
     /
A---B---C---F origin/master

Après "git pull", ce sera:

      D--------E  
     /          \
A---B---C---F----G   master, origin/master

Après "git pull --rebase", il n'y aura plus de point de fusion G. Notez que D et E deviennent des commits différents:

A---B---C---F---D'---E'   master, origin/master
Deqing
la source
1
n'est-ce pas A --- B --- C --- D '--- E' - F?
prgmrDev
5
@prgmrDev Pourquoi D et E seraient-ils insérés avant F?
Jon
1
N'est-ce pas exactement ce que git rebasefait? Mais nous parlons git pull --rebase. Et ce sont des choses différentes.
Vert
10

Dans le cas le plus simple d'absence de collision

  • avec rebase: rebase vos validations locales sur le dessus de HEAD distant et ne crée pas de fusion / validation de fusion
  • sans / normal: fusionne et crée un commit de fusion

Voir également:

man git-pull

Plus précisément, git pull exécute git fetch avec les paramètres donnés et appelle git merge pour fusionner les têtes de branche récupérées dans la branche actuelle. Avec --rebase, il exécute git rebase au lieu de git merge.

Voir aussi:
Quand dois-je utiliser git pull --rebase?
http://git-scm.com/book/en/Git-Branching-Rebasing

drahnr
la source
3
Et en cas de collisions?
Rndm
1
On vous demandera de les résoudre manuellement puis - continuez avec rebase: git sdd modified-file; git rebase --continueou fusionnez: git add modified-file; git commit;modified-fileest votre fichier local que vous avez modifié manuellement / mergetool
drahnr
Qu'est-ce qui est si spécial fetch? Pourquoi ont-ils créé deux rebaseflux? 1) git rebaseet 2) git pull --rebase?
Vert
7

Pour cela, il est important de comprendre la différence entre fusionner et rebaser.

Les rebases sont la façon dont les changements doivent passer du haut de la hiérarchie vers le bas et les fusions sont la façon dont ils remontent.

Pour plus de détails, consultez - http://www.derekgourlay.com/archives/428

Sagar Mody
la source
Je pense que votre réponse offre une explication beaucoup plus simple qui n'est pas évidente dans le reste des réponses ci-dessus. Merci.
Aaron C