Advanced git: Using git bisect to find buggy commits


While every developer today probably has a working knowledge of common git-commands for everyday life, there are some more obscure commands that fewer people know about and even fewer people use. One of these is git bisect. If you ever had a broken build and a large number of commits that had been pushed since the last known good build, then you will very much appreciate, what git bisect can do.

Basically, git bisect helps you find the breaking commit by keeping track of good and bad commits and by assisting with doing a binary search.

An example

Let’s say your current build is broken, and there are 100 commits since the last known good commit. Because 100 are make our example difficult to show on the screen, I will use 10 commits. Your git-history might look something like this:

$ git log --oneline
898ec44 (HEAD -> main) Adds some awesome feature    <--- By this time, the build is broken
e189571 ...
a3776b0 ...
ed4c74f ...
d8d42a8 ...
897faa4 ...     <--- middle commit between last known good and known broken commit
5671670 ...
4ea9391 ...
dc4444d ...
64828e9 ...
25899da Adds some useful feature            <--- Last known good commit

A reasonable strategy to find the breaking commit within a large of commits is to simple use a binary search strategy: Pick the commit in the middle between the last known good commit (25899da) and the current, known broken commit (898ec44). That commit would be 897faa4. Once you have run a build against that commit, you will know whether it is good or bad. Depending on whether it is good or bad you will pick your next commit, again, in the middle between the last known good and bad commit. So, if the 897faa4 was bad, you would now check out 4ea9391, if it was good, you would instead check out a3776b0. Rinse and repeat.

That might sound pretty easy with only ten commits. But once you have many more, it’s easy to lose track of things.

git bisect to the rescue!

With git bisect, you have your own personal assistant that keeps track of good and bad commits and automatically chooses the next commit for you. It’s amazing. This what a debugging session looks like:

# Tell bisect that we need its help:
$ git bisect start

# Tell bisect that the current commit is broken:
$ git bisect bad

# Tell bisect the las known good commit. git bisect will automatically checkout the commit for you!
$ git bisect good 25899da
Bisecting: 5 revisions left to test after this (roughly 2 steps)
[898ec44...] Commit message of this commit

# Now run your test or whatever to determine if the build is good or bad, and tell bisect the result:
$ git bisect good
[a3776b0...] Commit message of this commit

# Again, bisect has checked out a3776b0 for you, so run your test again, and tell bisect the result:
$ git bisect bad

Repeat git bisect good and git bisect bad until bisect tells you, which commit was the first broken commit:

e189571... is the first bad commit
commit e189571...
Author: Stefan Ukena <stefan@ukena.de>
Date:   Thu Oct 14 19:46:20 2021 +0200
...

Let’s hope you don’t need it

Needing to use git bisect to find a breaking commit, is often a sign that something has gone wrong – wronger than normal. As software development teams we will usually try to integrate often and build often, in order to keep the individual change-sets between builds small. But there will come a time in every developer’s life, when it is your job to find a breaking commit in a very, very large change-set. And know you know that in those situations, git bisect is your friend.


See also