git bisect
Apprenez la commande git bisect pour effectuer une recherche binaire dans votre historique et identifier le commit qui a introduit un bug.
La commande git bisect vous aide à trouver le commit exact qui a introduit un bug en effectuant une recherche binaire dans votre historique. Vous indiquez à Git un commit où le code fonctionnait (« good ») et un où il est cassé (« bad »), et Git extrait successivement le point médian pour que vous le testiez, réduisant de moitié la plage suspecte à chaque étape jusqu'à ce qu'il ne reste qu'un seul coupable.
Ce chapitre explique comment lancer une session bisect manuellement, comment lire la progression affichée par Git après chaque réponse, comment automatiser toute la recherche avec une commande de test, comment ignorer les commits non testables, et comment récupérer en cas d'erreur.
Définition
Pourquoi la recherche binaire
Si un bug est apparu quelque part dans les 1 000 derniers commits, les vérifier un par un serait épuisant. La recherche binaire nécessite seulement une dizaine de tests pour identifier le coupable, car chaque réponse divise par deux les candidats restants — environ log2(N) étapes pour N commits. git bisect automatise la gestion des étapes afin que vous n'ayez qu'à répondre à « est-ce que ça fonctionne ici ? »
Démarrer une session bisect
Commencez la session, puis marquez l'état actuel comme cassé et un commit passé connu comme fonctionnel :
git bisect start
git bisect bad # the current commit is broken
git bisect good v1.4.0 # this tag was known to workGit extrait un commit situé à mi-chemin entre les deux. Vous compilez et testez cette révision, puis signalez le résultat :
git bisect good # this commit works — bug is newer
# or
git bisect bad # this commit is broken — bug is here or olderAprès chaque réponse, Git affiche la portion restante de la plage et extrait le prochain point médian :
Bisecting: 7 revisions left to test after this (roughly 3 steps)
[a1b2c3d4...] Refactor the parserRépétez la boucle test-et-marquage jusqu'à ce que Git annonce le premier commit défectueux :
a1b2c3d4 is the first bad commit
commit a1b2c3d4...
Refactor the parserLire le résultat avec git bisect log
À tout moment, vous pouvez consulter les réponses déjà données. C'est également utile pour conserver un enregistrement de la session :
git bisect logSi vous pensez avoir marqué un commit de façon incorrecte, réinitialisez et rejouez un journal corrigé plutôt que de recommencer depuis le début :
git bisect log > bisect-run.txt # edit out the mistaken line
git bisect reset
git bisect replay bisect-run.txtTerminer la session
Quand Git signale le coupable, retournez à votre état de départ :
git bisect resetCela restaure HEAD sur la branche où vous vous trouviez avant le bisect.
Automatiser avec git bisect run
Si vous pouvez exprimer le test sous forme de script ou de commande qui renvoie 0 pour good et une valeur non nulle pour bad, Git effectuera toute la recherche sans intervention :
git bisect start HEAD v1.4.0
git bisect run npm testGit extrait chaque point médian, exécute la commande, interprète le code de sortie et s'arrête sur le premier commit défaillant — aucun marquage manuel requis.
La commande peut être n'importe quel exécutable : une ligne de commande, un script shell ou un binaire. Le code de sortie 0 signifie good, tout code entre 1 et 127 (sauf 125) signifie bad. Le code de sortie spécial 125 indique à Git que le commit ne peut pas être testé et équivaut à exécuter git bisect skip — utilisez-le lorsque la compilation elle-même échoue à cette révision :
#!/bin/sh
# test.sh — skip commits that don't even compile
make || exit 125
./run-the-failing-case # exits non-zero when the bug is presentgit bisect start HEAD v1.4.0
git bisect run ./test.shgit bisect run doit être idempotente et autonome. Si votre test laisse des artefacts de compilation ou des fichiers modifiés, ajoutez une étape de nettoyage pour que le prochain checkout parte d'un état propre — sinon un binaire obsolète peut faire passer un bon commit pour un mauvais.Ignorer les commits non testables
Parfois le commit extrait est cassé pour une raison sans rapport — il ne compile pas ou une dépendance est manquante — et vous ne pouvez donc vraiment pas répondre « good » ou « bad ». Demandez à Git de le mettre de côté :
git bisect skipGit choisit un commit voisin et continue à réduire la plage. Si trop de commits dans une zone sont ignorés, Git peut signaler une plage de candidats plutôt qu'un commit unique.
Options courantes
| Commande | Description |
|---|---|
git bisect start | Démarre une session bisect. |
git bisect bad [<commit>] | Marque un commit comme défectueux (par défaut le commit actuel). |
git bisect good [<commit>] | Marque un commit comme fonctionnel. |
git bisect skip | Ignore un commit qui ne peut pas être testé (par exemple, il ne compile pas). |
git bisect run <cmd> | Automatise la recherche en utilisant le code de sortie d'une commande de test. |
git bisect log | Affiche les réponses good/bad données jusqu'à présent. |
git bisect replay <file> | Rejoue un journal bisect sauvegardé. |
git bisect reset | Termine la session et restaure le HEAD d'origine. |
Commandes associées
Une fois que bisect indique le coupable, ces commandes vous aident à l'inspecter et à agir :
- git show — affiche les modifications exactes introduites par le commit défectueux.
- git blame — indique quel commit a modifié une ligne spécifique en dernier.
- git log — parcourt l'historique dans lequel bisect a effectué sa recherche.
- git revert — annule le commit défectueux sans réécrire l'historique.
- git checkout — la façon dont Git déplace
HEAD, utilisée en interne par bisect.