Anti-regression Training: git bisect (Part 2)

Part 2 of 2

In part 1 I talked about how git bisect can save your project a lot of headaches, and how it can save you as a developer a lot of grief. Here in part 2, I’ll go over how to use git bisect.

Git bisect does a binary search from . If you’re still interested in the article, you’re probably a developer and know what this means already. I’ve been having fun with Inkscape the past few days and made a picture though:

A developer has determined in line 1 that the bug is present at the tip of the code (red) and has determined a known working version in the past (by guessing and testing) in green. I usually do this by checking out the version from about 100 or 200 commits ago, and checking if this version has the bug present. Once you have any known working version, (say, version B) to start git bisect, check out the head again and do:

git status
git bisect start
git bisect bad HEAD
git bisect good B

Git will now automatically checkout the midpoint (shown in blue) between the bad version, HEAD (version A) and the bug-free version, version B. This is shown on the second line of the picture. You, the dev, compile the blue commit selected automatically by git and test it. In this particular scenario, you determine the bug is still present on this version, so you enter
git bisect bad
Git now knows that the regression you’re searching for is not between version A and the blue commit. Had the commit been bug-free, you would have said git bisect good
This process continues, cutting the number of potential problem commits in half each time.

This takes log2(A-B) steps, logarithmically less tests than testing each commit! This process continues until there are no more commits to test, and git bisect will spit out the commit (including the commit message, sha hash, etc) of the first bad commit. You now know what chunk of code to blame for your bug!

Advanced Usage

In some cases, the blue commit is simply not testable. Sometimes the blue commit is at a point where the entire program doesn’t work well enough to test, sometimes it doesn’t compile. It can be a myriad of reasons. In this case, typing git bisect skip will force git bisect to pick another commit near the blue one to test in the next step. This potentially could leave git bisect without a final commit to blame. For instance, if a bad commit is surrounded by untestable commits, git bisect won’t be able to figure out the bad commit, but probably 4/5 times, git bisect skip will get you out of a tight spot where the commit isn’t testable.

git bisect visualize fires up the graphical “gitk” program to view what is going on graphically, like I did with inkscape.

git bisect log prints a text log of the steps that have happened. Useful if you enter a bad git bisect message.

git bisect replay will replay a sequence of steps generated by git bisect log

git bisect reset will bail out of git bisect, returning you to the head before you started the bisection.

Automated Testing

The last cool thing git bisect can do, is perform these steps manually. You have to create a script (in any language you like) that carries out the compilation steps and the test procedure. If this script returns a 1, then the script determines that the commit was bad. A 0 on return, the commit passed the test case. Git bisect works through all the commits automatically

Example script: test_script.sh
./program arg1 arg2

With that script in place, we can just run
git bisect run test_script.sh
and git would automatically show us the first bad commit!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.