git bisect

I have long been aware of git bisect but I have never used it. I assumed it was complex as I had never actually read about it properly. In the past when non-obvious regressions have crept in I have stepped through commits, tested and repeated until I found the regression. I have also jumped forward and back doing some sort of manual binary search whilst keeping track of my findings in a markdown file.

Today I had the pleasure of tracking down a regression that was potentially weeks old and I just did not have the energy for my antiquated manual fumbling. So, I read the documentation and found it was far easier than my stupid assumption!

This command uses a binary search algorithm to find which commit in your project’s history introduced a bug. You use it by first telling it a “bad” commit that is known to contain the bug, and a “good” commit that is known to be before the bug was introduced. Then git bisect picks a commit between those two endpoints and asks you whether the selected commit is “good” or “bad”. It continues narrowing down the range until it finds the exact commit that introduced the change.

git-bisect documentation

git bisect session example

Start a bisect session.

$ git bisect start
status: waiting for both good and bad commits

Mark a good commit, a commit where everything still worked. Here I am using a commit hash, you can also use a tag.

$ git bisect good e631aaf
status: waiting for bad commit, 1 good commit known

Now mark a bad commit, a commit where the bug is present (likely the current HEAD).

$ git bisect bad be292f57
Bisecting: 15 revisions left to test after this (roughly 4 steps)
[d1e2ced8f1a0fe0cc6c354ac0e521c5152b9184e] feat: adds login flow

Note the response from git. It tells us how many commits are left to test and how many steps it will take to find the bad commit. Then we see the commit hash and message for the commit that git has checked out for us to test. This is a midpoint commit between the good and bad commits.

Bisecting: 15 revisions left to test after this (roughly 4 steps)
[d1e2ced8f1a0fe0cc6c354ac0e521c5152b9184e] feat: adds login flow

Now run your application and verify if the bug is present or not then mark it as good or bad.

If the bug still exists, mark it as bad.

$ git bisect bad

If the bug is not present, mark it as good.

$ git bisect good

Keep repeating these steps until git tells you it has found a bad commit.

08be2ad is the first bad commit

Bad commit

When git has found the bad commit it will show you the commit details.

commit 08be2ad70aaaea85e41410f5d657dc25f92cfdd9
Author: Jane Doe <[email protected]m>
Date:   Wed Apr 23 14:31:52 2025 +0100

    fix: filter users by role

    affected/files/constants.ts           | 28 +++++++++++++++
    affected/files/User.tsx               |  7 ++--
    affected/files/Users.tsx              | 27 +++++++-------  
    affected/files/types.ts               | 17 ++-------
    affected/files/utils.ts               | 41 +++++++++++-----------

Once done, reset the bisect session to return to your original branch. You now have the bad commit, which is half the work, and can you can debug from there.

git bisect reset

Summary

Save yourself some pain and use git bisect!