By admin , 29 April 2026

Hands-free bisection

Manual bisect requires a human verdict at each step. git bisect run automates the loop: provide a script that exits 0 for good, non-zero for bad, and 125 for "skip this commit." Bisect will drive the search to completion, often unattended.

The contract

Your script must:

  • Exit 0 when the commit is good.
  • Exit between 1 and 124, or 126/127, when bad.
  • Exit 125 when the commit cannot be tested (broken build, missing dependency).
  • Avoid exit codes outside these ranges; 128+ aborts bisect.

Example

#!/usr/bin/env bash
set -e
make clean
make || exit 125              # untestable
./tests/regression-1234 || exit 1
exit 0

Drive bisect with it:

git bisect start HEAD v2.4.0
git bisect run ./bisect-test.sh

Inline one-liners

For quick searches you can avoid a script file:

git bisect run sh -c "make && ./run-test || exit 1"

Performance regressions

Bisect a slowdown by comparing a benchmark against a threshold:

git bisect run sh -c '
  cargo build --release || exit 125
  t=$(./bench --json | jq .ms)
  awk -v t="$t" "BEGIN { exit (t > 250) }"'

The awk trick converts the comparison into the script's exit code.

Flaky tests

If a test is intermittently failing, run it multiple times and consider it good only if all runs pass:

git bisect run sh -c '
  for i in 1 2 3 4 5; do
./flaky-test || exit 1
  done
  exit 0'

Common mistakes

Returning exit code 128 or higher mid-search aborts bisect — wrap commands in || exit 1 to clamp. Forgetting to git bisect reset at the end leaves you on a detached HEAD. Failing to use exit 125 for unbuildable commits causes false bads. Side-effect-laden tests that mutate the working tree confuse subsequent steps; always clean up first.

Reproducible reports

Capture the exact bisect path for postmortems:

git bisect log > bisect.log

Attach this log to the bug ticket; it doubles as a reproduction recipe. See "Automatic bug bisection with git bisect" for the manual fundamentals.