git bisect run
bissection automatique
Si vous avez un système automatisé ./test
script qui a le statut de sortie 0 si le test est OK, vous pouvez automatiquement trouver le bug avec bisect run
:
git checkout KNOWN_BAD_COMMIT
git bisect start
# Confirm that our test script is correct, and fails on the bad commit.
./test
# Should output != 0.
echo $?
# Tell Git that the current commit is bad.
git bisect bad
# Same for a known good commit in the past.
git checkout KNOWN_GOOD_COMMIT
./test
# Should output 0.
echo $?
# After this, git automatically checks out to the commit
# in the middle of KNOWN_BAD_COMMIT and KNOWN_GOOD_COMMIT.
git bisect good
# Bisect automatically all the way to the first bad or last good rev.
git bisect run ./test
# End the bisect operation and checkout to master again.
git bisect reset
Cela suppose bien sûr que si le test script ./test
fait l'objet d'un suivi git, afin qu'il ne disparaisse pas lors d'un commit antérieur pendant la bisection.
J'ai constaté que, très souvent, on peut s'en sortir en copiant simplement le script de l'arbre, et en jouant éventuellement avec les éléments suivants PATH
-et l'exécuter à partir de là.
Bien sûr, si l'infrastructure de test sur laquelle test
dépend de ruptures sur des commits plus anciens, alors il n'y a pas de solution, et vous devrez faire les choses manuellement, en décidant comment tester les commits un par un.
J'ai cependant constaté que l'utilisation de cette automatisation fonctionne souvent, et peut être un énorme gain de temps pour les tests plus lents qui se trouvent dans votre arriéré de tâches, où vous pouvez simplement le laisser fonctionner pendant la nuit, et peut-être avoir votre bug identifié le lendemain matin, cela vaut la peine d'essayer.
Plus de conseils
Rester sur le premier commit défaillant après bisect au lieu de revenir à master
:
git bisect reset HEAD
start
+ initial bad
et good
en une seule fois :
git bisect start KNOWN_BAD_COMMIT KNOWN_GOOD_COMMIT~
est la même chose que :
git checkout KNOWN_BAD_COMMIT
git bisect start
git bisect bad
git bisect good KNOWN_GOOD_COMMIT
Voir ce qui a été testé jusqu'à présent (par manuel) good
et bad
ou run
) :
git bisect log
Exemple de sortie :
git bisect log
git bisect start
# bad: [00b9fcdbe7e7d2579f212b51342f4d605e53253d] 9
git bisect bad 00b9fcdbe7e7d2579f212b51342f4d605e53253d
# good: [db7ec3d602db2d994fe981c0da55b7b85ca62566] 0
git bisect good db7ec3d602db2d994fe981c0da55b7b85ca62566
# good: [2461cd8ce8d3d1367ddb036c8f715c7b896397a5] 4
git bisect good 2461cd8ce8d3d1367ddb036c8f715c7b896397a5
# good: [8fbab5a3b44fd469a2da3830dac5c4c1358a87a0] 6
git bisect good 8fbab5a3b44fd469a2da3830dac5c4c1358a87a0
# bad: [dd2c05e71c246f9bcbd2fbe81deabf826c54be23] 8
git bisect bad dd2c05e71c246f9bcbd2fbe81deabf826c54be23
# bad: [c536b1b7242d5fcf92cd87e9a534bedb1c0c9c05] 7
git bisect bad c536b1b7242d5fcf92cd87e9a534bedb1c0c9c05
# first bad commit: [c536b1b7242d5fcf92cd87e9a534bedb1c0c9c0
Montrer les bons et mauvais refs sur git log pour avoir une meilleure notion du temps :
git log --decorate --pretty=fuller --simplify-by-decoration master
Cela ne montre que les commits avec une référence correspondante, ce qui réduit considérablement le bruit, mais inclut les références autogénérées de type :
refs/bisect/good*
refs/bisect/bad*
qui nous indiquent les engagements que nous avons marqués comme bons ou mauvais.
Pensez à ce répertoire de test si vous voulez jouer avec la commande.
L'échec est rapide, le succès est lent
Parfois :
- l'échec est rapide, par exemple, l'un des premiers tests se brise
- le succès prend un certain temps, par exemple, le test cassé passe, et tous les autres tests dont nous ne nous soucions pas suivent.
Pour ces cas, par exemple en supposant que l'échec se produit toujours dans les 5 secondes, et si nous sommes paresseux pour rendre le test plus spécifique comme nous le devrions, nous pouvons utiliser timeout
comme dans :
#!/usr/bin/env bash
timeout 5 test-command
if [ $? -eq 1 ]; then
exit 1
fi
Cela fonctionne puisque timeout
sort de 124
tandis que l'échec de test-command
sort de 1
.
Statuts de sortie magiques
git bisect run
est un peu pointilleux sur les statuts de sortie :
-
tout ce qui est supérieur à 127 fait échouer la bissection avec quelque chose comme :
git bisect run failed:
exit code 134 from '../test -aa' is < 0 or >= 128
En particulier, un C assert(0)
conduit à un SIGABRT
et sort avec le statut 134, très ennuyeux.
-
125 est magique et fait sauter la course avec git bisect skip
.
L'intention est d'aider à éviter les constructions cassées pour des raisons non liées.
Voir man git-bisect
pour les détails.
Vous pouvez donc utiliser quelque chose comme :
#!/usr/bin/env bash
set -eu
./build
status=0
./actual-test-command || status=$?
if [ "$status" -eq 125 ] || [ "$status" -gt 127 ]; then
status=1
fi
exit "$status"
Testé sur git 2.16.1.
1 votes
@01 : Comme le dit le livre git : effectuer une recherche par force brute dans l'historique du projet .
14 votes
Pas si ///brute :-), il utilise la recherche binaire.
1 votes
"git blame" est similaire à "svn blame". "git bisect" est une chose complètement différente.
1 votes
Pour ce que ça vaut, il y a un bon description de bisect dans Pro Git aussi. La réponse de Sylvain est un autre bon point de vue. Si, après avoir examiné tout cela, vous ne comprenez toujours pas, je vous suggère de poser une question plus spécifique. Les questions générales entraînent des réponses générales.
0 votes
ProGit a une meilleure explication, mais je pense que Sylvain l'explique beaucoup mieux. D'après ce que j'ai compris, il n'y a pas que la recherche.
5 votes
Lien vers le livre mis à jour : git-scm.com/book/en/Git-Tools-Debugging-with-Git#Binary-Search (en anglais)
0 votes
Démonstration très utile : webchick.net/node/99