Guide pratique du rebase interactif Git, avec exemples concrets

La gestion de versions avec Git est devenue une norme dans le casier à outils de chaque développeur moderne. Des commandes comme commit, push et pull sont entrées dans la mémoire musculaire de nos doigts. Mais relativement peu de développeurs connaissent les fonctionnalités « plus avancées » de Git — et à quel point elles peuvent être incroyablement précieuses ! Dans cet article, nous allons explorer le « rebase interactif », l’un des outils les plus puissants de Git.

Pourquoi le Rebase Interactif Devrait Faire Partie de l’Outil de Tous les Développeurs

En un mot, et sans exagération, le rebase interactif peut vous aider à devenir un meilleur développeur, en vous permettant de créer une histoire de commit propre et bien structurée dans vos projets.

Pourquoi une histoire de commit bien structurée est-elle importante ? Imaginez simplement le contraire : une histoire de commit difficile à lire, où vous ne savez pas ce que vos collègues ont réellement fait avec leurs dernières modifications. De plus en plus de « coins sombres » commencent à émerger dans un tel projet, et vous ne comprenez que les petites parties sur lesquelles vous avez travaillé vous-même.

En revanche, une histoire de commit propre et bien structurée aide à rendre le code d’un projet plus lisible et plus facile à comprendre. C’est un ingrédient essentiel pour un projet sain et durable !

Ce que le Rebase Interactif Peut Faire pour Vous

Le Rebase Interactif vous aide à optimiser et nettoyer votre histoire de commit. Il couvre de nombreux cas d’utilisation différents, dont certains vous permettent de faire ce qui suit :

  • modifier un message de commit ancien
  • supprimer un commit
  • rassembler/combiner plusieurs commits
  • réordonner les commits
  • réparer de vieux commits
  • diviser/réouvrir de vieux commits pour édition

Quand utiliser un rebase interactif (et quand ne pas le faire!)

Comme plusieurs autres outils Git, le rebase interactif « réécrit l’histoire ». Cela signifie que, lorsque vous manipulez une série de commits à l’aide du rebase interactif, cette partie de votre histoire des commits sera réécrite: les hachages SHA-1 des commits auront changé. Ce sont, pour ainsi dire, de nouveaux objets de commit.

Ce fait implique une règle simple mais importante à respecter : n’utilisez pas le rebase interactif (ou d’autres outils qui réécrivent l’histoire) sur des commits que vous avez déjà partagés avec vos collègues sur un dépôt distant. Utilisez-le plutôt pour nettoyer vos propres commits locaux – comme dans l’une de vos propres branches de fonctionnalité – avant de les fusionner dans une branche de l’équipe.

Le mécanisme de base d’une opération de rebase interactif

Bien qu’il existe de nombreuses choses différentes que le rebase interactif peut être utilisé pour, le flux de travail de base est toujours le même. Une fois que vous avez bien compris ce mécanisme de base, le rebase interactif perdra son air de « mystère complexe » et deviendra un élément précieux et accessible dans votre trousse à outils.

Étape 1 : Où devriez-vous commencer la session?

La première question à se poser est : « Quelle partie de mon histoire des commits souhaite-je manipuler? » Cela vous indique où vous devriez commencer votre session de rebase interactif. Prenons un exemple pratique et disons que nous aimerions éditer un message de commit ancien (ce que nous ferons effectivement en pratique dans un instant).

Notre situation de départ est représentée ci-dessous, où nous modifions un message de commit ancien via un rebasage interactif.

Pour pouvoir modifier le message de commit dans C2, nous devons commencer notre session de rebasage interactif à partir de son commit parent (ou même avant cela, si vous le souhaitez). Dans cet exemple, nous utiliserions C1 comme point de départ pour notre session de rebasage interactif.

Étape 2 : démarrage de la session réelle !

Démarrer la session réelle est assez simple :

$ git rebase -i HEAD~3

Nous utilisons la commande git rebase avec l’indicateur -i (pour indiquer que nous voulons qu’il soit « interactif ») et fournissons le commit de base (que nous avons déterminé dans notre première étape ci-dessus). Dans cet exemple, j’ai utilisé HEAD~3 pour spécifier le commit qui est « 3 derrière le commit HEAD ». Alternativement, j’aurais pu fournir un hachage SHA-1 spécifique.

Étape 3 : indiquer à Git ce que vous souhaitez faire

Après avoir démarré la session de rebasage interactif, vous serez présenté avec une fenêtre d’éditeur où Git liste une série de commits — du dernier commit jusqu’au (mais sans inclure) celui que vous avez choisi comme commit de base dans l’Étape 1.

Il y a deux choses importantes à garder à l’esprit dans cette étape :

  1. Les commits sont listés dans l’ordre inverse ! Le dernier commit, que nous nous attendrions à voir apparaître au haut, apparaîtra en bas de la liste. Ne vous inquiétez pas : votre dépôt Git est en pleine forme ! 🥳 Rappelez-vous que nous sommes en train d’effectuer une opération de rebasage interactif, et cela nécessite à Git de réappliquer les commits du plus ancien au plus récent à la fin de l’opération.
  2. Ne faites pas vos modifications réelles dans cette fenêtre d’éditeur ! Bien que vous puissiez avoir envie de simplement modifier le message de commit dans cette fenêtre d’éditeur (après tout, c’est ce que nous voulons vraiment faire…), vous devez montrer de la patience. Ici, nous allons simplement indiquer à Git ce que nous voulons faire — mais sans faire la modification réelle. Je vais illustrer ce point en pratique sous peu !

Maintenant que cette vue théorique est éclaircie, plongeons ensemble dans des cas pratiques !

Modifier un Message de Commit Ancien

L’une des utilisations très populaires du rebasage interactif est que vous pouvez modifier un message de commit ancien après coup. Vous êtes peut-être conscient que git commit --amend vous permet également de changer le message d’un commit — mais uniquement s’il s’agit du dernier commit. Pour tout commit plus ancien que cela, nous devons utiliser le rebasage interactif !

Examinons un scénario concret. Voici une image d’un mauvais message de commit qui doit être corrigé.

Remarque : Pour une meilleure vue d’ensemble et une visualisation plus claire, j’utilise le client de bureau Tower Git dans certaines de mes captures d’écran. Vous n’avez pas besoin de Tower pour suivre ce tutoriel.

Dans notre exemple, disons que nous aimerions modifier le message du commit actuellement intitulé « Optimiser la structure de balisage dans index… »

Notre premier pas consiste à déterminer le commit de base pour commencer cette session de rebase interactive. Étant donné que nous devons (au moins) remonter jusqu’au parent de notre commit « mauvais fruit », nous commençons notre session à HEAD~3 (trois commits derrière le commit HEAD, qui est celui intitulé « Changer les titres… ») :

$ git rebase -i HEAD~3

Immédiatement après avoir exécuté cette commande, votre éditeur préféré s’ouvrira et présentera la liste des commits que vous venez de sélectionner (en fournissant un commit de base).

À titre de rappel : même si vous pourriez être tenté de le faire, nous ne modifions pas le message du commit ici. Nous ne marquons que la ligne respective avec un « mot-clé d’action ». Dans notre cas, nous voulons reword le commit (ce qui signifie que nous aimerions changer le message du commit, mais laisser le reste du commit tel quel).

Très pratiquement, tous les mots-clés d’action disponibles sont documentés en bas de cette fenêtre – donc pas besoin de mémoriser quoi que ce soit !

Une fois que vous avez remplacé le mot-clé standard pick (qui signifie « prendre le commit tel quel ») par votre mot-clé d’action préféré, vous pouvez simplement enregistrer et fermer la fenêtre.

Après cela, une nouvelle fenêtre d’éditeur s’ouvrira contenant le message de commit actuel. Enfin, nous sommes autorisés à faire ce que nous nous étions fixés comme objectif en premier lieu : modifier ce message de commit ancien !

Après avoir effectué notre modification, puis enregistrement et fermeture de la fenêtre d’éditeur, la session de rebase interactive est terminée – et notre message de commit est mis à jour ! 🎉

Supprimer un Commit Indésirable

La rebase interactive vous permet également de supprimer un ancien commit de votre historique que vous n’avez plus besoin (ou ne souhaitez plus). Imaginez simplement que vous avez accidentellement inclus un mot de passe personnel dans un commit récent : des informations sensibles comme celle-ci ne devraient pas, dans la plupart des cas, être incluses dans une base de code.

N’oubliez pas également que simplement supprimer l’information et commiter à nouveau ne résout pas vraiment votre problème : cela signifierait que le mot de passe est toujours enregistré dans le dépôt, sous la forme de votre ancien commit. Ce que vous souhaitez vraiment, c’est nettoyer et complètement supprimer cet élément de données du dépôt tout court!

Commençons par déterminer le commit de base pour notre session de rebase interactif. Puisque nous devons commencer au moins au parent du mauvais commit, nous utilisons le commit « Optimiser la structure de mise en forme… » comme base :

$ git rebase -i 6bcf266b

Notez que, cette fois, j’ai utilisé un hachage SHA-1 concret dans la commande git rebase -i. Au lieu de l’identifiant du commit, bien sûr, j’aurais pu utiliser HEAD~2 pour désigner ce commit.

Après avoir exécuté cette commande, nous sommes à nouveau présentés avec une liste de commits.

Cette fois, nous utilisons le mot-clé d’action drop pour éliminer le commit indésirable. Alternativement, dans ce cas particulier, nous pourrions également simplement supprimer la ligne entière dans l’éditeur. Si une ligne (représentant un commit) n’est plus présente lorsque vous enregistrez et fermez la fenêtre, Git supprimera le commit correspondant.

Quelle que soit la méthode choisie, après avoir enregistré et fermé la fenêtre de l’éditeur, le commit sera supprimé de l’histoire de votre dépôt !

Combiner plusieurs commits en un seul

Un autre cas d’utilisation pour le rebase interactif est lorsque vous souhaitez combiner plusieurs commits distincts en un seul. Avant de plonger dans comment cela fonctionne, passons quelques instants à parler de quand ou pourquoi cela pourrait être précieux.

Généralement parlant, rendre les commits « plus gros » (en combinant plusieurs en un) est pas une bonne stratégie dans la plupart des cas. La règle générale est de garder les commits aussi petits que possible, car « petit » signifie « plus facile à lire et à comprendre ». Mais il existe des situations où cela peut néanmoins être logique. Voici deux exemples:

  • Imaginez que vous remarquiez un problème avec un commit plus ancien. Vous pourriez alors procéder à la création d’un nouveau commit qui corrige le problème. Dans une telle situation, être en mesure de combiner ces commits en un seul en a beaucoup de sens : le commit plus récent, après tout, n’était qu’un « pansement » pour résoudre un problème qui n’aurait pas dû être là en premier lieu. En combinant ces commits, on dirait qu’il n’y a jamais eu de problème en premier lieu!
  • Un autre exemple est lorsque vous remarquez que vous avez rendu les choses un peu trop granulaires. Faire des commits petits est très bien, mais jeter votre historique de commits avec beaucoup de trop petits commits signifierait dépasser la marque.

La logique est la même dans les deux exemples : en combinant deux (ou plusieurs) commits qui auraient dû être un seul à la base, vous produisez un historique de commits plus propre et plus lisible!

Traçons ensemble un exemple pratique et prenons la situation illustrée ci-dessous comme situation de départ.

Supposons que, du point de vue sémantique, il est plus logique que ces deux commits soient réunis en un seul. En utilisant l’outil squash du rebase interactif, nous pouvons effectivement les combiner :

$ git rebase -i HEAD~3

À présent, vous êtes déjà habitué à ce qui suit : une fenêtre d’éditeur s’ouvre avec une liste des commits.

I already mentioned that we’re going to use the squash action keyword in this case. There’s an important thing to know about how squash works: the line you mark up with the keyword will be combined with the line directly above! This explains why I marked line 2 with the squash keyword in our example.

Après avoir enregistré et fermé cette fenêtre, une nouvelle s’ouvrira. Cela est dû au fait que, en combinant plusieurs commits, nous créons bien sûr un nouveau. Et celui-ci a besoin d’un message de commit, comme n’importe quel autre commit !

Ce que vous voyez dans l’image ci-dessus est ce que Git a préparé pour nous : il a combiné les messages de commit des commits originaux respectifs avec quelques commentaires. Vous êtes libre de supprimer les anciens messages et de repartir de zéro — ou de les conserver et d’ajouter plus d’informations.

Après avoir enregistré et fermé cette fenêtre d’éditeur, nous pouvons déclarer avec fierté : ce qui était auparavant deux commits séparés est maintenant un seul !

Maîtriser le Pouvoir du Rebase Interactif

I hope you agree that Git’s interactive rebase tools can be very valuable! As developers, it’s important for us to strive for a clean and clear commit history. It’s a crucial ingredient in keeping a codebase healthy and easy to understand (both for your teammates, and yourself, after some time has passed).

Si vous souhaitez en savoir plus, je recommande vivement le “Premier Secours pour Git”. Il s’agit d’une collection (gratuite) de courts vidéos qui vous montrent comment nettoyer et annuler les erreurs dans Git.

Amusez-vous bien !

Questions Fréquemment Posées (FAQs) sur le Rebase Interactif Git

Quelle est la différence entre Git Rebase et Git Merge ?

Git Rebase et Git Merge sont deux manières différentes d’intégrer des modifications d’une branche dans une autre. Git Merge est une manière simple de combiner le code de deux branches différentes. Il crée un nouveau commit dans l’historique, préservant l’ordre chronologique des commits. D’un autre côté, Git Rebase est une manière de déplacer ou de combiner une séquence de commits vers un nouveau commit de base. C’est comme dire « Je veux baser mes modifications sur ce que tout le monde a fait. » En d’autres termes, cela vous permet de placer les modifications de la branche actuelle au-dessus d’une autre branche.

Comment puis-je annuler un Git Rebase?

Si vous souhaitez annuler un Git Rebase, vous pouvez utiliser la commande git reflog pour trouver le commit auquel vous souhaitez revenir, puis utiliser la commande git reset --hard HEAD@{number}. La commande git reflog affiche une liste de chaque modification effectuée sur le HEAD, et la commande git reset vous permet de définir le HEAD actuel à l’état spécifié.

Quel est le but de Git Interactive Rebase?

Git Interactive Rebase vous permet de modifier les commits de plusieurs façons, telles que l’édition, la suppression et le compression. Non seulement vous pouvez changer le message de commit, mais vous pouvez également changer le code réel si vous avez fait une erreur. C’est un outil puissant qui vous donne un contrôle total sur l’historique des commits de votre projet.

Comment puis-je compresser des commits en utilisant Git Interactive Rebase?

Le fait de « squasher » consiste à combiner plusieurs commits en un seul. Dans Git, vous pouvez squasher des commits en utilisant la commande git rebase -i suivie du hash du commit que vous souhaitez squasher. Dans l’éditeur de texte qui s’ouvre, vous pouvez marquer les commits que vous souhaitez squasher en remplaçant pick par squash ou s à côté de chaque commit.

Quels sont les risques d’utiliser Git Interactive Rebase?

Bien que Git Interactive Rebase soit un outil puissant, il peut être dangereux si ce n’est pas utilisé correctement. Il réécrit l’histoire des commits, ce qui peut poser problème si vous travaillez sur une branche publique sur laquelle d’autres personnes travaillent également. Il est recommandé de l’utiliser sur des branches locales qui n’ont pas encore été poussées.

Comment puis-je résoudre les conflits pendant un Git Rebase?

Pendant un rebase, des conflits peuvent survenir. Git s’arrêtera et vous permettra de résoudre ces conflits avant de continuer. Vous pouvez résoudre les conflits en modifiant les fichiers pour corriger les modifications en conflit, puis en ajoutant les fichiers résolus avec git add. Après avoir résolu tous les conflits, vous pouvez continuer le rebase avec git rebase --continue.

Puis-je utiliser Git Interactive Rebase pour diviser un commit?

Oui, vous pouvez utiliser Git Interactive Rebase pour diviser un commit en plusieurs plus petits. Ceci peut être utile si vous avez apporté plusieurs modifications dans un seul commit mais décidez plus tard qu’elles auraient dû être des commits séparés.

Comment puis-je modifier un message de commit en utilisant Git Interactive Rebase?

Vous pouvez modifier un message de commit lors d’un rebasage interactif. Dans la liste des commits, remplacez pick par reword ou r à côté du commit que vous souhaitez modifier. Lorsque vous continuez, Git ouvrira un éditeur de texte pour chaque commit marqué reword, vous permettant de modifier le message de commit.

Quelle est la différence entre Git Rebase et Git Pull?

Git Pull est une commande qui récupère les modifications d’un dépôt distant et les fusionne dans votre branche courante. Par contre, Git Rebase est une commande qui déplace ou combine une séquence de commits vers un nouveau commit de base. Bien que les deux commandes soient utilisées pour intégrer des modifications, elles le font de manières différentes.

Puis-je utiliser Git Interactive Rebase pour changer l’ordre des commits?

Oui, vous pouvez changer l’ordre des commits en utilisant Git Interactive Rebase. Dans la liste des commits, vous pouvez simplement changer l’ordre des lignes pour modifier l’ordre des commits. Cela peut être utile si vous souhaitez rendre votre historique de commits plus logique ou clair.

Source:
https://www.sitepoint.com/git-interactive-rebase-guide/