Git bisect: The unsung hero for hunting down bugs

The best solution to quickly find that annoying bug among hundreds of commits

Gonçalo Queirós
infraspeak
5 min readJan 28, 2020

--

The year is 2010, a wild bug appears in a code base, but this is no common bug, this is one that likes to play hide and seek among the thousands of lines some feature introduced into the branch you are working on… The year is now 2020 and sadly, this wild bug still visits you from time to time, coming in many shapes and forms, but always using the same technique, hiding between large batches of commits.

We have all lived (and survived) stories like this, where a seamlessly commit introduces a bug that is hard to track down, and though we should deliver small batches of code, we don’t always live in that greenfield.

Back in 2010, I was introduced to one of the git “unsung heroes”: git bisect Since then, it has saved me lots of time hunting down bugs. This is not a tool that you will be using every day (or at least I hope you don’t have to), but when you do, you will really appreciate how a simple tool can accomplish so much.

What does it do

Plain and simple, git bisect allows you to interactively search through a batch of commits until you find the commit that introduced the bug or changes you are looking for. In order to do this, git bisect keeps jumping between commits, while asking you whether the commit you are currently on is working or not. Based on your response, git bisect decides what commit to analyze next, and this process goes on until it finds the commit you are looking for.

How does it work

How does that help me search a batch of 100 commits? The easiest way to answer that question, is to show you the tool in action.

Let’s start by creating an empty repository with 100 commits with each commit message being the commit number from 1 (oldest) to 100 (newest):

If now we perform a git log we should see something similar to:

In a real scenario the only thing that we’d know at this point is that our HEAD contains a bug that wasn’t there in the past. Our first mission is to find a commit where the bug we are searching for doesn’t exist.

To find that commit we can either go back in history to a specific tag where we know things were working, or we can try to go back in steps of 50 commits with git reset --hard HEAD~50 until we find one commit where the bug is not present.

In our scenario, let’s pick commit number 7 whose hash is 5f310beb96815 as the commit that we know things were working.

We kick off bisect with git bisect start and then we inform it about one good and one bad commit:

From the image above we can see that I informed bisect that our good commit is 5f310beb96815 and our bad commit is HEADwhich is the current commit.
With that information, bisect performed a git checkout to a commit between those two (100 and 7). In this case, it is commit 53.

At this point, we have literally rolled back our commit history, and now we just have to check if this commit is exhibiting the bug we are looking for. For our scenario let’s imagine that it is. We need to tell bisect that the commit is bad, using git bisect bad

Since commit 7 was good and 53 was bad, it’s safe to assume that we are looking for a commit between commits 7 and 53, clearing all commits between 53 and 100. That’s exactly what bisect does, so it will move the history to a commit in between 7 and 53. In this case, commit 30.

On commit 30 we test again our code to see if the bug is there. Assuming that it’s not, we inform bisect about that with git bisect good

Having informed bisect that commit 53 is broken but 30 was not, bisect will once again checkout to a commit between these two. In this case, commit 41!

We would keep issuing git bisect good and git bisect bad commands until we find the culprit, in which case we get something similar to this:

I found you, Pikachu!

We found out that commit 42 is our culprit (but that should be no surprise :-), so now we just need to inspect the code it introduced and our quest should be much easier.

The year is 2020, and you no longer fear large chunks of commits coming into your branch. With git bisect as your secret weapon, you know that finding those commits won’t take you much time and energy, and you will be able to use them to solve more interesting riddles.

--

--