Finding bugs with Git Bisect

A simple yet very useful tool

Alex Tavares
hurb.labs
5 min readJan 17, 2022

--

Have you ever found yourself in a situation in which you need to find where that pesky bug comes from?

Sometimes we only notice it when the code has been updated and has already been running in production for a long time, giving us a hard time trying to trace back to where it was introduced.

With git bisect, we can find the exact commit hash that has started all the trouble, saving us time, especially when we are uncertain of the source of the problem.

How does it work?

We start by telling git bisect a revision (a commit hash, tag, branch name, or any reference to a commit) that we are sure to have the bug and another revision without the bug. Then it will begin the lookup process by checking out to a commit between the bad and the good endpoints provided. After checking out, it will expect us to type bad or good in the terminal to indicate if it is buggy or not.

When we provide this information, using the binary search algorithm, it will know if it has to look to the right or to the left of the assessed commit. So, it will narrow down the range of the last known bad and good commits accordingly, and checking out to the one in the middle so that we have again to type bad or good in the terminal. This process will be repeated until it finds the very first one to have the bug.

There are three main commands we should focus on:

Let’s visualize this process

Below I present to you a hypothetical situation in which we have 5 commits in our Git history and we know that the HEAD (or the 5th commit) has the bug. We also know that the 1st commit does not have the bug. Let’s say we know nothing more than that. So any commit in between could be the first one that introduced it.

A git log displays the following output:

The following illustration depicts that scenario:

Now let’s start the lookup process and provide the bad and good commits with the following commands:

It will then check out to the commit in the middle, which in our case is the 3rd commit.

With the git bisect visualize command, we’re able to see our current state in which the bad commit reference is the 5th commit and the HEAD is the 3rd commit, as expected. Let’s check the output below:

Let’s say that, after some investigation, we found the bug in it. Now we need to tell git bisect that it’s a bad one with the following command:

Then, the algorithm will check out to the 2nd commit. It does it because if the one we were assessing has the bug (the 3rd commit), that means that the ones to its left (in this case the 4th commit) must be buggy too. So it’s time to narrow the range down and look for the next target to its right, which in our case will be our last assessment.

Let’s do a git bisect visualize again to see the current state:

Now, let’s say this is a commit without the bug. Then, we tell git bisect it is a good one:

Since it was our last assessment, the algorithm already knows that the 3rd commit is the first one that introduced the bug, and the bad reference will stay at it.

It then outputs a message saying that it is the first bad commit indeed:

With the commit hash in hand, we can identify the changes that caused the bug and choose the best strategy to fix it.

Now that I already know the bad commit, what should I do?

Just do a git bisect reset and you will be thrown back to the commit you were checked out before the process started.

Doing a git bisect start also cleans up the old state, so that way you start a whole new lookup process.

What if I’m not looking for a bug?

There are times when we’d like to find a commit that is not necessarily a bug. If it were a feature, for instance, it would be confusing to use bad or good to indicate that the commit is the one with or without the feature.

So, in that case, you can use old instead of good and new instead of bad, so you don’t get it confused. It works the very same way.

You can also use git bisect term to define your own terms:

Conclusion

I hope this article helped you get a better understanding of how Git Bisect works and that it proves useful when you need to find a tricky bug, as it is really simple to use and can save us precious time.

There are also more features than the ones shown in this article, like running a script to automate the process, for example. It’s worth checking the documentation if you want to have a complete grasp of the topic.

--

--