Mattias Wallander

Developing myself

Find the Bug With Git Bisect

| Comments

git bisect start
git bisect bad 123abc  # skip the commit hash if you want to mark the current position
git bisect good 234bcd

The other day we discovered a really bad bug that in some special circumstances hogged down the web browser tab so much that it had to be killed. I was happy Firefox recently split up the page contents and browser UI in different threads.

We knew we didn’t have this problem before but how could we find where the bug had been introduced without doing a lot of manual labor? Then I remembered a git command that a colleague on a former project was praising regularly. It was git bisect.

git bisect is a command that helps you find a specific commit in which a problem was first seen. It works by doing a binary search from two starting points that you specify by saying that one is good and one is bad.

The difference between linear and binary search is O(n) vs O(log n). That means that for, say, one thousand points the linear search will in the worst case check all one thousand points, but the binary search will only need to do ~10 checks. Maybe you won’t have one thousand commits to check but it will make a difference even on a smaller scale.

Let’s try this out. Start up the search by running this:

git bisect start

The next thing you have to do is find two commits where one is bad, i.e. is has the bug, and one is good, i.e. it does not have the bug. Given that the bug exists at the current position on the branch you’re on, run this:

git bisect bad

You can also add a commit hash to the end of the command to mark a different commit as bad.

Then you have to find some commit where the bug had not been introduced yet. Since the binary search is quite quick I would say you don’t have to fine-tune this selection. Just choose the first commit you can find and then run:

git bisect good 234bcd

After this, git will do the work and you just answer if a commit is good or bad. Git will itself check out a new commit that you need to validate or invalidate and then record the answer by running either git bisect good or git bisect bad. After each command, git checks out another commit using the binary search. After a while it will report that it found the commit that introduced the bug and you can do your magic and hopefully find and fix the problem.

To go back to where you were before you started, just reset the bisecting. This can also be used whenever you want to abort the procedure.

git bisect reset

Of course, you could do all this yourself, but it would mean much more tedious work on your part.