Bug hunting with git bisect

So, my friend Juan G Hurtado is blogging about Git and sharing some recipes lately. I am going to get ahead on this one about a nice tool that you may not use often, but that will prove worthwile when you do: git bisect

Let’s play a small roleplaying here, shall we? Imagine that you are working with a bunch of other devs in a project, coding and commiting like there’s no tomorrow. And I mean a lot of commiting, because you all are using Git and it simply rocks how easy and fast it is. All of a sudden, a certain functionality is reported not to be working correctly, despite its test (you do test, don’t you?) succeeding. So, unfortunately, your tests weren’t as good as you thought they were (this kind of thing happens, you know) and you find yourself in this kind of situation in which you are not really sure when the system stopped working correctly. Damn.

Fear no more, because with git bisect you will find the problem in a breeze. All it does is performing a binary search between a commit in which everything worked perfectly and one in which it does not until it finds the offending one.

So it works like this, you start by typing git bisect start and then you mark the current revision as a failing one with git bisect bad. After that, find a commit which is working as expected (ie, 805f87d) and type git bisect good 805f87d. Git will start to iterate between the different commits asking for your input so that it knows whether the current commit works okay or not. Find a complete example below:

[email protected]:~/Projects/config
> git bisect start                                                                                                                                                                             master [56ab365]

[email protected]:~/Projects/config
> git bisect bad                                                                                                                                                                               master [56ab365]

[email protected]:~/Projects/config
> git bisect good 805f87d                                                                                                                                                                      master [56ab365]
Bisecting: 30 revisions left to test after this (roughly 5 steps)
[fbae52a8dcb942c9f57bfbb24e550188f3e1f500] smarter awesome wm autostart module

[email protected]:~/Projects/config (*)
> git bisect bad                                                                                                                                                                            [fbae52a]  modified
Bisecting: 15 revisions left to test after this (roughly 4 steps)
[0ce9d70fcf99d08e62af99acc1ca22e5e23317cf] unset precmd and preexec functions

[email protected]:~/Projects/config (*)
> git bisect bad                                                                                                                                                                            [0ce9d70]  modified
Bisecting: 6 revisions left to test after this (roughly 3 steps)
[147cd96506ecda9bcbf008698cd755a49dfe389c] Merge branch 'master' of github.com:antonio/dotfiles

[email protected]:~/Projects/config (*)
> git bisect good                                                                                                                                                                           [147cd96]  modified
Bisecting: 3 revisions left to test after this (roughly 2 steps)
[4d1684c4467401907b7d59fbf9e125b988f9fc41] opener plugin

[email protected]:~/Projects/config (*)
> git bisect bad                                                                                                                                                                            [4d1684c]  modified
Bisecting: 0 revisions left to test after this (roughly 1 step)
[df372cc78ae0dd7ad9682cdf2173e03a9aef20f2] juanghurtado theme

[email protected]:~/Projects/config (*)
> git bisect good                                                                                                                                                                           [df372cc]  modified
4d1684c4467401907b7d59fbf9e125b988f9fc41 is the first bad commit
commit 4d1684c4467401907b7d59fbf9e125b988f9fc41
Author: Antonio <[email protected]>
Date:   Thu Jan 13 14:43:54 2011 +0100

    opener plugin

:100644 100644 e49543bfc52339d359b6c9c8be194a8b432d2e4a 47eceba05361e1d4c14366eee1788d49e2dfe370 M      .zshrc
:040000 040000 c3963fc6ca3997faba573d4d5b8e708834b9899b e014f61b7f668229e15ee019dd774f6c952456c5 M      zsh

Now that you’ve found the culprit commit, it may be a good time to do some git blame for public humiliation :D

A nice feature is the possibility of writing a shell script that automatically tests the functionality, returning 0 if it works and a number between 1 and 127 (with the exception of 125) if it does not. Given the testing script test.sh, it would go like this

git bisect run test.sh

Check up the git bisect manual for more information on how to use this awesome feature.