Bisektionale Bugsuche mit Git

Manches Verhalten läßt sich nur schwer maschinell testen, manches gar nicht. GUI-Tests können keinen Menschen ersetzen und man kann nicht jeden Logik-Fall mit Unit-Tests abdecken. Und bei Fehlern in 3rd-Party-Frameworks schaut man eh in die Röhre.

Machmal kommt es in Apps vor, daß man komplexes Verhalten hat, das im Laufe der letzten Commits anscheinend kaputtgegangen ist. Und Fehlersuche in eigenem Code ist schwierig, weil man ihn selbst geschrieben hat. Man neigt nämlich dazu, denselben Denk-Fehler wieder zu machen, wenn man den Code durchgeht. Was tun?

Kleine Commits

Ich mache immer viele kleine Commits in Git per Xcode. Typischerweise mehrmals am Tag. Die aktuellen Änderungen sehe ich mir im Commit-Fenster von Xcode nochmal an und deaktiviere die Stellen oder ganze Dateien, die thematisch nicht zu der Verbesserung gehören, die ich in dem nächsten Commit haben möchte. Der Rest kommt schrittweise in nachfolgende Commits. Ich gebe dem Commit jeweils eine zugehörige Bezeichnung aus einem Bugtracker wie YouTrack oder dergleichen, um später den geschäftlichen Hintergrund der Änderung rekonstruieren und verwandte Commits finden zu können. Die Commit-Message ist eine imperative Handlungsanweisung, die den Inhalt beschreibt, in Anlehnung an How to Write a Git Commit Message.

Selbst für diese Website benutze ich übrigens Git. Allerdings im Terminal.

Bug-Suche

Mit Git kann man schnell einen alten Stand reaktivieren, indem man einen alten Commit auscheckt. Den aktuellen Stand bekommt man zurück mit einem stumpfen Checkout auf den Branchnamen. Ich schaue mir die Commit-Historie in Xcode an und suche mir einen Commit raus, bei dem definitiv noch alles ok war. Checke diesen aus. Probiere den Stand aus. Danach nehme ich einen Commit der zeitlich in der Mitte zwischen dem aktuellen Stand und dem alten funktionierendem Commit liegt. Verhält sich der Code aus diesem Commit wie gewünscht, dann probiere ich als nächstes einen Commit in der Mitte zwischen diesem grad und dem aktuellen Stand. Ansonsten probiere ich einen zwischen diesem grad und dem ganz alten Stand. Entweder liegt der Fehler vor oder nach dem grad ausprobiertem Commit. Liegt er vorher, halbiere ich den Teil vorher. Ansonsten dahinter. Das Suchfenster halbiert sich mit jedem Schritt. Es ist dasselbe Vorgehen wie beim Raten einer Zahl zwischen 1 und 100.

Genauer gesagt ist es eine bisektionale Suche, eine binäre Suche, eine Interval-Halbierungs-Suche, eine logarithmische Suche. Sie ist extrem schnell. Selbst bei 1000 Commits ist man nach 10 Schritten bei dem Commit, der den Fehler verursacht hat. Und dieser Commit ist meistens eine Überraschung, denn dort hätte ich den Fehler durch Nachdenken in der Regel nie vermutet. Und da es kleine Commits sind, ist die Fehlersuche auf recht wenige verbleibende Zeilen begrenzt, die ich zur Not auch noch einzeln rückgängig machen kann bequem in Xcode mit der Compare-Ansicht.

Ich kann dieses Vorgehen nur empfehlen. Wie oft habe ich schon mit fruchtlosem Nachdenken und Nachschauen an völlig falschen Stellen Zeit verloren und anschließend mit dieser Methode den Fehler schnell gefunden, bei der man nicht mal viel überlegen muß.

Git Kommandos

Diese Git-Befehle verwende ich im Terminal bei diesem Thema:

Valid XHTML 1.0!

Besucherzähler


Latest Update: 26. December 2016 at 13:45h (german time)
Link: macmark.de/dev/osx_dev_bug_bisect.php