It can be hard to fix bugs when you work on a huge code base shared by multiple developers. It is even harder if you have no idea when the bug started happening. You will usually have no idea if you don’t know;

When the bug came to life Which file is the source of the bug Who introduced the bug

This generally happens when the bug is related to a non critical part of the system. Nobody is aware of the problem for a long time until a user discovers and reports it. In the meantime hundreds of commits might have been sent to the repo.

I stumbled upon such a bug this past week when we were working on our latest project: The JotForm Form Designer. We did not discover this bug for a long time because it only happens on iPad, using Chrome. The bug causes a complete browser freeze. As Paul Irish pointed out, Chrome has very limited debugging capabilities on IOS. Thus, I was left with an horrible debug method: checking every single commit, until I found the code change that introduced the bug.

Luckily our revision control system, git, has a very efficient method to do this. It is called git bisect. It allows you to test thousands of commits using a very small number of tests. As is implied from the name of the git command, its efficiency comes from its logarithmic time complex algorithm.

How to Use Git Bisect?

First you need a good version of your code, where the bug has been not introduced yet. Assume the hash of that commit is ‘abc’.

Start bisecting process by calling:

git bisect start

2. Then, mark the current latest version as “bad”:

git bisect bad

3. And, mark the “abc” version as good:

git bisect good ‘abc’

Now, git bisect knows the interval that the bug introduced.

It will immediately start process by checking out literally the middle commit between current head and the commit with hash ‘abc’.

Check if the code is broken or not. If the code is good, type:

git bisect good

If the bug is still there, type:

git bisect bad

Depending on your answer, the git bisect will check out the next version for you. Continue checking versions, and telling git bisect that it is “good” or “bad” like this until you find the exact commit that has broken your software.

Isn’t it great? Now you know exactly what caused the bug, when it was introduced, which files/changes were responsible, who introduced it and you can read the commit message to understand why it was introduced.

Conclusion

After using git bisect for the bug, after 10 tests for roughly 600 commits, I found the culprit. The freeze caused by an update of less.js library from version 1.7.5 to version 2.0.0. One would have never expected that and I believe without git bisect, it would have taken much much more time to identify the bug and resolve it.

It turned out we did not even need less.js v2 and reverting to 1.7.5 has fixed the issue. I still don’t have any idea why our Form Designer broke completely on iOS/Chrome on less.js v2. But I will look into that mystery later.

The surprising thing about this story is that I have been thinking about a solution like this already. I always dreamed of implementing something similar. Even though I use git all day long I had no idea about git bisect. Better late then never: It is great to have a weapon like git bisect in my arsenal.