Comprendre et mémoriser les paramètres de rebase de git

12

Jusqu'à présent, la partie la plus déroutante de git rebase sur une autre branche. Plus précisément, ce sont les arguments de ligne de commande qui prêtent à confusion.

Chaque fois que je veux rebaser un petit morceau d'une branche sur la pointe d'une autre, je dois revoir la documentation de git rebase et cela me prend environ 5-10 minutes pour comprendre ce que chacun des 3 principaux arguments devrait être.

git rebase <upstream> <branch> --onto <newbase>

Quelle est la bonne règle de base pour m'aider à mémoriser à quoi chacun de ces 3 paramètres doit être réglé, compte tenu de tout type de rebase sur une autre branche?

Gardez à l'esprit que j'ai parcouru la documentation de git-rebase encore et encore, encore et encore et encore (et encore), mais c'est toujours difficile à comprendre (comme un livre blanc scientifique ennuyeux ou quelque chose). Donc, à ce stade, je sens que je dois impliquer d'autres personnes pour m'aider à le comprendre.

Mon objectif est de ne jamais avoir à consulter la documentation de ces paramètres de base. Je n'ai pas pu les mémoriser jusqu'à présent, et j'ai déjà fait une tonne de rebases. Il est donc un peu inhabituel que j'ai pu mémoriser toutes les autres commandes et ses paramètres jusqu'à présent, mais pas rebaser avec --onto.

void.pointer
la source
Vous pouvez soit définir des alias git pour vos cas d'utilisation courants, soit créer un script d'assistant qui vous rappelle ce que signifie chacun des paramètres avant d'exécuter la commande.
Rory Hunter
4
Ah, cette élégance époustouflante et pure des options de commande git. Donc intuitivement à utiliser. Toujours un vrai plaisir.
JensG

Réponses:

10

Sautons --ontopour le moment. upstreamet branchsont assez basiques, et en fait une sorte de mimique checkoutet branch- le deuxième argument est facultatif:

git branch <newbranch>
git branch <newbranch> <base>
git checkout -b <newbranch>
git checkout -b <newbranch> <base>
git rebase <upstream>
git rebase <upstream> <branch>

( En plus, les noms de ces arguments rebase, « en amont » et « branche » ne sont pas très descriptif OMI Je pense généralement d'entre eux comme peachoftree,. <start>Et <end>, ce qui est de savoir comment je vais les utiliser: git rebase <start> <end>)

Lorsque la deuxième branche est omise, le résultat est presque le même que la première extraction de cette branche, puis le fait comme si vous n'aviez pas spécifié cette branche. L'exception est celle branchqui ne change pas votre branche actuelle:

git checkout <base> && git branch <newbranch> && git checkout <previous_branch>
git checkout <base> && git checkout -b <newbranch>
git checkout <end>  && git rebase <start>

En ce qui concerne la compréhension de ce qui se rebaseproduit lorsqu'il est invoqué, j'ai d'abord commencé par le considérer comme un type spécial de fusion. Ce n'est pas vraiment, mais cela a aidé lorsque j'ai commencé à comprendre le rebase. Pour emprunter l'exemple de peachoftree:

A--B--F--G master
    \
     C--D--E feature

Un git merge masterrésultat en ceci:

A--B--F-----G master
    \        \
     C--D--E--H feature

Alors qu'un git rebase master(sur une branche feature!) Entraîne ceci:

A--B--F--G master
          \
           C'--D'--E' feature

Dans les deux cas, featurecontient maintenant le code des deux masteret feature. Si vous n'êtes pas featureactivé, le deuxième argument peut être utilisé pour y basculer en tant que raccourci: git rebase master featurefera la même chose que ci-dessus.


Maintenant, pour la spéciale --onto. La partie importante à retenir avec cela est qu'elle est par défaut <start>si elle n'est pas spécifiée. Donc ci-dessus, si je spécifiais --ontospécifiquement, cela se traduirait par la même chose:

git rebase --onto master master
git rebase --onto master master feature

(Je n'utilise pas --ontosans spécifier <end>simplement parce qu'il est plus facile d'analyser mentalement, même si ces deux sont les mêmes s'ils sont déjà activés feature.)

Pour voir pourquoi --ontoest utile, voici un exemple différent. Disons que j'étais featureallumé et que j'ai remarqué un bogue, que j'ai ensuite commencé à corriger - mais que j'avais dérivé au featurelieu de masterpar erreur:

A--B--F--G master
    \
     C--D--E feature
            \
             H--I bugfix

Ce que je veux, c'est "déplacer" ces commits pour bugfixqu'ils ne soient plus dépendants feature. En l'état, toute sorte de fusion ou de rebase illustrée ci-dessus dans cette réponse prendra les trois featurevalidations avec les deux bugfixvalidations.

Par exemple, git rebase master bugfixc'est faux. La plage <start>à <end>inclure tous les commits feature, qui sont rejoués en plus de master:

A--B--F--G master
    \     \
     \     C'--D'--E'--H'--I' bugfix
      \
       C--D--E feature

Ce que nous voulons réellement est la gamme de commits de featureà bugfixêtre rejoué au - dessus de master. C'est à cela que --ontosert - en spécifiant une cible de "relecture" différente de la branche "start":

git rebase --onto master feature bugfix

A--B--F--G master
    \     \
     \     H'--I' bugfix
      \
       C--D--E feature
Izkata
la source
1

Juste un rappel, le rebasage est principalement pour quand vous voulez que votre historique de commit apparaisse linéaire si deux branches se sont développées indépendamment l'une de l'autre, fondamentalement il réécrit l'historique de commit.

la façon dont j'aime le faire est git rebase --onto <target branch> <start branch> <end branch>

<target branch>est la branche sur laquelle vous rebasez, <start branch>est normalement la branche à partir de laquelle vous vous séparez <end branch>et <end branch>est la branche sur laquelle vous rebasez.

si vous commencez par

A--B--F--G master
    \
     C--D--E feature

et fait

git rebase --onto master master feature

tu auras

A--B--F--G master
          \
           C'--D'--E' feature

une autre bonne chose à savoir est que par <target branch>défaut <start branch>, vous pouvez faire la même rebase que

git rebase --onto master feature

si vous avez besoin de plus d'aide, consultez le guide Rebase without tears

peachoftree
la source
Votre résultat semble trompeur. rebase devrait laisser la masterbranche elle-même inchangée. Vous obtenez simplement une «fonctionnalité» pour vous ramifier comme G--C'--D'--E'si vous vous arrêtiez mastertoujours à G.
Frank
@Frank, je l'ai fait pour souligner toute l'histoire linéaire, mais maintenant je pense que vous allez mieux. fixé.
peachoftree
1
Pouvez-vous montrer un exemple où <target branch>et <start branch>sont différents afin d'aider les lecteurs à comprendre le cas le plus général?
Rufflewind