Publié par
Il y a 2 années · 5 minutes · Craft

git essentials – 2 – bisect

gitCeci est le deuxième article d’une série consacrée aux commandes de Git, le système de gestion de révisions décentralisé. Le sujet de cet article est la commande bisect, qui permet de déterminer rapidement quel commit d’une série a causé une anomalie.

Retrouvez le premier article git essentials – 1 – log

Lorsque l’on remarque qu’une anomalie a été introduite dans une application et que l’on cherche à déterminer quelle partie du code source est en cause, il y deux approches possibles :

  • la traditionnelle : on cherche dans tout le code, possiblement aidé par des outils (de débogage, d’étude de performance, etc.) ;
  • la stratégique : on réduit d’abord le nombre de lignes de codes à étudier à un petit nombre, puis on commence à chercher.

Vous m’avez vu venir, je vais ici vous parler d’un outil facilitant grandement la deuxième approche : la commande git bisect.

Qu’est-ce ?

La commande git bisect permet de déterminer quel commit précis a causé une anomalie au moyen d’une recherche dichotomique. Ne soyez pas effrayés par le terme, Git va s’occuper de tout !

En pratique, il faut donner à Git un minimum d’informations de départ (facultatives, mais permettant de réduire le nombre de commits à étudier et donc de converger plus rapidement vers le commit coupable) :

  • le dernier commit où « ça fonctionnait », c’est-à-dire que l’anomalie n’était pas encore apparue ;
  • un commit où il a été remarqué que ça ne fonctionne plus, c’est-à-dire que l’anomalie que vous cherchez est apparue (souvent le commit actuel, HEAD).

À partir de ces deux bornes, Git disposera alors d’un intervalle de commits parmi lesquels se trouve le coupable. Il va :

  1. commencer par selectionner le commit du milieu de l’intervalle et le checkout ;
  2. Ensuite, avec ce commit dans votre copie de travail, à vous de déterminer si l’anomalie est présente ou pas. Suivant votre réponse, Git saura si le coupable se trouve dans la première ou la seconde partie de l’intervalle, c’est-à-dire avant ou après le commit actuellement étudié.
  3. Puis Git va continuer de la même manière : checkout de la version du milieu de l’intervalle restant, à vous de dire si c’est bon ou pas, puis ainsi de suite.

À chaque réponse de votre part, Git divise par deux (environ) le nombre de commits potentiellement coupables, vous permettant ainsi de converger rapidement vers le résultat.

Nous allons à présent mettre en pratique cette technique au travers d’un exemple.

Cas pratique

Prenons un projet d’exemple, versionné sous Git, dont l’historique est le suivant :

Git-bisect

 

 

 

 

 

 

 

Note : si vous voulez savoir comment obtenir la liste des commits avec cette mise en forme, l’article précédent de cette série vous l’expliquera en détail.

Démarrer la « bisection »

La situation de départ est la suivante : au commit actuel, nous remarquons qu’une anomalie est apparue, mais nous ne savons pas quel commit l’a introduite. Par contre, nous savons que l’anomalie n’était pas présente au commit f5d930f « Create file for some test ». Nous allons donc pouvoir commencer la « bisection » (mélange de bi(naire) et dissection) avec la commande :

git bisect start

Puis, nous indiquons que la révision courante, HEAD, comporte l’anomalie :

git bisect bad

Enfin, nous savons qu’à l’époque du commit f5d930f, l’anomalie n’était pas présente :

git bisect good f5d930f

La sortie de la commande est la suivante :

Git-bisect-2

 

 

Nous observons que Git affiche le nombre approximatif d’étapes interactives qu’il reste pour cibler le commit précis ayant introduit l’anomalie.

Si nous faisons un git status, nous observons :

Git-bisect-3

 

 

 

 

Nous voyons que le commit checkout par Git (« HEAD detached at 7aa200f ») est bien au milieu de l’intervalle de commits que nous lui avons fourni au départ :

Git-bisect-4

 

 

 

 

 

Déterminer si le commit contient l’anomalie

Maintenant que git nous a mis la copie de travail dans l’état du commit 7aa200f - « Add magic feature », nous déterminons manuellement si le commit contient l’anomalie (bad) ou non (good), par exemple via l’exécution de tests automatisés ou bien via un test manuel de l’application. Une fois déterminé si l’anomalie est présente, il faut en informer Git. Pour notre exemple, nous dirons que l’anomalie est présente dans ce commit :

git bisect bad

La sortie de la commande nous informe qu’il reste environ 2 étapes interactives dans le processus :

Git-bisect-5

 

 

Git a maintenant checkout la révision suivante à étudier, située au milieu de l’intervalle restant :

Git-bisect-6

 

 

 

 

 

Recommencer…

Nous renouvelons l’opération précédente : déterminer si le commit est good ou bad :

git bisect good

Ce qui nous informe qu’il reste 1 étape :

Git-bisect-7

 

 

Avec le nouveau commit, nous déterminons qu’il est bad :

git bisect bad

Sortie :

Git-bisect-8

 

 

Et une dernière fois :

git bisect good

Ce qui produit la sortie suivante :

Git-bisect-9

 

 

 

Git a donc déterminé que le commit a36645a - « Make more quality » est celui qui a introduit l’anomalie, en seulement 3 étapes alors qu’il y avait 16 commits à étudier !

Terminer

Si nous faisons un git status à ce moment-là, vous remarquerez que nous nous trouvons toujours en état de bisection :

Git-bisect-10

 

Pour retourner à un état normal, nous terminons la procédure par :

git bisect reset

 

Conclusion

Nous avons vu comment rechercher et cibler rapidement un commit fautif. Il est possible d’accélérer ou de faciliter la recherche de plusieurs manières :

  • En fournissant à git bisect la commande (script) à exécuter à chaque étape pour déterminer automatiquement si le commit est good (code de sortie 0) ou bad (autre code de sortie) :
    git bisect run my_script arguments

    À exécuter après le git bisect start.

  • En donnant toutes les entrées d’un coup :
    git bisect start HEAD f5d930f
  • En donnant un chemin, c’est-à-dire une partie de l’arborescence du projet, sur lequel restreindre la recherche (seuls les commits affectant ce chemin seront évalués). Par exemple si on sait que le problème se trouve forcément dans les sources java du projet (pas les fichiers de configuration ou de tests), nous pouvons donner cette information à git :
    git bisect start -- src/main/java/

À bientôt pour le prochain article de cette série !

Bastien Bonnet
Bastien est un développeur disposant de 4 ans d'expérience. Il est passionné par le développement de logiciel de qualité (code clair, facile à maintenir, robuste face aux régression (tests automatisés)). Agiliste convaincu, il s'inscrit parfaitement dans le mouvement du software craftsmanship. Il est convaincu et investi dans le partage de connaissance pour améliorer le niveau technique et les compétences de son équipe.

2 thoughts on “git essentials – 2 – bisect”

  1. Publié par homer242, Il y a 2 années

    Article très intéressant et clair. Merci !

  2. Publié par mirelsol, Il y a 2 années

    Très bon article, merci !

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *