Typing good and bad is error-prone, and one wrong answer sends the search down the wrong half. git bisect run <command> runs the command at every step and reads its exit status: 0 means good; 1 to 127 means bad, except 125, which means "cannot test, skip this commit"; anything else, such as a crash with 128 or more, aborts the bisect. check-price.js was written to that contract, and its catch returns 125 when a commit cannot even build the database:
git bisect start main v1.1.0
git bisect run node ../check-price.js
git bisect resetBisecting: 3 revisions left to test after this (roughly 2 steps) [a5f5aa26a2a50f0e947b2b01d419fa4753dae30f] Add an isbn column to books running 'node' '../check-price.js' book 1 costs 14.99 ... f2b410653316fff815ca6c89aa129ad9174d0a42 is the first 'bad' commit ... db/migrations/004-widen-price.sql | 2 ++ ... bisect found first 'bad' commit ...
The same three steps now run unattended, and across a thousand commits with a slow test, that saves an afternoon. Keep the script outside the working tree, because bisect checks out commits that lack it. Any command works: npm 2,036 test for an existing failing test, curl 3,008 against a started server, grep in a build. Keep the check narrow: an unrelated failure, a flaky test for example, marks a commit bad and misleads the search. git bisect start --first-parent (Git 2.29 1,932 ) follows only the merges into main.