git bisect uses binary search to find the exact commit that introduced a bug.
You tell Git one "good" commit (where the bug didn't exist) and one "bad" commit (where the bug exists). Git checks out the midpoint and asks: good or bad? It keeps halving until it finds the exact commit.
With 1,000 commits between good and bad, bisect finds the culprit in about 10 steps.
# Start bisecting
git bisect start
# Current commit is broken
git bisect bad
# This older commit was fine
git bisect good v1.0.0Bisecting: 15 revisions left to test after this (roughly 4 steps)
[c3d4e5f] Add caching layer
Git checks out a commit in the middle. Test it:
# Run your tests
npm test
# If tests pass:
git bisect good
# If tests fail:
git bisect badRepeat until Git narrows it down:
b2c3d4e is the first bad commit
commit b2c3d4e
Author: Someone <someone@example.com>
Date: Mon Mar 10 2025
Refactor database queries
git bisect resetThis returns you to the branch you were on before bisecting.
If you have a script or test that can determine good/bad automatically, let Git run it for you.
git bisect start HEAD v1.0.0
git bisect run npm testrunning 'npm test'...
...
b2c3d4e is the first bad commit
git bisect start HEAD v1.0.0
git bisect run ./test-bug.shThe script must exit with code 0 for good and 1 (or 125 to skip) for bad.
#!/bin/bash
# Check if the specific bug exists
grep -q "broken_function" app.js && exit 1 || exit 0Sometimes a commit can't be tested (doesn't compile, for example):
git bisect skipGit will try a nearby commit instead.
git bisect loggit bisect start
# bad: [e4f5a6b] HEAD
git bisect bad e4f5a6b
# good: [a1b2c3d] v1.0.0
git bisect good a1b2c3d
# good: [c3d4e5f] Add caching layer
git bisect good c3d4e5f
# bad: [d4e5f6g] Update dependencies
git bisect bad d4e5f6g