Jake Worth

Jake Worth

How to Isolate the Breaking Commit With Git Bisect

Published: May 17, 2022 • Updated: February 07, 2023 4 min read

  • git
  • debugging

Something is broken, and you can’t figure out why.

Maybe there are a lot of changes to consider, and isolating that breaking change seems impossible.

Or, maybe you’re curious about how things become broken in your organization.

The command-line tool you need is git-bisect. Git bisect lets you conduct a binary search through your Git commit history to find a breaking commit. In this post, I’ll show how it works with an example.

Git Bisect Start

You’re on main (or master) and something is broken. A white screen. A style regression. An inexplicable error.

Indicate this as your starting point with start:

$ git bisect start
 (git)-[main|bisect]-$

Now we’re at main in a bisect state, per the prompt.

Git Bisect Bad

Let’s note that this commit is broken with bad:

$ git bisect bad
 (git)-[main|bisect]-$

You can verify that it did something with git show, or any command that shows refs:

$ git show
commit 8bec317a (HEAD -> main, refs/bisect/bad)

Note the bad ref at the end.

Find a Good Commit

Now, we need to find a commit in the past where things worked. I usually jump back at least twenty commits to start. When in doubt, jump farther.

$ git checkout HEAD~20
Note: switching to 'HEAD~20'.

Test your code again. Is it still broken? If so, jump back the same amount of commits or more.

Once you find a place where it isn’t broken, that’s a ‘good’ commit. Let’s make a note:

$ git bisect good
Bisecting: 22 revisions left to test after this (roughly 5 steps)
[69d80fa4acjad4bd38e0b802ab87d4a6a3279c40] Merge pull request #8 from repo/branch

As the prompt explains, even though we’ve jumped back forty commits, we are only five steps from an answer!

Continuing the Bisect

Now, we continue the bisect. Test your code on the new commit. Is it still broken? If so, make a note:

$ git bisect bad
Bisecting: 11 revisions left to test after this (roughly 4 steps)
[56988ajc43ab972baf43984a18f4580971cc2450] Remove deprecation warning

If it isn’t broken, swap good for bad.

Continue this process until there are no more commits to test. You’ll see a conclusion like this:

(git)-[v0.2.21~1|bisect]-$ git bisect bad
c66d2c2daja91def4aaaf107da9136c43861296f is the first bad commit
commit c66d2c2daja91def4aaaf107da9136c43861296f 
Author: Some Dev <dev@example.com>
Date:   Tue Aug 28 14:57:00 2018 -0700

    Quickpush to fix all the bugs 😅

 example.gemspec | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

Use show to learn more about your bad commit.

$ git show c66d2c2daja91def4aaaf107da9136c43861296f

Lastly, exit with reset (not stop 😡):

$ git bisect reset
Switched to branch 'main'

To summarize:

# Start
$ git bisect start

# Test your feature and confirm that it's broken
$ git bisect bad

# Travel backward n commits
$ git checkout HEAD~<n>

# Test your feature and find out if it works (or continue jumping back)
$ git bisect good

# Continue until the bad commit is identified...

Git Bisect Run and Using Automated Tests

Have a program that returns 0 for success or 1 for error, like a unit test? Use it to automate your bisect:

$ git bisect start
$ git bisect bad
$ git checkout <any good ref>
$ git bisect good
$ git bisect run <rspec spec/demonstrates_the_feature_spec.rb>

run will complete the entire bisect for you with your test!

A Caveat

For bisect to be useful, you must be committing atomically. If your practice is to squash-merge PRs, or commit swaths of unrelated code with each commit, bisect is only going to tell you that something broke when you merged in some mega PR. That isn’t typically new or useful information.

Why Bother?

Why bother with this technique? Why not just fix the issue and move on?

My advice is to try it a few times when you’re stuck debugging and see. When I have used it, I’ve felt like a forensic scientist, able to glean insights about a tough problem that would have taken me much longer to arrive at another way. You’ll learn how it broke, even when that’s a tough question to answer, and maybe even how things break generally in your organization.

Conclusion

git-bisect is an incredible tool. I hope it helps you.

What are your thoughts on this? Let me know!


Get better at programming by learning with me! Join my 100+ subscribers receiving weekly ideas, creations, and curated resources from across the world of programming.