How to Identify the Breaking Commit With Git Bisect
- 8 minutes read - 1681 wordsSome code is broken, and you can’t figure out why. Maybe there are a lot of changes to consider, and identifying that breaking change seems impossible.
Or, maybe you’re curious about how things generally break in your organization. The tool you need is git-bisect
.
Git bisect conducts a binary search through your Git history to find a commit of interest. In this post, I’ll show how it works with an example.
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, a bisect may only tell you that something broke when you merged in a mega PR. That isn’t typically new or useful information.
Start the Bisect
Back to our scenario: you’re on main
and something is broken. A white screen. A style
regression. An inexplicable network error.
Tell Git this as your starting point with start
:
Now we’re at main
in a bisect state, as you can read in the new prompt.
Mark a Bad Reference
The reference we have checked out, main
is bad– it demonstrates the bad
behavior. We note that this commit is broken with bad
:
You can verify that it did something with git show
, or any command that shows
refs:
Note the bad
ref at the end.
Find a Good Reference
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.
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:
As the prompt explains, even though we’ve jumped back forty commits, we are only five steps from an answer!
Continue the Bisect
Now, we continue the bisect. Test your code on the new commit. Is it still broken? If so, make a note:
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:
Use show
to learn more about your bad commit.
Lastly, exit with reset
(not stop
or abort
, as I often mistype 😡):
To summarize all the commands:
Git Bisect Run With Automated Tests
Have a program that returns 0
for success or 1
for error, like a unit test?
Use it to automate your bisect:
run
will complete the entire bisect for you, using your test!
Conclusion
Why bother with this technique? Why not just find and 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 I’m able to answer a question that nobody else can within a reasonable amount of time. There’s something empowering and precise about saying “this broke in the Rails upgrade.” It turns your Git history into a useful resource for learning how to quickly fix things and how things break generally in your organization.
git-bisect
is an incredible tool. I hope it helps you.