git bisect
Lerne den git bisect-Befehl kennen, um per Binärsuche den Commit zu finden, der einen Fehler eingeführt hat. Mit Automatisierung per run.
Der Befehl git bisect hilft dir dabei, den genauen Commit zu finden, der einen Fehler eingeführt hat, indem er eine Binärsuche durch deine Commit-Historie durchführt. Du teilst Git einen Commit mit, bei dem der Code funktionierte ("good"), und einen, bei dem er fehlerhaft ist ("bad"). Git checkt dann wiederholt den Mittelpunkt für dich zum Testen aus und halbiert dabei jedes Mal den Verdachtsbereich, bis ein einzelner Verursacher übrig bleibt.
Dieses Kapitel erklärt, wie du eine Bisect-Sitzung manuell durchführst, wie du die Fortschrittsausgabe von Git nach jeder Antwort liest, wie du die gesamte Suche mit einem Testbefehl automatisierst, wie du nicht testbare Commits überspringst und wie du vorgehst, wenn du einen Fehler machst.
Definition
Warum Binärsuche
Wenn ein Fehler irgendwo in den letzten 1.000 Commits aufgetaucht ist, wäre es sehr mühsam, sie einzeln zu überprüfen. Die Binärsuche benötigt nur etwa zehn Tests, um den Verursacher zu finden, weil jede Antwort die verbleibenden Kandidaten halbiert — ungefähr log2(N) Schritte für N Commits. git bisect übernimmt die gesamte Buchführung, sodass du nur noch beantworten musst: "Funktioniert es hier?"
Eine Bisect-Sitzung starten
Beginne die Sitzung, markiere dann den aktuell fehlerhaften Zustand und einen bekannt funktionierenden früheren Commit:
git bisect start
git bisect bad # the current commit is broken
git bisect good v1.4.0 # this tag was known to workGit checkt einen Commit auf halbem Weg zwischen diesen beiden aus. Du baust und testest diese Version, dann meldest du das Ergebnis:
git bisect good # this commit works — bug is newer
# or
git bisect bad # this commit is broken — bug is here or olderNach jeder Antwort gibt Git aus, wie viel vom Bereich noch übrig ist, und checkt den nächsten Mittelpunkt für dich aus:
Bisecting: 7 revisions left to test after this (roughly 3 steps)
[a1b2c3d4...] Refactor the parserWiederhole die Test-und-Markierungs-Schleife, bis Git den ersten schlechten Commit ankündigt:
a1b2c3d4 is the first bad commit
commit a1b2c3d4...
Refactor the parserDas Ergebnis mit git bisect log lesen
Du kannst jederzeit die bisher gegebenen Antworten einsehen. Das ist auch praktisch, um eine Aufzeichnung der Sitzung zu behalten:
git bisect logWenn du vermutest, einen Commit falsch markiert zu haben, setze zurück und wiederhole mit einem korrigierten Log, anstatt von vorne anzufangen:
git bisect log > bisect-run.txt # edit out the mistaken line
git bisect reset
git bisect replay bisect-run.txtDie Sitzung beenden
Wenn Git den Verursacher meldet, kehre dorthin zurück, wo du begonnen hast:
git bisect resetDamit wird HEAD auf den Branch zurückgesetzt, auf dem du vor dem Bisect warst.
Mit git bisect run automatisieren
Wenn du den Test als Skript oder Befehl ausdrücken kannst, der bei Erfolg 0 und bei Fehler einen Nicht-Null-Wert zurückgibt, führt Git die gesamte Suche unbeaufsichtigt durch:
git bisect start HEAD v1.4.0
git bisect run npm testGit checkt jeden Mittelpunkt aus, führt den Befehl aus, wertet den Exit-Code aus und stoppt beim ersten fehlerhaften Commit — ohne manuelle Markierungen.
Der Befehl kann jede ausführbare Datei sein: ein Einzeiler, ein Shell-Skript oder eine Binärdatei. Exit-Code 0 bedeutet gut, jeder Code zwischen 1 und 127 (außer 125) bedeutet schlecht. Der spezielle Exit-Code 125 teilt Git mit, dass der Commit nicht getestet werden kann, und entspricht dem Ausführen von git bisect skip — verwende ihn, wenn der Build selbst bei dieser Version kaputt ist:
#!/bin/sh
# test.sh — skip commits that don't even compile
make || exit 125
./run-the-failing-case # exits non-zero when the bug is presentgit bisect start HEAD v1.4.0
git bisect run ./test.shgit bisect run-Befehl sollte idempotent und in sich geschlossen sein. Wenn dein Test Build-Artefakte oder geänderte Dateien hinterlässt, füge einen Bereinigungsschritt hinzu, damit der nächste Checkout sauber startet — sonst kann eine veraltete Binärdatei dazu führen, dass ein guter Commit als schlecht erscheint.Commits überspringen, die du nicht testen kannst
Manchmal ist der ausgecheckte Commit aus einem unrelated Grund kaputt — er lässt sich nicht kompilieren, oder eine Abhängigkeit fehlt — sodass du wirklich nicht "gut" oder "schlecht" sagen kannst. Sage Git, ihn beiseite zu legen:
git bisect skipGit wählt stattdessen einen nahegelegenen Commit und setzt die Eingrenzung fort. Wenn zu viele Commits in einem Bereich übersprungen werden, kann Git einen Bereich von Kandidaten anstelle eines einzelnen Commits melden.
Häufige Optionen
| Befehl | Beschreibung |
|---|---|
git bisect start | Startet eine Bisect-Sitzung. |
git bisect bad [<commit>] | Markiert einen Commit als fehlerhaft (Standard: aktueller). |
git bisect good [<commit>] | Markiert einen Commit als funktionierend. |
git bisect skip | Überspringt einen Commit, der nicht getestet werden kann (z. B. weil er nicht baut). |
git bisect run <cmd> | Automatisiert die Suche anhand des Exit-Codes eines Testbefehls. |
git bisect log | Gibt die bisher gegebenen gut/schlecht-Antworten aus. |
git bisect replay <file> | Wiederholt ein gespeichertes Bisect-Log. |
git bisect reset | Beendet die Sitzung und stellt den ursprünglichen HEAD wieder her. |
Verwandte Befehle
Sobald Bisect auf den Verursacher zeigt, helfen dir diese Befehle, ihn zu untersuchen und darauf zu reagieren:
- git show — zeigt die genauen Änderungen, die der schlechte Commit eingeführt hat.
- git blame — zeigt, welcher Commit eine bestimmte Zeile zuletzt geändert hat.
- git log — durchsucht die Historie, die Bisect durchsucht hat.
- git revert — macht den schlechten Commit rückgängig, ohne die Historie neu zu schreiben.
- git checkout — erklärt, wie Git
HEADbewegt, was Bisect intern verwendet.