Using Git Bisect for Finding When a Bug Was Introduced

Previously I wrote about updating a framework, automated tests, and included a brief mention of `git bisect`. I’d like to expand on the power of `git bisect` and your repository.

First a definition of the command:

git-bisect – Find by binary search the change that introduced a bug

The man page is quite helpful, but its application may not be immediately obvious. This has been my use case.

Step 1 – Prepare Your Bisect

$ git bisect start
$ git bisect bad
$ git bisect good 3f5ee0d32dd2a13c9274655de825d31c6a12313f

First, we tell git that we are starting the bisect. Then we indicate at what point we first noticed the bug – in this case HEAD. Finally we indicate at what point we were bug free – in this case at commit 3f5ee0d32dd2a13c9274655de825d31c6a12313f.

Step 2 – Start Your Engines

$ git bisect run ./path/to/test-script

We’ve told git-bisect which commits were good, and bad. Then with the above command, git will iteratively step through history and run the ./path/to/test-script. And what is ./path/to/test-script? It is any executable file that exits with a 0 status or not 0 status [learn more].

If the test-script exits with status 0, the current commit is considered good. Otherwise it is considered bad. Eventually git-bisect will converge on the commit that introduced the bad result and report the bad commit log entry.

Script Use Cases

So what is this ./path/to/test-script? Sometimes I’ve used `rake` for my Rails project. But that can be overkill. I’ve also ran bisect with one of the test files as the Good/Bad indicator (i.e. ruby ./test/unit/page_test.rb). In these cases, the tests were in my repository, which meant they were equally volatile.

I have also written a script that sat outside the repository I was bisecting. This was really powerful when my manager asked “When did this seemingly strange behavior get introduced?”

I wrote a Capybara test that automated the steps my manager reported for reproducing the error and an assertion of the expected behavior.

Sure enough, a few weeks prior, I had introduced the odd behavior as a side-effect. At the time I didn’t have test coverage for that particular behavior. I patched the error, answered my managers question, and had an automated test that I could drop into my repository to make sure I didn’t reintroduce that behavior.

As with most git utilities, I’m sure I’m only scratching the surface of git-bisect, but even with only using my above process, I’ve saved plenty of time and mental energy.

I have also created, long ago, a repository that highlights and automates several git commands. Follow the directions and it will walk you through a series of commits.