45 votes

Quelle est la différence entre `git fetch` puis `git rebase`, et `git pull --rebase` ?

En lisant le git pull la page, il donne cet avertissement sévère sur git pull --rebase :

Il s'agit d'un mode de fonctionnement potentiellement dangereux. Il réécrit l'histoire, ce qui n'est pas de bon augure lorsque vous avez déjà publié cette histoire. N'utilisez pas cette option si vous n'avez pas lu attentivement git-rebase(1).

Dans le git rebase Elle donne beaucoup de descriptions mais aucun avertissement de ce type.

De plus, j'ai vu certaines personnes dire que

git fetch
git rebase

est la même chose que

git pull --rebase

tandis que d'autres disent qu'ils légèrement différent.

Quelle est la vérité ?

1 votes

Un très bon livre sur git que vous devriez garder sous votre oreiller. progit.org

0 votes

L'avertissement sur le git pull donne l'impression que les choses peuvent déraper assez facilement. Mais la description dans le livre donne l'impression qu'il faut faire un effort pour foirer le rebasage.

0 votes

Ce que j'ai fini par faire régulièrement est d'utiliser git fetch pour mettre à jour ma vue du dépôt distant, puis en regardant l'historique tiré vers le bas et en décidant ce que je veux faire. (En général, je fais suivre cette opération d'un git rebase .)

45voto

Adam Spiers Points 4193

La vérité est qu'ils SONT différent. Voici une page web très utile qui l'explique parfaitement :

http://gitolite.com/git-pull--rebase.html

Alors git pull --rebase a une certaine magie par rapport à git fetch; git rebase La plupart du temps, vous ne le remarquerez pas, mais dans les cas où le mainteneur amont a méchamment ignoré tous ces avertissements sévères et a décidé de réécrire l'histoire d'une branche publique, il peut vraiment aider en consultant votre reflog local et en effectuant la rebase locale d'une manière plus intelligente.

Cela dit, il s'agit toujours d'un rebasement, donc vous réécrivez toujours l'histoire ! Par conséquent, toutes les mises en garde standard s'appliquent toujours. Mais si vous travaillez sur une branche privée (c'est-à-dire non publiée), alors c'est OK.

Je vais en dire un peu plus sur les avertissements sévères. Ils sont valables, mais personnellement, je trouve que la plupart des gens sont un peu trop paranoïaque sur le rebasement, comme un git rebase s'est glissé dans leur chambre au milieu de la nuit quand ils étaient jeunes et a mangé leur soeur ou quelque chose comme ça. Ça ne devrait vraiment pas être si effrayant :

  • si c'est une branche privée, rebasez à votre guise
  • s'il s'agit d'une branche publique, ne rebasez pas à moins de vraiment Si vous n'êtes pas obligé de le faire, et si vous le faites, assurez-vous d'en comprendre l'impact et veillez à ce que toute personne susceptible d'être touchée soit correctement informée de ce que vous avez fait, afin qu'elle n'ait pas de mauvaise surprise et ne perde pas un temps fou à comprendre ce qui s'est passé.

C'est aussi simple que cela. Et oui, j'irais même jusqu'à encourager activement les gens à régulièrement git rebase -i sur leurs branches privées. Polir l'histoire avant de la pousser vers un endroit public/en amont est une bonne chose parce que personne n'a envie de parcourir l'historique d'un projet qui est rempli de commits du type 'oops, correction d'une erreur que j'ai faite il y a 3 commits'. (OTOH, ne soyez pas totalement obsédés par le rebasement en quête d'un historique sans faille. Nous sommes humains. Nous faisons des erreurs. Faites avec).

Une dernière observation concernant le git pull --rebase la magie. Si la branche publique amont a été rebasée de manière sensée (par exemple, en corrigeant des commits ou en abandonnant des commits qui n'auraient pas dû être placés là), la magie opère en votre faveur. Cependant, si le rebasement en amont a accidentellement abandonné commits, alors la magie vous empêchera silencieusement de les remettre. Dans ce cas, si vous voulez remettre ces commits abandonnés, vous devriez plutôt utiliser git fetch; git rebase .

34voto

Seth Robertson Points 13276

La règle avec Git est que vous ne devriez jamais essayer de modifier l'historique après qu'il ait été partagé, publié ou poussé. Vous pouvez le faire, bien sûr, si vous le voulez vraiment et si vous avez les permissions suffisantes, mais cela doit être fait avec beaucoup de précaution car cela peut perturber d'autres personnes.

Heureusement, lorsque vous avez un déploiement Git typique avec un seul dépôt amont (origine) qui est la source de tout ce qui est bon et vrai dans l'univers, vous pouvez utiliser git pull --rebase à votre guise, ce sera parfaitement sûr et, à mon avis, cela vous donnera une histoire beaucoup plus saine (c'est-à-dire linéaire). Mon équipe et moi-même l'utilisons en permanence.

Cependant, si vous commencez à avoir plusieurs télécommandes et à faire git pull --rebase <arguments> afin que vous ne fassiez plus de rebasement sur la même cible à chaque fois, ou commencez à pousser votre branche vers des dépôts alternatifs. avant en cours d'exécution git pull --rebase avec votre primaire en amont - alors vous pouvez commencer à avoir des problèmes.

Chaque fois que vous partagez vos modifications avec un autre dépôt distant et que vous modifiez ensuite ces modifications (pour des valeurs de modification égales à la modification du SHA, du parent, etc. même si le message/contenu du commit n'a pas changé), vous pouvez perturber la personne qui avait les anciennes modifications.

Tant que vous ne sortez pas de l'enveloppe de bon sens de la base, git pull --rebase sera très bon pour vous.

Cela, err, ne répond pas à la question sur la différence entre git pull --rebase y git fetch && git rebase @{u} . Je me contenterai de dire que je n'ai pas conscience d'une quelconque différence et que, s'il y en a une, elle est suffisamment subtile pour que je ne la remarque pas depuis que j'utilise Git. Peut-être dans le fait que le système détermine le dépôt correct que votre branche doit récupérer si vous avez plusieurs dépôts et que "origin" n'est pas l'amont de cette branche ?

Et même si vous vous trompez avec git-rebase, vous pouvez bien sûr revenir à votre environnement original pré-rebase facilement avec git log -g et/ou git reset --hard ORIG_HEAD . Évitez simplement de faire des poussées forcées (interdites par défaut dans presque tous les serveurs Git), et vous serez heureux.

EDITED

Avec le temps, ma compréhension s'est élargie. git pull --rebase appelle git rebase pour faire le travail de rebasement, donc dans ce sens il n'y a pas de différence entre eux. Cependant, git-pull appelle en fait git rebase --onto @{u} $(git merge-base HEAD @{u}@{1})

D'accord, cette syntaxe ("@{u}@{1}") est peut-être un peu opaque et est en plus une simplification, mais le fait est qu'elle permet de savoir quelle était la base de fusion en amont. AVANT il a lancé la commande fetch. Quelle différence cela fait-il, demandez-vous ?

Eh bien, dans le cas normal, aucune. Cependant, si vous changez l'endroit vers lequel upstream pointe ou si upstream lui-même a été rebasé, pas mal de choses. Si upstream a été réécrit et que vous avez ensuite fait un git rebase @{u} vous pourriez être très malheureux et obtenir des doubles-commits ou des conflits selon le degré de réécriture des anciens commits.

Cependant, avec la magie derrière git pull --rebase seuls les commits qui sont les vôtres et uniquement les vôtres seront appliqués au-dessus de @{u}.

OK, ceci trop est une simplification. Si upstream fait un rebasement en commençant par les 100 commits précédents (mais il y a en fait 101+ commits dans l'historique) y vous avez fait un git fetch avant faire un git pull --rebase alors Git ne sera pas en mesure de déterminer avec précision quelle était la base de fusion historique appropriée pour déterminer quels sont vos commits locaux.

Le résultat est le suivant , git fetch est considéré comme nuisible (lorsque vous avez des commits locaux et que l'amont est réécrit). Cependant, la véritable règle d'or est de "ne jamais tenter de modifier l'histoire après qu'elle ait été partagée, publiée ou poussée", et c'est là que j'ai commencé.

TL;DR :

git fetch est considéré comme nuisible (utilisez donc git pull --rebase ) ; et n'essayez jamais de modifier l'historique après qu'il ait été partagé, publié ou poussé (parce que, entre autres, cela entraînerait git fetch pour être nuisible).

0 votes

TL;DR (peut-être que les réponses aux questions sont enfouies là-dedans mais je ne le saurai jamais :)

0 votes

@RickO'Shea : Ajouté un TL;DR juste pour vous .

1 votes

TLDR est faux : git fetch ne peut pas être nuisible ! Il ne fait rien d'autre que de récupérer de nouveaux objets à distance. Elle ne modifie en aucune façon l'état de la caisse locale ou des branches locales.

-6voto

Rick O'Shea Points 15

En plus de la mise à jour de votre branche locale à partir de sa branche de suivi à distance, le programme -pull met à jour les fichiers de votre espace de travail.

Donc c'est probablement plus typique de git pull --rebase (ou configurer pull pour utiliser rebase par défaut) que de git fetch; git rebase .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X