Q&A
What is Git Bisect?
Overview
When a bug appears but you don't know which of hundreds of commits caused it, testing each one is O(n). git bisect applies binary search: since "good" and "bad" partition history at some boundary commit, you can halve the search space with each test. Finding the culprit among 1,000 commits takes ~10 tests instead of 1,000.
graph TD
A[Known good commit] -.many commits.-> B[Known bad commit]
B --> C[git bisect checks out the midpoint]
C --> D{Test: good or bad?}
D -->|good| E[Bug is in the newer half]
D -->|bad| F[Bug is in the older half]
E & F --> G[Repeat on the remaining half]
G --> H[First bad commit identified]
style C fill:#1e1b4b,color:#fff
The Manual Workflow
git bisect start
git bisect bad # current commit is broken
git bisect good v1.2.0 # this older commit/tag worked
# Git checks out a commit halfway between them; you test it, then:
git bisect good # if this commit works
# or
git bisect bad # if this commit is broken
# ... repeat: Git keeps halving the range ...
# eventually:
# "abc1234 is the first bad commit"
git bisect reset # return to your original HEAD
Each good/bad you report halves the remaining commits. After ~log₂(n) iterations, Git names the first bad commit.
Automated Bisect with a Test Script
If you can write a script that exits 0 when good and non-zero when bad, Git runs the entire bisect automatically:
git bisect start HEAD v1.2.0 # bad=HEAD, good=v1.2.0 in one line
git bisect run ./test.sh # Git runs test.sh on each midpoint
git bisect reset
Example test.sh:
#!/bin/bash
make build || exit 125 # 125 = "skip this commit" (can't be tested)
./run_tests --case bug42 # exit 0 = good, non-zero = bad
exit 125 tells bisect to skip a commit that can't be tested (e.g. won't compile).
Skipping Untestable Commits
git bisect skip # current commit can't be tested; try a nearby one
How the Binary Search Works
Git assumes the property is monotonic: once the bug is introduced it stays "bad." So history splits into a good prefix and a bad suffix, and the boundary is the first bad commit. Binary search finds that boundary: test the middle; if good, the boundary is in the newer half; if bad, it's in the older half; recurse. That's why it's O(log n).
Practical Tips
- Pick a
goodcommit you're confident worked (going too far back wastes steps but is safe; too recent gives a wrong answer). - Keep tests fast and deterministic - flaky tests mislead bisect.
git bisect logrecords your session;git bisect replayre-runs it.- Combine with
git bisect run+ a unit test for fully hands-off culprit-finding.
Why This Matters in Interviews
Git/debugging questions use bisect to test whether you know efficient debugging beyond git log reading. The key points: it's binary search over commit history (O(log n) vs O(n)), the good/bad marking workflow, automation via git bisect run with exit codes, and the monotonicity assumption (bug stays present once introduced). Mentioning exit 125 to skip untestable commits is a strong detail.
Common Pitfalls
- Marking a
goodcommit that actually already had the bug → wrong result. - Flaky/non-deterministic tests giving inconsistent good/bad answers.
- Forgetting
git bisect resetafterward, leaving you on a detached commit. - Using it for non-monotonic bugs (intermittent issues) where the good/bad assumption breaks.
References
git bisectdocs: https://git-scm.com/docs/git-bisect- Pro Git - Debugging with Git: https://git-scm.com/book/en/v2/Git-Tools-Debugging-with-Git