Guide

Something worked last week and is broken now. Between the two points there are 600 commits. Checking each one by hand would take a day. git bisect does a binary search over the history instead. Each test halves the range, so it needs about log2(600) ≈ 9.2 tests, which means 10 at most.

Concept

Before you start: a regression is a bug that a working version did not have. Bisect needs two points: one where the bug is absent (good) and one where it is present (bad).

Walking through it: by hand

Mark the current commit as bad, and an old release as good. Git checks out the midpoint. You test it, then mark it good or bad. Git halves the range again.

Bash
$ git bisect start
$ git bisect bad HEAD               # broken now
$ git bisect good v2.14.0           # known good release
Bisecting: 299 revisions left to test after this (roughly 8 steps)
$ ./run-test.sh && git bisect good || git bisect bad   # repeat...

Each step cuts the search space roughly in half. With 600 commits, the answer appears in about 10 tests.

Walking through it: automated

If you have a script that reproduces the bug, let bisect run it. The exit code tells Git the result: 0 means good, 1 to 127 means bad, and 125 means skip, for example when the commit does not build.

Bash
$ git bisect run ./scripts/check-latency.sh
...
4e1f9ab is the first bad commit
$ git bisect reset

A script that turns a day of guessing into a coffee break. Make the reproduction first, then let bisect do the work.

Why it works best with small commits

Bisect assumes every commit can be built and tested. A commit that does not compile returns "skip", which leaves gaps in the search. Huge squashed commits give bisect one large step with many changes inside, so you then need to read that whole diff to find the cause.

Small, self-contained commits make bisect precise. That is one more reason to keep changes small and avoid squashing a large branch into one commit.

Tip

Pair bisect with the debugging habit of making a failure reproducible first. A failing test you can run in seconds is the best input to git bisect run.

Common mistakes

  • Marking the wrong endpoints. Check that the "good" commit really passes, or bisect points you at the wrong change.
  • Forgetting git bisect reset. Your working directory stays on a detached commit until you reset.
  • Using a flaky test. A test that sometimes passes gives wrong good or bad answers. Stabilize it, or run it several times per step.

Check yourself

  • Why does bisect need about 10 tests for 600 commits? Each test halves the remaining range, and 2 to the power of 10 is 1,024, which covers 600.
  • What should a script return for a commit that does not compile? Exit code 125, so bisect skips it.

Key takeaways

  • git bisect binary-searches history in about log2(N) tests.
  • git bisect run with a script that reproduces the bug finds the first bad commit with no manual steps.
  • Exit code 125 skips a commit that does not build.
  • Small, buildable commits make bisect precise. Huge squashed commits do not.

Further learning

Next, see how teams organize branches and PRs so that small commits and clean history are the norm, in team workflows.