Qu'est-ce qu’un rebase interactif ?
Le rebase interactif, également connu sous le nom de Git rebase interactive en anglais, est un peu le « couteau suisse » de Git car il permet d’avoir accès à différents outils pour de nombreux usages possibles. Son cas d'utilisation principal restant cependant le nettoyage de l'historique des commits locaux.
Soulignons bien ici le mot local. Le rebase interactif s'utilise uniquement pour nettoyer votre propre historique de commits en local, avant par exemple d'intégrer l’une de vos branches de fonctionnalités au sein d’une branche d’équipe.
En revanche, le rebase interactif (ou Git rebase interactive) ne doit pas être utilisé sur un historique de commits Git dont le push a déjà été effectué et partagé sur un dépôt distant. Le rebase interactif est l’un de ces outils qui « réécrivent » l'historique Git ; il ne doit donc pas être utilisé sur des commits déjà partagés avec d'autres personnes. Passé ce petit avertissement, voyons quelques exemples pratiques !
Corriger un ancien message de commit avec le rebase interactif
Parfois, vous remarquez une coquille dans un vieux message de commit. Ou bien, vous oubliez de mentionner quelque chose d'utile dans une description. Si l'on parle du tout dernier commit en date, vous pouvez utiliser l'option --amend
de la commande git commit
. Mais pour les commits plus anciens, le Git rebase interactive vous permet de les modifier après coup.
Voici un exemple de message de commit nécessitant une correction :
La première étape dans toute session de Git rebase interactive consiste à déterminer quelle partie de l'historique des commits vous souhaitez manipuler. Pour modifier le commit incorrect dans l'exemple précédent, nous devons démarrer la session à partir de son commit parent.
Nous pouvons maintenant transmettre le hash du commit de départ à la commande Git rebase interactive :
$ git rebase -i 0023cddd
Une fenêtre d’édition va alors s'ouvrir, contenant la liste des commits que vous venez de sélectionner. Ne soyez pas surpris s’ils apparaissent dans l'ordre inverse. Dans une session de rebase interactif, Git applique les commits élément après élément, du plus ancien au plus récent, ce qui signifie que l'inversion de l'ordre est correcte du point de vue de Git.
Une chose importante à noter à propos de cette fenêtre d’édition : ce n'est pas ici que vous effectuez les manipulations réelles ! Dans cet exemple concret, ce n’est pas à cet endroit que vous modifiez le message du commit. Vous indiquez seulement le commit que vous allez modifier en appliquant un mot-clé d'action. Dans notre cas, comme nous voulons changer le message d'un commit, nous entrons la ligne « reword ». Si vous sauvegardez et fermez la fenêtre d’édition, une nouvelle fenêtre s'ouvrira, contenant l'ancien message de commit.
Il est temps d'effectuer vos modifications :
Après avoir sauvegardé et fermé la fenêtre une fois de plus, la session de Git rebase interactive est terminée et notre ancien message de commit a été corrigé.
Combiner plusieurs commits en un seul avec le rebase interactif
Autre cas d'usage du Git rebase interactive : lorsque vous souhaitez combiner plusieurs anciens commentaires en un seul. Bien entendu, la règle d'or du contrôle de version s'applique : il est généralement conseillé de créer plus de petits commits plutôt que quelques gros. Cependant, nous pouvons parfois nous laisser emporter, et vouloir ensuite fusionner quelques commits en un seul.
Prenons un exemple concret, où nous allons entreprendre de combiner les commits suivants :
Comme dans notre premier cas, nous commençons par démarrer la session de Git rebase interactive au niveau du commit parent de celui que nous voulons manipuler.
$ git rebase -i 2b504bee
Une fois encore, une fenêtre d'édition s'ouvre, listant la partie de notre historique de commits Git que nous souhaitons manipuler.
Marquer les lignes avec le mot-clé « squash »
Le mot-clé d’action que nous allons utiliser ici s'appelle « squash ». Pour bien utiliser cette fonction, retenez que la ligne marquée avec le mot-clé « squash » sera combinée avec la ligne directement au-dessus. Ainsi, comme le montre la capture d'écran ci-dessus, nous avons marqué la ligne #2 avec « squash » afin de la combiner avec le commit de la ligne #1 juste au-dessus.
Nous pouvons maintenant sauvegarder et fermer la fenêtre d’édition ; une nouvelle fenêtre va alors apparaître. Il nous est maintenant demandé de fournir un message de commit pour le nouveau commit créé en combinant ces deux anciens.
Enfin, sauvegardez et fermez cette fenêtre d’édition. Un nouveau commit est créé, contenant les modifications des deux anciens commits.
Corriger une erreur avec le rebase interactif
Un autre cas d’usage du Git rebase interactive consiste à corriger une erreur identifiée dans l'un de vos commits précédents. La nature exacte de l'erreur n'a pas d'importance. Vous pourriez par exemple avoir oublié d'ajouter un changement, de supprimer un fichier, ou simplement de corriger une faute de frappe.
Dans une telle situation, nous avons tendance à vouloir créer un nouveau commit pour corriger cette erreur. Cela risque toutefois d'ajouter du désordre à votre historique de commits. Il n'est pas idéal d'ajouter un commit de fortune au commit initial juste pour corriger quelques erreurs. Votre historique de commits deviendra rapidement illisible, car jonché de multiples petits commits de correction.
C'est là que vous pouvez profiter de « fixup », l'un des outils fournis avec le Git rebase interactive. « Fixup » applique ce commit de réparation rapide et ses changements au commit initial, le corrigeant ainsi. Ensuite, il se débarrasse simplement du commit de fortune.
Comment utiliser « fixup » ?
Une fois la fonction « fixup » utilisée, c'est comme si notre commit initial avait toujours été correct. Voyons cela à l'aide d'un exemple.
La première étape consiste à faire le nécessaire pour corriger le problème. Il peut s'agir d'ajouter un nouveau fichier, de modifier des fichiers existants ou de supprimer ceux qui sont obsolètes. Vous avez simplement à effectuer les modifications qui corrigent l'erreur.
L'étape suivante consiste à valider ces modifications au niveau du dépôt, mais avec un petit truc en plus. Au moment du commit, nous allons ajouter --fixup
et indiquer à Git le hash de notre mauvais commit :
$ git add corrections.txt
$ git commit --fixup 2b504bee
Jetez maintenant un coup d'œil à votre historique de commits. Vous constaterez qu'un commit d'apparence ordinaire a été créé. Mais à y voir de plus près, il s'est passé quelque chose. Le nouveau commit affiche la mention « fixup ! » et il reprend le sujet de notre mauvais commit.
Enfin, la troisième étape consiste à démarrer la session de Git rebase interactive. Nous sélectionnons à nouveau le commit parent de notre mauvais commit comme point de départ :
$ git rebase -i 0023cddd --autosquash
Et pour conclure, nous utilisons notre botte secrète : --autosquash
. Cette option nous assure de ne rien avoir à faire au sein de la fenêtre d’édition désormais ouverte. Regardons de plus près la situation :
Git a automatiquement effectué deux choses :
- Le commit de correction de fortune est marqué comme « fixup ».
- L'ordre des lignes fait apparaître notre commit de correction directement sous le mauvais commit. Tout comme « squash », « fixup » combine le commit avec celui de la ligne supérieure.
Enfin, il ne nous reste plus qu'à sauvegarder et à fermer la fenêtre d’édition.
Jetons un coup d'œil à l'historique des commits :
Ainsi, le mauvais commit initial contient maintenant les changements du commit de secours. Mais en plus de cela, le commit de secours a maintenant disparu de l’historique de commits. Tout beau, tout propre, comme s'il n'y avait jamais eu le moindre problème !
Découvrez la puissance du rebase interactif
Vous allez pouvoir utiliser le Git rebase interactive dans de très nombreux cas, la plupart du temps afin de corriger des erreurs. Pour une vue d'ensemble de toutes les choses utiles à faire avec le rebase interactif, nous vous recommandons ce guide sur Git.
FAQ sur le rebase interactif
Quelle est la différence entre rebase et merge ?
Voilà une question souvent posée par les développeurs : rebase ou merge ? Ces commandes permettent d'effectuer des changements d'une branche à l'autre. Avec git merge
, nous créons un commit de merge dans la branche locale. Avec git rebase
, chaque commit de la branche locale est recréé en pointe de la branche principale. Git rebase -i
interactif est similaire à git rebase, mais permet en plus de modifier les commits au moment de les envoyer vers la branche principale.
Quelle est la différence entre le Git rebase interactive et le Git rebase ?
Lorsque l'on ajoute l'option interactive au Git rebase, cela permet d'ouvrir une fenêtre d’édition afin d'éditer en amont chaque commit de votre branche locale avant de les rebaser, notamment pour nettoyer votre historique. Les commandes principales sont reword
(éditer un message de commit), squash
(fusionner deux commits), et fixup
(amender un commit).
Quelles sont les erreurs à éviter avec le rebase interactif ?
Le rebase interactif est généralement conseillé aux utilisateurs plutôt avancés. Lorsque vous utilisez ces commandes, veillez à éviter les pièges suivants :
- Ordre des commits. Conservez la logique du workflow lorsque vous réordonnez des commits.
- Sauvegarde. N'oubliez pas de sauvegarder et fermer votre fenêtre d'édition en fin de session de rebase interactif.
- Rebasing sur la branche principale. Le rebase s'applique toujours à des commits de votre branche locale vers la branche publique.
Image de couverture par David Taljat sur Pexels.