How to Use git bisect to Find a Bad Commit
Your build passed at v1.0.0 and fails on main - 50 commits later. git bisect uses binary search to isolate the single breaking commit in log2(50) steps, roughly 6 runs instead of 50. Here's how to run it manually and fully automated.
What git bisect does
git bisect performs a binary search through your commit history. You mark one
commit as good (build passes) and another as bad (build fails). Git checks out
the midpoint commit; you test and mark it good or bad. Repeat until git narrows it
down to the single first-bad commit.
For 50 commits that's at most log2(50) = 6 test runs - regardless of which commit is the culprit.
Manual bisect
cd /workspace/repo
git bisect start
git bisect bad HEAD # current commit is broken
git bisect good v1.0.0 # this tag built clean
# git checks out the midpoint - test it, then mark it:
./build.sh && git bisect good || git bisect bad
# repeat until git prints:
# "<sha> is the first bad commit"
git bisect reset # return to HEAD when done
After git bisect reset you're back on your original branch, no detached HEAD left
behind.
Automated bisect with git bisect run
If you have a script that exits 0 for a good commit and non-zero for a bad one,
hand it to git bisect run and let git drive the whole search:
git bisect start
git bisect bad HEAD
git bisect good v1.0.0
git bisect run ./build.sh
# git runs build.sh at each midpoint automatically
# output ends with: "<sha> is the first bad commit"
git bisect reset
Git reads the script's exit code at each step and picks the next midpoint itself. The search is fully unattended.
Capturing the bad commit SHA
Once bisect prints the result, grab the SHA and record it:
# After git bisect run finishes, the bad ref is stored:
git rev-parse refs/bisect/bad
# Or parse it from bisect output directly:
git bisect run ./build.sh | grep "is the first bad commit" | awk '{print $1}'
After git bisect reset, inspect that commit to understand what changed:
git show <sha>
Choosing a good bisect script
- Use the fastest reproducer - not the full test suite. If a single unit test or
make buildcatches the regression, use that. Faster script = faster bisect. - The script must be deterministic - a flaky test causes git to mark good/bad commits wrong, leading to a false result.
- Exit
0= good, any non-zero = bad. If your test runner uses other conventions, wrap it in a small shell script that normalizes the exit code.
Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.
Try it in a workspace →What you'll practice
- Running git bisect start / bad / good to set the search range
- Automating the search with git bisect run and a build/test script
- Reading the first-bad commit SHA and inspecting it with git show
FAQ
How does git bisect find the bad commit?
It uses binary search - you mark a known-good and known-bad commit, git checks out the midpoint, you test and mark it, and it keeps halving the range. For 50 commits that's about 6 steps instead of 50.
How do I automate git bisect?
Use git bisect run <script>. The script should exit 0 if the commit is good and non-zero if it's bad. Git runs it at each midpoint automatically and prints the first bad commit's SHA when done.
How do I get back to my branch after git bisect?
Run git bisect reset - it ends the bisect session and checks out the commit you were on before you started, including any branch pointer.
Keep learning
Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.
Open the workspace →