Guide du débutant pour le rebasage interactif

Publié initialement par Stride le 16 janvier 2018 52,731 lectures
.

En début d’année, j’ai fait une rebase interactive pour la première fois et j’ai été impressionné par ce qu’on peut faire avec. J’ai également trouvé que c’était un peu complexe au début. Espérons que ce guide aidera à lever certaines incertitudes autour de lui.

En outre, parce qu’il est si puissant et que vous pouvez essentiellement réécrire l’histoire, un petit avertissement avant de commencer : Il existe de nombreuses écoles de pensée sur Git et si le rebasement est une bonne idée ou non. Ce post ne plongera pas dans ces discussions et est purement destiné à parcourir les bases de l’utilisation du rebasing interactif.

TL;DR

  • Le rebasing interactif peut être utilisé pour modifier les commits de plusieurs façons, telles que l’édition, la suppression et l’écrasement.
  • Pour indiquer à Git où commencer le rebasement interactif, utilisez le SHA-1 ou l’index du commit qui précède immédiatement le commit que vous voulez modifier.
  • Pendant un rebasement interactif, lorsque Git fait une pause sur un commit que vous avez marqué pour l’éditer, le flux de travail n’est pas différent d’un processus de commit normal – vous mettez en scène les fichiers puis vous les commitez. La seule différence est que vous utilisez la commande git commit --amend plutôt que git commit.
  • Le rebasement interactif créera de nouveaux SHA-1, il est donc préférable d’utiliser le rebasement interactif sur les commits que vous n’avez pas poussés vers une branche distante.

Le problème

Dans cet exemple, nous allons travailler sur une situation où nous avons travaillé dans une branche de fonctionnalité et nous avons quelques commits que nous aimerions modifier ou supprimer. Voici à quoi ressemble notre journal git:

D’après le journal git ci-dessus, voici les deux commits que nous voulons modifier :
4a4d705 – Dans ce commit, nous avons accidentellement commis un conflit de fusion
6c01350 – Dans ce commit, nous avons supprimé le conflit de fusion

Ce que nous voudrions faire, c’est revenir en arrière dans le temps à 4a4d705, supprimer le conflit de fusion dans le commit, puis supprimer 6c01350 puisque le conflit de fusion est résolu et que nous n’avons plus besoin de ce commit. Cela constituera une amélioration de notre historique de commit pour deux raisons :

  1. Nous n’aurons pas de commits cassés (conflits de fusion)
  2. Nous n’aurons que des commits significatifs, pas de commits liés uniquement à la correction d’un conflit de fusion manqué

La solution

Cette situation est un bon candidat pour le rebasage interactif. Scott Chacon, dans son livre Pro Git, décrit le rebasage interactif comme suit : « Parfois, la chose corrigée… ne peut pas être modifiée par rapport au commit pas tout à fait parfait qu’elle corrige, parce que ce commit est enterré profondément dans une série de patchs. C’est exactement à cela que sert le rebase interactif : utilisez-le après beaucoup de , en réorganisant et en modifiant les commits, et en écrasant plusieurs commits en un seul. »

Quels commits voulons-nous modifier ?

Pour démarrer un rebase interactif, nous devons indiquer à Git quels commits nous voulons modifier. Nous le faisons en référençant le commit immédiatement antérieur au commit le plus ancien que nous voulons modifier. Ou, plus simplement, nous référençons « le dernier commit que nous voulons conserver tel quel », selon Scott Chacon.

Regardons notre exemple pour avoir une meilleure compréhension. Il y a deux façons de référencer ce commit :
By SHA-1 – Le dernier commit que nous voulons conserver tel quel a un SHA-1 de 528f82edonc nous pouvons le passer dans notre commande interactive rebase.
By Index – Le dernier commit que nous voulons conserver tel quel a une position d’index de 3 (Git utilise une indexation basée sur zéro) donc nous pouvons passer dans HEAD~3 à notre commande interactive rebase.

Note – Si vous n’avez que quelques commits sur lesquels rebaser interactivement, utiliser l’index est probablement plus facile pour la plupart des gens. Cependant, si vous avez beaucoup de commits, l’utilisation du SHA-1 est probablement plus facile afin que vous n’ayez pas à compter tout le long du journal git.

Démarrer le rebasage interactif

Selon notre exemple, nous allons exécuter soit :

$ git rebase -i 528f82e

Or

$ git rebase -i HEAD~3

Ce qui ouvre cette fenêtre dans Vim :

Notez que les commits sont dans l’ordre inverse de celui de git log. Dans git log, le commit le plus récent est en haut. Dans cette vue, le commit le plus récent est en bas. Remarquez également que les commentaires ci-dessous donnent une liste utile des commandes valides que nous pouvons utiliser sur chaque commit.

Si vous ne connaissez pas Vim, il suffit de cliquer sur chaque mot pick que vous voulez éditer puis d’appuyer sur la touche <i> (pour le mode insertion). Une fois que vous avez fini de taper, appuyez sur la touche <esc> pour quitter le mode insertion.

Dans notre exemple, nous avons changé la commande en edit pour le commit que nous voulons modifier et nous avons changé la commande en drop pour le commit que nous voulons supprimer. Ensuite, nous exécutons :wq pour sauvegarder et quitter la fenêtre Vim.

Modifier le commit

De retour dans le terminal, nous voyons ce message:

Ceci est logique que nous soyons arrêtés à 4a4d705. C’est le commit le plus ancien dans la série de commits que nous voulons modifier. Nous allons commencer avec ce commit et travailler notre chemin à travers chaque commit jusqu’au plus récent.

Pour rappel, 4a4d705 était le commit avec le conflit de fusion que nous avons accidentellement commis. Lorsque nous ouvrons notre éditeur, nous y voyons le conflit de fusion :

Donc nous corrigeons le conflit de fusion dans le fichier mais que faisons-nous maintenant ? Dans le doute, git status:

Cool ! Ceci est en fait utile. Nous voyons que nous sommes actuellement en train d’éditer 4a4d705, et nous voyons les deux prochains commits sur lesquels il faut agir après celui-ci.

Le reste du message nous explique un flux de travail familier. Git nous dit que si nous voulons modifier le commit, nous exécutons git commit --amend. Cela agira essentiellement comme notre git commit typique que nous utilisons dans un flux de travail normal. Au bas de ce message, nous voyons que notre fichier a été modifié en reflétant les changements que nous venons de faire pour supprimer le conflit de fusion. Nous devons mettre en scène le fichier avant de le valider. Ce n’est pas différent d’un flux de travail normal.

Tout ce que nous faisons est git add tempChanger.js de mettre en scène le fichier édité et ensuite git commit --amend de commiter le fichier mis en scène ! Cela va maintenant ouvrir une fenêtre Vim à nouveau avec le message de commit:

Nous pouvons soit modifier le message de commit, soit le laisser tel quel. Choisissons de garder le message de commit tel quel et nous allons taper :wq pour sauvegarder et quitter la fenêtre.

Nous avons maintenant édité notre ancien commit. Et maintenant ? Exécutez git status:

Continue interactive rebase

Nous n’avons rien d’autre à changer dans le commit donc continuons!

Nous exécutons git rebase --continue et nous voyons le message suivant:

Woah, nous avons fini ? Mais qu’en est-il de ces deux autres commits ? Eh bien, le prochain commit sur lequel nous devons agir est 6c01350. Ce commit a été marqué comme devant être supprimé (drop) lorsque nous avons lancé le rebasement interactif. Git l’a automatiquement supprimé et est passé au commit suivant, 41aa9d2. Celui-ci n’a jamais été modifié lors de la rebase interactive initiale. Sa commande par défaut était pick ce qui signifie que le commit sera utilisé. Git a appliqué ce commit et comme c’était le dernier, la rebase interactive s’est terminée.

Notez, si nous avions plus de commits à modifier, nous serions simplement passés au commit suivant et aurions commencé le processus de modification comme nous l’avons fait ci-dessus. Le cycle continue jusqu’à ce qu’il n’y ait plus de commits.

Le bouton d’éjection

Il est intéressant de noter que si à un moment donné dans notre rebase interactif nous foirons des choses et ne savons pas comment les réparer, nous pouvons toujours abandonner. À tout moment, nous pouvons exécuter git rebase --abort dans le terminal et le rebase interactif sera interrompu sans qu’aucun changement ne soit enregistré. Nous aurions alors besoin de recommencer le rebasement interactif.

Après le rebasement interactif

Notre journal git ressemble maintenant à :

Vous remarquerez que quelques choses ont changé par rapport à avant de commencer le rebasement interactif :

  • Nous n’avons plus le commit 6c01350 avec le message de commit « Remove merge conflict ». C’est le commit que nous avons supprimé dans notre rebase interactive.
  • Notre commit que nous avons édité, 4a4d705, a un SHA-1 différent, 2b7443d.
  • Notre plus récent commit de notre journal git original, 41aa9d2, a également un nouveau SHA-1, 2b95e92. Ce commit n’a pas été modifié mais a simplement été appliqué au commit qui le précédait 2b7443d.

Effets secondaires du rebasage interactif

Pour les deux commits les plus récents de notre journal git, parce qu’ils ont de nouveaux SHA-1, Git les voit comme des commits entièrement nouveaux. C’est même vrai pour notre dernier commit, 2b95e92, où ni le message de commit ni les fichiers n’ont changé du tout. Cela soulève un point important avec le rebasage interactif : Si vous modifiez un commit, ce commit et tous les commits successifs auront de nouveaux SHA-1.

Cela n’affectera rien si les commits que vous avez modifiés n’ont pas été poussés vers une branche distante. Cependant, si vous avez en fait complété un rebase interactif sur des commits qui ont déjà été poussés vers une branche distante et que vous avez ensuite poussé votre branche à nouveau, vous verrez :

Techniquement, vous pourriez contourner cela en utilisant git push --force mais c’est très dangereux. Si la branche distante a des commits d’autres personnes mais que votre branche locale n’a pas encore ces commits, vous allez effectivement supprimer leurs commits.

Une autre solution est d’utiliser git push --force-with-lease qui ne modifiera que vos commits mais pas les commits appartenant à d’autres personnes, bien que cela puisse aussi être problématique. Par exemple, si un autre développeur a déjà ces commits qui ont reçu de nouveaux SHA-1 sur leur branche locale, lorsqu’il tire la branche distante, il aura des conflits de fusion avec chacun de ces commits.

Quand utiliser --force-with-lease est au-delà de la portée de cet article de blog, mais il serait préférable de consulter les autres membres de votre équipe avant de le faire. Vous pouvez en savoir plus sur git push --force-with-lease ici.

La principale conclusion de cette section est qu’il est beaucoup plus facile et plus sûr d’utiliser le rebasement interactif sur les commits qui n’ont pas encore été poussés vers une branche distante.

Écrit par Blake DeBoer. Originellement posté sur Dev.to

Développeur senior, leader ou principal à NYC ? Stride embauche ! Vous voulez mettre à niveau votre équipe technique ? Voyez comment nous le faisons ! www.stridenyc.com

.

Tags

Rejoignez Hacker Noon

Créez votre compte gratuit pour débloquer votre expérience de lecture personnalisée.

Leave a Reply