Quand dois-je utiliser git pull --rebase?

806

Je connais certaines personnes qui utilisent git pull --rebasepar défaut et d'autres qui insistent pour ne jamais l'utiliser. Je crois que je comprends la différence entre fusionner et rebaser, mais j'essaie de mettre cela dans le contexte de git pull. S'agit-il simplement de ne pas vouloir voir beaucoup de messages de validation de fusion, ou y a-t-il d'autres problèmes?

Jason Baker
la source
1
Source pour les personnes déconseillant git pull --rebase? Rebase ou git rebase est une activité distincte de git pull --rebase!
przemo_li

Réponses:

584

Vous devez utiliser git pull --rebaselorsque

  • vos modifications ne méritent pas une branche distincte

En effet - pourquoi pas alors? C'est plus clair et n'impose pas de regroupement logique à vos commits.


Ok, je suppose qu'il a besoin de quelques éclaircissements. Dans Git, comme vous le savez probablement, vous êtes encouragé à créer des succursales et à fusionner. Votre branche locale, dans laquelle vous tirez les modifications, et la branche distante sont, en fait, des branches différentes, et il git pulls'agit de les fusionner. C'est raisonnable, car vous ne poussez pas très souvent et accumulez généralement un certain nombre de modifications avant qu'elles ne constituent une fonctionnalité terminée.

Cependant, parfois - pour quelque raison que ce soit - vous pensez qu'il serait en fait préférable que ces deux - distant et local - soient une seule branche. Comme dans SVN. C'est ici git pull --rebasequ'intervient le jeu. Vous ne fusionnez plus - vous vous engagez réellement au-dessus de la branche distante . C'est de cela qu'il s'agit réellement.

Que ce soit dangereux ou non est la question de savoir si vous traitez les succursales locales et distantes comme une chose inséparable. Parfois, c'est raisonnable (lorsque vos modifications sont petites, ou si vous êtes au début d'un développement robuste, lorsque des modifications importantes sont apportées par de petits commits). Parfois, ce n'est pas le cas (lorsque vous créez normalement une autre branche, mais que vous êtes trop paresseux pour le faire). Mais c'est une question différente.

P Shved
la source
17
Je pense que c'est utile lorsque vous travaillez sur la même branche, mais vous pouvez changer votre poste de travail. J'ai tendance à valider et à pousser mes modifications d'un poste de travail, puis à tirer le rebase dans l'autre, et à continuer à travailler sur la même branche.
Pablo Pazos
11
Il est préférable de configurer Git pour rebaser automatiquement lors de l'extraction avec git config --global pull.rebase preserve (préserver dit en plus d'activer le rebasage, pour essayer de conserver les fusions si vous en avez fait localement).
Colin D Bennett
2
Je ne suis pas d'accord pour que vous ne deviez utiliser pull --rebase que lorsque vous travaillez sur une branche. Vous devez l'utiliser tout le temps, sauf si cela est impossible en raison d'une autre circonstance.
Tomáš Fejfar
@P Shved ... 'Cependant, parfois - pour quelque raison que ce soit - vous pensez qu'il serait en fait préférable que ces deux - distants et locaux - soient une seule branche' '... cela peut-il être fait? qu'en environnement local, je peux avoir ma branche et un miroir de branche distant comme origine / maître. Pouvez-vous s'il vous plaît fournir des entrées ici?
Mandroid
736

Je voudrais apporter une perspective différente sur ce que signifie réellement «git pull --rebase», car il semble parfois se perdre.

Si vous avez déjà utilisé Subversion (ou CVS), vous pouvez être habitué au comportement de "svn update". Si vous avez des modifications à valider et que la validation échoue parce que des modifications ont été apportées en amont, vous "mettez à jour svn". Subversion procède en fusionnant les modifications en amont avec les vôtres, ce qui peut entraîner des conflits.

Ce que Subversion vient de faire, c'était essentiellement du «pull --rebase». Le fait de reformuler vos modifications locales pour qu'elles soient relatives à la version la plus récente en est la partie "rebasage". Si vous aviez fait "svn diff" avant la tentative de validation échouée et comparez le diff résultant avec la sortie de "svn diff" après, la différence entre les deux diff est ce que l'opération de rebasage a fait.

La différence majeure entre Git et Subversion dans ce cas est que dans Subversion, "vos" modifications n'existent qu'en tant que modifications non validées dans votre copie de travail, tandis que dans Git vous avez des validations réelles localement. En d'autres termes, dans Git, vous avez bifurqué l'histoire; votre histoire et l'histoire en amont ont divergé, mais vous avez un ancêtre commun.

À mon avis, dans le cas normal d'avoir votre branche locale reflète simplement la branche en amont et en faire un développement continu sur elle, la bonne chose à faire est toujours « --rebase », parce que c'est ce que vous sémantiquement réellement faites . Vous et d'autres piratez l'histoire linéaire voulue d'une branche. Le fait que quelqu'un d'autre ait poussé légèrement avant votre tentative de poussée n'est pas pertinent, et il semble contre-productif que chaque accident de ce type entraîne des fusions dans l'histoire.

Si vous ressentez réellement le besoin que quelque chose soit une succursale pour une raison quelconque, c'est une préoccupation différente à mon avis. Mais à moins que vous n'ayez un désir spécifique et actif de représenter vos modifications sous la forme d'une fusion, le comportement par défaut devrait, à mon avis, être "git pull --rebase".

Veuillez considérer d'autres personnes qui ont besoin d'observer et de comprendre l'histoire de votre projet. Voulez-vous que l'histoire soit jonchée de centaines de fusions partout, ou voulez-vous seulement les quelques fusions sélectionnées qui représentent de véritables fusions d'efforts de développement divergents intentionnels?

scode
la source
18
@MarceloCantos Pour être clair, je ne dis pas que git (l'outil) devrait par défaut rebaser. Ce serait dangereux puisqu'un rebase détruit essentiellement l'histoire. Je dis qu'en termes de flux de travail, lorsque vous n'avez pas l'intention de créer une branche et que vous piratez simplement une branche sur laquelle d'autres personnes travaillent également, "git pull --rebase" devrait être le comportement par défaut de l'utilisateur.
scode
1
Voulez-vous dire que l'on ne devrait pas git config --global branch.autosetupmerge always?
Marcelo Cantos du
9
@MarceloCantos Non, je ne le suis pas;) Personnellement, je laisserais la configuration automatique comme valeur par défaut (si je fusionne en arrière et en quatrième entre les branches autres que la télécommande locale <->, j'aime que ce soit explicite). Je dis simplement qu'en tant qu'être humain, j'utilise toujours "git pull --rebase" dans le cadre de mon flux de travail normal "saisir la dernière dans la branche principale", car je ne veux jamais créer de validation de fusion à moins que je ne crée explicitement une branche.
scode
9
+1 @scode. Après de nombreuses heures douloureuses à lutter avec la question de rebase / fusion, voici enfin une réponse qui résout le problème .
AgileYogi
10
Cette réponse n'est qu'une tentative d'adapter les utilisateurs de systèmes de contrôle de version non distribués à Git au lieu de leur donner une chance de bien comprendre les avantages d'avoir des branches appropriées.
Alexey Zimarev
211

Peut-être que la meilleure façon de l'expliquer est avec un exemple:

  1. Alice crée la branche thématique A et y travaille
  2. Bob crée une branche de sujet indépendante B et y travaille
  3. Alice le fait git checkout master && git pull. Le Maître est déjà à jour.
  4. Bob le fait git checkout master && git pull. Le Maître est déjà à jour.
  5. Alice fait git merge topic-branch-A
  6. Bob fait git merge topic-branch-B
  7. Bob fait git push origin masteravant Alice
  8. Alice le fait git push origin master, ce qui est rejeté car il ne s'agit pas d'une fusion rapide.
  9. Alice regarde le journal d'origine / maître et constate que la validation n'est pas liée au sien.
  10. Alice fait git pull --rebase origin master
  11. La validation de fusion d'Alice est déroulée, la validation de Bob est extraite et la validation d'Alice est appliquée après la validation de Bob.
  12. Alice le fait git push origin master, et tout le monde est heureux de ne pas avoir à lire un commit de fusion inutile lorsqu'ils consulteront les journaux à l'avenir.

Notez que la branche spécifique fusionnée n'est pas pertinente pour l'exemple. Dans cet exemple, Master pourrait tout aussi bien être une branche de publication ou une branche de développement. Le point clé est qu'Alice & Bob fusionnent simultanément leurs branches locales en une branche distante partagée.

Cody Poll
la source
2
Agréable. J'ai tendance à être explicite et à git co master && git pull; git checkout topic-branch-A; git rebase master; git checkout master; git merge topic-branch-A; git push origin masterrépéter si la poussée d'un autre à maîtriser s'est produite avant la mienne. Bien que je puisse voir les avantages succincts de votre recette.
HankCa
Belle explication @Cody Poll
Rajanikanta Pradhan
148

Je pense que vous devriez utiliser git pull --rebaselorsque vous collaborez avec d'autres sur la même branche. Vous êtes dans votre travail → validation → travail → cycle de validation, et lorsque vous décidez de pousser votre travail, votre poussée est rejetée, car il y a eu un travail parallèle sur la même branche. À ce stade, je fais toujours un pull --rebase. Je n'utilise pas de squash (pour aplatir les commits), mais je rebase pour éviter les commits de fusion supplémentaires.

Au fur et à mesure que votre connaissance de Git augmente, vous vous retrouvez beaucoup plus dans l'histoire qu'avec n'importe quel autre système de contrôle de version que j'ai utilisé. Si vous avez une tonne de petits commits de fusion, il est facile de perdre de vue la vue d'ensemble qui se passe dans votre histoire.

C'est en fait la seule fois où je rebase (*), et le reste de mon flux de travail est basé sur la fusion. Mais aussi longtemps que vos committers les plus fréquents le font, l'histoire semble bien meilleure à la fin.

(*) Pendant que j'enseignais un cours Git, un étudiant m'a arrêté à ce sujet, car j'ai également préconisé le rebasage des branches de fonctionnalités dans certaines circonstances. Et il avait lu cette réponse;) Un tel changement de base est également possible, mais il doit toujours être conforme à un système pré-arrangé / convenu, et en tant que tel ne devrait pas "toujours" être appliqué. Et à ce moment-là, je ne fais généralement pas non pull --rebaseplus, ce qui est la question;)

krosenvold
la source
2
on peut sûrement écrire un script pour cacher les
validations de
3
Les fusions peuvent également contenir des différences, ce qui signifie que ce n'est pas tout à fait trivial
krosenvold
9
@hasen j Oui, mais le CONTENU de ces fusions peut être important
krosenvold
Cette réponse est vague et opiniâtre par rapport à la réponse choisie: qu'entendez-vous exactement par "même branche"? Il y a cependant de bons points qui ne sont pas dans la réponse choisie.
iwein
1
Le flou autour de la "branche" est assez intentionnel, car il existe de nombreuses façons d'utiliser les références; «ligne de travail» n'est qu'une option.
krosenvold
49

Je ne pense pas qu'il y ait jamais de raison de ne pas utiliser pull --rebase- j'ai ajouté du code à Git spécifiquement pour permettre à ma git pullcommande de toujours rebaser contre les commits en amont.

Lorsque vous parcourez l'histoire, il n'est tout simplement jamais intéressant de savoir quand le gars / la fille travaillant sur la fonctionnalité s'est arrêté pour se synchroniser. Cela pourrait être utile pour le gars / la fille pendant qu'il / elle le fait, mais c'est pour ça reflog. C'est juste ajouter du bruit pour tout le monde.

Dustin
la source
2
"Quand on regarde l'histoire, il n'est tout simplement jamais intéressant de savoir quand le gars qui travaille sur la fonctionnalité s'est arrêté pour se synchroniser." / mais cela ne signifie-t-il pas que ces validations intermédiaires sont probablement des versions cassées?
eglasius
10
Oui, et ce n'est pas non plus un "État entier". C'est pourquoi nous n'en voulons pas. Je veux savoir ce qu'il voulait, pas comment il y est arrivé.
Dustin
4
Si pull --rebasedoit toujours être utilisé, pourquoi ne le pullfait-il pas par défaut?
straya
2
Je crains que vous n'ayez à vous faire votre propre opinion. J'ai plusieurs choses en moi .gitconfigpour que certaines des options fassent ce qu'il faut. Je pense que git rebase fait la mauvaise chose par défaut, tout comme git tag, etc ... Si vous n'êtes pas d'accord, vous n'avez pas besoin de justifier votre opinion.
Dustin
8
Cela semble un bon conseil si vous tirez de "l'amont", disons de master, et si la branche dans laquelle vous vous arrêtez n'est pas encore devenue publique. Si vous tirez d'autre part d'une branche de fonctionnalité dans masterc'est plus comme l'inverse: il n'y a jamais de raison d'utiliser --rebase, non? C'est peut-être la raison pour laquelle ce n'est pas par défaut. J'ai trouvé que 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. derekgourlay.com/blog/git-when-to-merge-vs-when-to-rebase
jolvi
38

Rappelez-vous juste:

  • pull = fetch + merge
  • pull --rebase = fetch + rebase

Alors, choisissez la façon dont vous voulez gérer votre branche.

Vous feriez mieux de connaître la différence entre fusionner et rebaser :)

leohxj
la source
9

Je pense que cela se résume à une préférence personnelle.

Voulez-vous cacher vos erreurs idiotes avant de pousser vos changements? Si oui, git pull --rebasec'est parfait. Il vous permet de compresser ultérieurement vos commits en quelques (ou un) commits. Si vous avez fusionné dans votre historique (non poussé), il n'est pas si facile d'en faire un git rebaseplus tard.

Personnellement, cela ne me dérange pas de publier toutes mes erreurs stupides, j'ai donc tendance à fusionner au lieu de rebaser.

hasen
la source
8
Remarque pour tous ceux qui consultent cette question: cette réponse est complètement hors de propos à la question "quand dois-je utiliser git pull --rebase?"
therealklanni
3
@therealklanni J'ai édité la réponse pour que la pertinence de la question soit clairement expliquée (j'espère sans détruire l'intention).
Paŭlo Ebermann
Partager un journal de travail sale et non structuré n'est pas une entreprise honnête, c'est juste de la paresse. Vous perdez du temps en faisant en sorte qu'ils vous poursuivent à travers votre trou de lapin de développement et de débogage; donnez-leur le résultat, pas les divagations.
krystah
8

git pull --rebasepeut masquer la réécriture d'un historique à un collaborateur git push --force. Je recommande de n'utiliser git pull --rebase que si vous savez que vous avez oublié de pousser vos commits avant que quelqu'un d'autre ne fasse de même.

Si vous n'avez rien commis, mais votre espace de travail n'est pas propre, juste git stashavant git pull. De cette façon, vous ne réécrivez pas en silence votre historique (ce qui pourrait supprimer en silence une partie de votre travail).

Habax
la source