Using Git Bisect to Find Bugs Autonomously

Combining binary search with automated testing

Using Git Bisect to Find Bugs Autonomously

I have written elsewhere on this lesser known git utility, but it’s worth showing how with some simple scripting, git bisect can be used to find which commit contains bad code without any further intervention on your part.

But first, what is git bisect?

If you have ever taken an algorithms course, you have probably learned about binary search algorithms. Git bisect uses that same logic to check commits between a start and end (good and bad/failing) commit to find which commit introduced the erroneous code. For large and complex codebases, particularly ones that you aren’t familiar with, this can sometimes be much quicker than trying to debug using conventional methods.

A basic use case looks like this: a large application that your team supports is returning bad data for a specific use case. You’re on point to fix it, but you’ve never coded in this repository before. There are automated functional tests for that use case, and they are failing, as expected. A month ago, they were passing, but no one knows when they started failing, and a lot of code has been committed in the past month.

First, tell git that we intend to do a search.

git bisect start

And follow up by telling it a commit that you know is bad. If you have the latest code currently checked out, you can omit a hash, otherwise provide a specific commit hash (such as efg from my beautiful drawing above).

git bisect bad efg

Next, tell git what a known good commit is.

git bisect good abc

Git will now check out a commit that is in the middle of the two you provided. You will run your tests, and then tell git whether the bug is still present with the commands git bisect good or git bisect bad. After several iterations, git will spit out a single commit hash which should contain the code changes that introduced your bug. Once you are finished, exit the bisect mode with git bisect reset.

Lets automate this process.

This already can seem like magic, but we can make it even better. You already have automated tests in your application (right?) which return a non-zero value when they fail. With some basic scripting, we can tell git bisect to run your tests after checking out commits, so that you don’t have to do it manually.

git bisect run ./some_script

After telling git what your initial good and bad commits are, you use git bisect run. That’s it!

Well, almost. You’ll need to write that script first that can determine whether the application is passing or failing your tests. A simple example for a node application might look like this:

#!/bin/bash

#install dependencies
npm install

#run tests
npm run test ./test/functional/spec/api.js

#return the exit code of the test command
exit $?

Using your script, git will run a binary search between the good and bad commits to find where your bug was introduced.

Have fun debugging, and if this little tutorial helped you out, please leave a comment.

Thanks for reading my newsletter! Subscribe for free to receive new posts and support my work.