git bisect: finding bugs with laser precision

“What? I already fixed this bug! Why is it still happening?” If you don’t have a good test suite or you don’t run it regularly, finding these sorts of regressions can be difficult. Because git makes it really easy to jump to other commits (branches or history), it is very easy to narrow down what commit(s) caused the regression. git bisect helps you do that.
I’m going to go through an example of git bisect to show the basics.

Let’s say we have history that looks something like this (from the official git repo):

All we know is that 8419d2e has the bug and 80bffaf works, so we run git bisect start 8419d2e 80bffaf. Git’s output looks like this:

$ git bisect start 8419d2e 80bffaf
Bisecting: 2 revisions left to test after this
[f28dd4774d4723e8251817e910dbdc5507282113] git-clone: improve error message if
curl program is missing or not executable

Now we’re right in the middle of these commits. We find that the bug existed at this point too, so we run git bisect bad:

$ git bisect bad
Bisecting: 0 revisions left to test after this
[c32da692de332d3c9a0b283066e3786af00f4931] hooks--update: Explicitly check for all
zeros for a deleted ref.

Sure, you could have done that with a temporary branch and git reset --hard, but things get a lot more complicated when merges are involved. git bisect doesn’t have problems walking down branches and keeping track of which sections are good and which sections are bad.

There are a few other options that git bisect has that can help a lot:

git bisect visualize

git bisect log

git bisect replay

git bisect run

git bisect skip

git bisect visualize opens up the range you’re analyzing in gitk which lets you see which sections you’ve discounted as good or bad.

git bisect log shows you history that can be replayed by git bisect replay. Our example’s log looks like this:

If you screw up bisecting, you can use git bisect log, git bisect reset, and git bisect replay to go back and fix your mistakes.

If you can write a script to automatically test your regression, you can use git bisect run. Your script has to do its test and exit with a status code. If the status code is 0, the revision is good; if the status is between 1 and 127 (but not 125), the revision is bad; if the status is anything else (exit -1 is common), the automatic bisect process will stop; if the status is 125, it means skip that revision.

git bisect skip is used to tell git that you can’t test this revision. There can be cases where git won’t know which commit caused the problem if a skipped commit makes the bisect ambiguous.

Most newer version control systems (especially distributed ones) support bisect features. Subversion is the notable exception.