Un guide pour réparer les erreurs avec Git (Partie 2)
Publié: 2022-03-10Dans cette deuxième partie de notre série sur "Réparer les erreurs avec Git", nous regarderons à nouveau courageusement le danger dans les yeux : j'ai préparé quatre nouveaux scénarios apocalyptiques, y compris, bien sûr, des moyens astucieux de nous sauver la peau ! Mais avant de plonger : jetez un œil aux articles précédents sur Git pour encore plus de méthodes d'auto-sauvetage qui vous aideront à réparer vos erreurs avec Git !
Allons-y!
Récupérer une branche supprimée à l'aide du Reflog
Avez-vous déjà supprimé une branche et, peu de temps après, réalisé que vous n'auriez pas dû ? Dans le cas improbable où vous ne connaissez pas ce sentiment, je peux vous dire que ce n'est pas bon. Un mélange de tristesse et de colère monte en vous, alors que vous pensez à tout le travail acharné qui a été consacré aux commits de cette branche, à tout le code précieux que vous avez maintenant perdu.
Heureusement, il existe un moyen de ramener cette branche d'entre les morts - avec l'aide d'un outil Git nommé "Reflog". Nous avions utilisé cet outil dans la première partie de notre série, mais voici un petit rappel : le Reflog est comme un journal où Git note chaque mouvement du pointeur HEAD dans votre dépôt local. En d'autres termes, moins ringards : chaque fois que vous passez à la caisse, validez, fusionnez, rebasez, sélectionnez, etc., une entrée de journal est créée. Cela fait du Reflog un filet de sécurité parfait lorsque les choses tournent mal !
Prenons un exemple concret :
$ git branch * feature/login master
Nous pouvons voir que nous avons actuellement extrait notre feature/login
branche. Disons que c'est la branche que nous allons supprimer (par inadvertance). Avant de pouvoir le faire, cependant, nous devons passer à une autre branche car nous ne pouvons pas supprimer notre branche HEAD actuelle !
$ git checkout master $ git branch -d feature/login
Notre précieuse branche de fonctionnalités a maintenant disparu - et je vous accorderai une minute pour (a) comprendre la gravité de notre erreur et (b) pleurer un peu. Après que vous ayez essuyé les larmes, nous devons trouver un moyen de ramener cette branche ! Ouvrons le Reflog (en tapant simplement git reflog
) et voyons ce qu'il nous réserve :
Voici quelques commentaires pour vous aider à donner un sens à la sortie :
- Tout d'abord, il faut savoir que le Reflog trie ses entrées par ordre chronologique : les éléments les plus récents sont en tête de liste.
- L'élément le plus haut (et donc le plus récent) est la
git checkout
que nous avons exécutée avant de supprimer la branche. Il est enregistré ici dans le Reflog parce que c'est l'un de ces "mouvements du pointeur HEAD" que le Reflog enregistre si consciencieusement. - Pour réparer notre grave erreur, nous pouvons simplement revenir à l'état d' avant - qui est également proprement et clairement enregistré dans le Reflog !
Essayons donc ceci, en créant une nouvelle branche (avec le nom de notre branche "perdue") qui commence à cet état "avant" du hachage SHA-1 :
$ git branch feature/login 776f8ca
Et voila ! Vous serez ravi de voir que nous avons maintenant restauré notre branche apparemment perdue !
Si vous utilisez une interface graphique de bureau Git telle que "Tower", vous pouvez prendre un joli raccourci : appuyez simplement sur CMD + Z sur votre clavier pour annuler la dernière commande - même si vous venez de supprimer violemment une branche !
Déplacer un commit vers une autre branche
Dans de nombreuses équipes, il existe un accord pour ne pas s'engager sur des branches de longue durée comme main
ou develop
: des branches comme celles -ci ne devraient recevoir de nouveaux commits que par le biais d'intégrations (par exemple, fusions ou rebases). Et pourtant, bien sûr, les erreurs sont inévitables : on oublie parfois et on commet quand même sur ces branches ! Alors, comment pouvons-nous nettoyer le gâchis que nous avons créé ?
Heureusement, ces types de problèmes peuvent être facilement corrigés. Retroussons nos manches et mettons-nous au travail.
La première étape consiste à basculer vers la bonne branche de destination, puis à déplacer le commit en utilisant la commande cherry-pick
:
$ git checkout feature/login $ git cherry-pick 776f8caf
Vous aurez maintenant le commit sur la branche souhaitée, là où il aurait dû se trouver en premier lieu. Impressionnant!
Mais il reste encore une chose à faire : nous devons nettoyer la branche où elle a atterri accidentellement en premier ! La commande cherry-pick
, pour ainsi dire, a créé une copie du commit — mais l'original est toujours présent sur notre branche de longue date :
Cela signifie que nous devons revenir à notre branche de longue date et utiliser git reset
pour la supprimer :
$ git checkout main $ git reset --hard HEAD~1
Comme vous pouvez le voir, nous utilisons ici la commande git reset
pour effacer le commit défectueux. Le paramètre HEAD~1
indique à Git de "revenir 1 révision derrière HEAD", effaçant ainsi le commit le plus élevé (et dans notre cas : indésirable) de l'historique de cette branche.
Et voilà : le commit est maintenant là où il aurait dû être en premier lieu et notre branche de longue date est propre — comme si notre erreur ne s'était jamais produite !
Modification du message d'un ancien commit
Il est trop facile d'introduire une faute de frappe dans un message de validation et de ne la découvrir que bien plus tard. Dans un tel cas, la bonne vieille option --amend
de git commit
ne peut pas être utilisée pour résoudre ce problème, car elle ne fonctionne que pour le tout dernier commit. Pour corriger tout commit plus ancien que cela, nous devons recourir à un outil Git appelé "Interactive Rebase".
Tout d'abord, nous devons indiquer à Interactive Rebase quelle partie de l'historique des commits nous voulons modifier. Cela se fait en lui alimentant un hash de commit : le commit parent de celui que nous voulons manipuler.
$ git rebase -i 6bcf266b
Une fenêtre d'édition s'ouvrira alors. Il contient une liste de tous les commits après celui que nous avons fourni comme base pour le rebase interactif dans la commande :
Ici, il est important que vous ne suiviez pas votre première impulsion : dans cette étape, nous n'éditons pas encore le message de validation. Au lieu de cela, nous disons seulement à Git quel type de manipulation nous voulons faire avec quel(s) commit(s). Très commodément, il y a une liste de mots-clés d'action notés dans les commentaires au bas de cette fenêtre. Dans notre cas, nous marquons la ligne #1 avec reword
(remplaçant ainsi le pick
standard).
Tout ce qui reste à faire dans cette étape est d'enregistrer et de fermer la fenêtre de l'éditeur. En retour, une nouvelle fenêtre d'éditeur s'ouvrira contenant le message actuel du commit que nous avons marqué. Et c'est enfin le moment de faire nos montages !
Voici tout le processus en un coup d'œil pour vous :
Corriger un commit cassé (d'une manière très élégante)
Enfin, nous allons jeter un œil à fixup
, le couteau suisse des outils d'annulation. En termes simples, cela vous permet de corriger un commit cassé/incomplet/incorrect après coup. C'est vraiment un outil merveilleux pour deux raisons :
- Peu importe quel est le problème.
Vous avez peut-être oublié d'ajouter un fichier, supprimé quelque chose, effectué une modification incorrecte ou simplement une faute de frappe.fixup
fonctionne dans toutes ces situations! - C'est extrêmement élégant.
Notre réaction normale et instinctive face à un bogue dans un commit est de produire un nouveau commit qui résout le problème. Cette façon de travailler, aussi intuitive qu'elle puisse paraître, rend votre historique de commit très chaotique, très bientôt. Vous avez des commits "d'origine", puis ces petits commits "de pansement" qui corrigent les problèmes qui se sont produits dans les commits d'origine. Votre historique est jonché de petits commits de pansement dénués de sens, ce qui rend difficile la compréhension de ce qui s'est passé dans votre base de code.
C'est là que fixup
entre en jeu. Elle vous permet de toujours faire ce commit de pansement correctif. Mais voici la magie : il l'applique ensuite au commit original et cassé (en le réparant de cette façon), puis supprime complètement le vilain commit de pansement !
Nous pouvons passer par un exemple pratique ensemble ! Disons que le commit sélectionné ici est cassé.
Disons également que j'ai préparé des modifications dans un fichier nommé error.html
qui résoudra le problème. Voici la première étape que nous devons faire :
$ git add error.html $ git commit --fixup 2b504bee
Nous créons un nouveau commit, mais nous disons à Git qu'il s'agit d'un commit spécial : c'est un correctif pour un ancien commit avec le hachage SHA-1 spécifié ( 2b504bee
dans ce cas).
La deuxième étape consiste maintenant à démarrer une session Interactive Rebase, car la fixup
appartient au grand ensemble d'outils d'Interactive Rebase.
$ git rebase -i --autosquash 0023cddd
Deux choses méritent d'être expliquées à propos de cette commande. Tout d'abord, pourquoi ai-je fourni 0023cddd
comme hachage de révision ici ? Parce que nous devons démarrer notre session Interactive Rebase au niveau du commit parent de notre compagnon brisé.
Deuxièmement, à quoi sert l'option --autosquash
? Cela nous enlève beaucoup de travail ! Dans la fenêtre de l'éditeur qui s'ouvre maintenant, tout est déjà préparé pour nous :
Grâce à l'option --autosquash
, Git a déjà fait le gros du travail pour nous :
- Il a marqué notre petit commit de pansement avec le mot-clé d'action de
fixup
. De cette façon, Git le combinera avec le commit directement au- dessus , puis le supprimera. - Il a également réorganisé les lignes en conséquence, déplaçant notre commit de pansement directement sous le commit que nous voulons corriger (encore une fois : le
fixup
fonctionne en combinant le commit balisé avec celui ci- dessus !).
En bref : Il n'y a rien à faire pour nous que de fermer la fenêtre !
Jetons un dernier regard sur le résultat final.
- Le commit précédemment cassé est corrigé : il contient désormais les modifications que nous avons préparées dans notre commit de pansement.
- L'affreux commit de pansement lui-même a été abandonné : l'historique des commits est clair et facile à lire, comme si aucune erreur ne s'était produite.
Savoir réparer les erreurs est un super pouvoir
Toutes nos félicitations! Vous êtes maintenant capable de sauver votre peau dans de nombreuses situations difficiles ! Nous ne pouvons pas vraiment éviter ces situations : quelle que soit notre expérience en tant que développeurs, les erreurs font tout simplement partie du travail. Mais maintenant que vous savez comment les gérer, vous pouvez les affronter avec un rythme cardiaque décontracté.
Si vous voulez en savoir plus sur la correction des erreurs avec Git, je peux vous recommander le "Kit de premiers secours pour Git" gratuit, une série de courtes vidéos sur exactement ce sujet.
Amusez-vous à faire des erreurs et, bien sûr, à les défaire facilement !