By admin , 29 April 2026

Binary search through history

git bisect performs binary search across commits. Tell it a known-good commit and a known-bad commit; it checks out the midpoint and asks you to mark it good or bad. After log2(N) steps, it identifies the first bad commit. For 1024 commits, that is ten checks.

Manual bisect

git bisect start
git bisect bad HEAD
git bisect good v2.4.0
# Git checks out the middle commit. Test it.
git bisect good        # if the bug is absent
git bisect bad         # if the bug is present
# Repeat until Git prints the offending SHA
git bisect reset       # return to HEAD

Automated bisect

If you can write a script that exits 0 for "good" and non-zero for "bad", bisect runs unattended:

git bisect start HEAD v2.4.0
git bisect run ./scripts/reproduce-bug.sh

The script can be a unit test, a curl-and-grep, or anything that decisively classifies a commit.

Skipping untestable commits

If a checked-out commit cannot be evaluated (broken build, missing dependency, irrelevant), skip it:

git bisect skip

Bisect will pick a nearby commit instead.

Bisect with terms beyond good/bad

Hunting for a regression where the issue is "slow" rather than "broken"? Customise the terms:

git bisect start --term-old=fast --term-new=slow
git bisect slow HEAD
git bisect fast v2.4.0

What makes bisect feasible

Bisect is most powerful when:

  • Commits are atomic - each commit builds and tests pass.
  • Tests are reproducible - flaky tests poison bisect.
  • The bug is deterministic - intermittent bugs need scripted retry logic.

A real-world example

You discover a memory leak in production. The last release was fine; HEAD leaks. Run:

git bisect start HEAD v3.0.0
git bisect run ./test-memory.sh

An hour later, bisect prints the SHA of the commit that introduced the leak. You diff that one commit and the cause is in 30 lines instead of 30,000.

Bisecting merge commits

Pass --first-parent to bisect only along trunk:

git bisect start --first-parent HEAD v2.4.0

This avoids descending into feature branch interiors when the bug was integrated as a merge.

Visualising progress

git bisect log
git bisect visualize        # opens gitk on the candidate range

Bisect turns "I have no idea what broke this" into a 20-minute, mechanical exercise. Internalise the workflow; it pays off the first time you have to find a regression in a thousand-commit window.