Binary-search the history between a known good commit and a known bad one until git names the commit that introduced the problem.
git bisect start
git bisect bad # the commit you're on is broken
git bisect good v1.4 # a tag, branch or sha that worked
Git checks out the commit halfway between them. Build, run the failing thing, then tell git what you saw:
git bisect good # or: git bisect bad
Repeat until it prints <sha> is the first bad commit. Then put your branch back:
git bisect reset
Let a script do the marking
If the failure is a command that exits non-zero, hand it to bisect and walk away:
git bisect start HEAD v1.4
git bisect run npm test -- --run src/auth.test.ts
run marks each step from the exit code: 0 is good, 1 to 127 is bad, and 125 tells bisect to skip that commit, which is what to return when the build itself fails there.
Gotchas
- A commit that won’t build is neither good nor bad. Mark it
git bisect skipand git picks a neighbour. - Bisect moves
HEADaround under you. Commit or stash before you start, or the checkout is refused halfway through. - Ten steps cover about a thousand commits, so a wide range is fine. What costs time is a slow reproduction, which is why
runis worth setting up. git bisect logprints what you’ve marked so far. If you mark one wrong,git bisect reset, edit that log, and replay it withgit bisect replay.