Bisect, mais vu par votre clavier

Dans l’article précédent j’ai expliqué le principe de fonctionnement de Git Bisect avec différentes infographies.

Il est temps de le voir fonctionner sur un exemple réel. Pour rappel, Bisect peut fonctionner selon deux modes:

  1. Semi manuel
  2. Automatique

Utiliser Git en mode semi manuel

Dans ce mode, Bisect se charge de sélectionner les commits à tester, mais nous nous occupons de faire les tests et désigner le commit BAD/GOOD.

Pour préparer la démo on lancera le script bash dans un espace de travail (un répertoire vide) que l’on trouve dans l’annexe A. Il est très simple et je ne le commente pas.

Si je fais un git log je trouve ceci:

commit e8a0a6099dfae050ee2e10db88cdf48aff124689 (HEAD -> master)
Author: XXXXXXX
Date:   Sat Feb 19 20:21:02 2022 +0100

    c7

commit 1217f087a6ee3be013ef350c0c575c1015717934
Author: XXXXXXX
Date:   Sat Feb 19 20:21:01 2022 +0100

    c6

commit 4c62d92f61d8101f6233fe38525ff48349137ea5
Author: XXXXXXX
Date:   Sat Feb 19 20:21:01 2022 +0100

    c5

commit 12d75ff1f1b5f14e84b010461b1f4144c220143d
Author: XXXXXXX
Date:   Sat Feb 19 20:21:01 2022 +0100

    c4

commit 450b45cc663641247782ea7d828639b978746f46
Author: XXXXXXX
Date:   Sat Feb 19 20:21:01 2022 +0100

    c3

commit 3ad35ccdea46fbab272cb24e9d8f353dcbaa948c
Author: XXXXXXX
Date:   Sat Feb 19 20:21:01 2022 +0100

    c2

commit 3f2330a8a0750029ffc4b9b0c802c1a4fa33e66a
Author: XXXXXXX
Date:   Sat Feb 19 20:21:00 2022 +0100

    c1

Nous auront besoin de la valeur des commits.

Dans notre scénario on va dire que l’on détecte une régression alors que nous sommes sur le commit C7. Ce sera notre commit BAD.

Par recoupement on a pu déterminer que le commit C2 était bon. Ce sera notre commit GOOD.

On lance Bisect:

git bisect start

L’affichage de Git bash change légèrement:

2022-02-19_20-28-01

Bisecting indique que Bisect est en cours d’exécution et attend nos instruction. Si on souhaitait sortir de ce mode il suffirait de lancer:

git bisect reste

Désignons GOOD et BAD. BAD est le commit en cours ce que l’on indique ainsi:

git bisect bad

GOOD est le commit C2 dont l’ID est 3ad35c…

git bisect good 3ad35c

Cette fois l’affichage change un peu:

2022-02-19_20-32-36

Bisect sélectionne immédiatement le commit de test. Il s’agit de 12d75… C’est à dire C4.

Il nous appartient de tester ce commit par le moyen de votre choix. Décidons que C4 est BAD et donc que la régression s’est produite plus loin:

git bisect bad

Immédiatement Bisect recherche un nouveau candidat:

2022-02-19_21-46-58

Il s’agit de C3. Décidons que ce commit est GOOD:

git bisect good

2022-02-19_21-49-06

Cette fois Bisect a suffisamment d’informations pour déterminer le premier commit BAD, c’est C4. Il nous l’indique dans un message.

Il ne nous reste plus qu’à identifier le code qui pose problème et le corriger. On sort de Bisect avec:

git bisect reset

Bisect en mode automatique

Bisect automatise déjà la recherche des commits. Mais on peut aller plus loin et lui demander de faire les tests lui-même. La recherche du premier BAD devient alors entièrement automatique. Comment faire?

On a besoin d’un projet de démo, par exemple un projet .NET:

dotnet new console

On peut le tester en lançant:

dotnet run

On va le modifier un peu pour avoir quelque chose à tester.

Premièrement on créé un fichier vide:

touch liste.txt

Ensuite on modifie Program.cs ainsi:

string arguments = args[0];

if (arguments == "pair") {
	Console.WriteLine(4);
} else {
	Console.WriteLine(5);
}

On peut tester facilement:

dotnet run pair

Qui affiche 4.

Il est temps de « gitifier » notre espace de travail. J’ai produit une série de commits:

$ git log
commit 1211b576dad2c5341e37f3b5f898ccc486b115ab (HEAD -> master)
Date:   Sun Feb 20 10:37:22 2022 +0100

    c7

commit 56ea9147d9691f3aee09a958de97dd1e604e265f
Date:   Sun Feb 20 10:34:54 2022 +0100

    c6

commit 87e3182b8523be982359153f774bfb07b10cac6e
Date:   Sun Feb 20 10:34:53 2022 +0100

    c5

commit 4ccaffa3eddeb76f56a393e38d06cd98e0104b59
Date:   Sun Feb 20 10:34:53 2022 +0100

    c4

commit b58d7d569f52991b0a0b5c435cdf8a80d4886a73
Date:   Sun Feb 20 10:34:40 2022 +0100

    c3

commit b12d3da207e6b7f38c0b5937b96fd8aff6d9f3e1
Date:   Sun Feb 20 10:33:46 2022 +0100

    c2

commit 34f2b6abd1b422aedf720bc39eb07578b2b7a05c
Date:   Sun Feb 20 10:32:53 2022 +0100

Lors du commit C3 j’ai créé un bug:

string arguments = args[0];

if (arguments == "paire") {
	Console.WriteLine(4);
} else {
	Console.WriteLine(5);
}

L’appli ne marche donc plus comme avant:

dotnet run pair

Affiche 5 maintenant.

Appelons Bisect à la recousse.

Au début rien ne chance, on doit désigner GOOD et BAD

git bisect start

git bisect bad

git bisect good 34f2b6ab

On a donc besoin de dire à Bisect comment tester la condition BAD/GOOD.

Si le projet avait des tests unitaires, cette commande ferait l’affaire:

git bisect run dotnet test projet

Ce n’est pas le cas, alors on va se débrouiller un peu autrement et faire du batch.

SPOILER: Plus refait depuis des siècles, j’ai mouillé la chemise!!

On a besoin d’un script qui effectue les test et retourne un code d’erreur:

  • 0 si GOOD
  • Valeur entre 1 et 127 si BAD (sauf 125 selon la doc, j’ignore pourquoi)

Je propose ce batch que j’appelle test.bat:

dotnet.exe run pair

call dotnet run pair > output.txt
set /p VAR=<output.txt
echo %VAR%

del output.txt

if "%VAR%"=="5" goto choix1
if "%VAR%"=="4" goto choix2

:choix1
echo bad
exit 1
goto eof

:choix2
echo good
exit 0
goto eof

:eof

Et on lance:

git bisect run test

Bisect fait sa magie:

$ git bisect good 34f2b
Bisecting: 2 revisions left to test after this (roughly 2 steps)
[4ccaffa3eddeb76f56a393e38d06cd98e0104b59] c4

fmirouze@LAP-20180124A MINGW64 /c/git/PROJET ((4ccaffa...)|BISECTING)
$ git bisect run test
running test
Bisecting: 0 revisions left to test after this (roughly 1 step)
[b58d7d569f52991b0a0b5c435cdf8a80d4886a73] c3
running test
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[b12d3da207e6b7f38c0b5937b96fd8aff6d9f3e1] c2
running test
b12d3da207e6b7f38c0b5937b96fd8aff6d9f3e1 is the first bad commit
commit b12d3da207e6b7f38c0b5937b96fd8aff6d9f3e1
Date:   Sun Feb 20 10:33:46 2022 +0100

    c2

 liste.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 liste.txt
bisect run success

Bisect dénonce successivement C4, C3, puis C2 qui est bien le commit qui amène les problèmes.

Il ne reste plus qu’à corriger.

ANNEXE A

Script utilisé dans le premier chapitre:

cls

touch liste.txt

git init
git add *
git commit -m"c1"

echo Blanquette de veau >> liste.txt
git add *
git commit -m"c2"

echo Paella >> liste.txt
git add *
git commit -m"c3"

echo Poire Belle Hélène >> liste.txt
git add *
git commit -m"c4"

echo Baba au rhum >> liste.txt
git add *
git commit -m"c5"

echo Oeuf mayonnaise >> liste.txt
git add *
git commit -m"c6"

echo Soupe à l'oignon >> liste.txt
git add *
git commit -m"c7"

Bibliographie

Votre commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l’aide de votre compte WordPress.com. Déconnexion /  Changer )

Image Twitter

Vous commentez à l’aide de votre compte Twitter. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l’aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s