git bisect: Wer hat wann was kaputt gespielt?

Gestern bin ich wohl dem Alptraum eines Programmierers: begegnet Das Programm macht unvorhersehbare Sachen. Aufgefallen war es mir als eine globale Variable in dem Programm (iOS-App) auf einmal 0 wurde. An sich nicht weiter verwunderlich, aber wenn es genau 5 Zeilen im ganzen Programm gibt, die darauf zugreifen können, ist das schon etwas seltsam. An meinem Mac wurde es dann noch lustiger… ein harmloser Methoden Aufruf endete tief im PrinterKit.

Nach dem ich gemerkt habe, das ich keinen Schimmer habe wo dieses komische Problem herkommt habe ich mich an einen guten Freund gewendet: git.

Ich wusste, dass der Fehler irgendwann noch nicht existiert hat und hier konnte ich mit git bisect ansetzen.

Mit git bisect sagt man git welche Version garantiert funktioniert und welche ebend nicht. Git hilft dir nun herauszufinden mit welchem Commit der Fehler eingeschleppt wurde.

Das ganze geht auch ziemlich flott. Ca. 5 Schritte waren für die 33 Commits zwischen meinem Bad-Commit und Good-Commit nötig, in der Schule haben wir das liebevoll Intervall-Halbierungs-Verfahren genannt. Aber genug vom vorgeblabber, so geht’s:

Als erstes initialisieren wir das git bisect system.

1
2
$ git bisect start
$ git bisect good <commit>

Bei dem zweiten Befehl geben wir einen Commit an, von dem wir wissen das er den Fehler nicht enthält. Nun sagen wir git noch, in welchem Commit auf jeden Fall der Fehler existiert:

1
$ git bisect bad <commit>

Der aufmerksame Beobachter wird festgestellt haben, dass git bisect nun einen anderen Commit ausgecheckt hat. Nun sind wir an der Reihe. Wir müssen nun testen, ob der Commit auch den Fehler enthält oder nicht. Sollte der Fehler auch hier bestehen teilen wir das git mit:

1
$ git bisect bad

ansonsten, wenn alles funktioniert:

1
$ git bisect good

Dies wiederholt man nun solange bis git bisect irgendwann stolz verkündet, welcher Commit den Fehler erschaffen hat. Dann bleibt nur den Commit zu merken, anzuschauen was dort verändert wurde und den Fehler in den (hoffentlich wenigen) Zeilen zu finden.

Zum Schluss müssen wir noch git bisect beenden:

1
$ git bisect reset

(Nachzulesen auch im Git Book)