← Zurück zum Blog

Die Datei-Timeline: Sehen Sie jeder Datei beim Wandel zu, Commit für Commit

feature tutorial

Die Frage, die sich jeder Entwickler irgendwann stellt

Letzten Monat hat es noch funktioniert. Da sind Sie sich sicher. Die Sidebar war ausgerichtet, der Datums-Parser kam mit Zeitzonen zurecht, der Button hatte den richtigen Blauton. Dann landet ein Bug-Report auf dem Tisch, und Sie starren auf eine Datei mit zwei Jahren Historie und versuchen, eine trügerisch einfache Frage zu beantworten: Wann hat sich das geändert, und welcher Commit ist verantwortlich?

Direkt dahinter kommt die zweite Frage: Wer hat das geändert, und warum? Die Commit-Message erklärt es vielleicht. Der Autor erinnert sich vielleicht. Aber zuerst müssen Sie den Commit finden, und genau da beginnt die mentale Turnübung.

Der CLI-Werkzeugkasten -- und wo er an seine Grenzen stößt

Git bringt bereits alles mit, was Sie brauchen, um die Historie einer Datei zu untersuchen. Die Werkzeuge sind mächtig und praxiserprobt -- die Reibung steckt nicht in einem einzelnen Befehl, sondern darin, wie viele davon Sie aneinanderketten müssen.

git log --follow

git log --follow --oneline -- src/styles/sidebar.css

Das listet jeden Commit auf, der die Datei berührt hat, sogar über Umbenennungen hinweg. Es ist der richtige Ausgangspunkt. Aber es liefert Ihnen SHAs und Commit-Messages, keinen Inhalt. Um zu sehen, wie die Datei zu einem bestimmten Zeitpunkt tatsächlich aussah, brauchen Sie den nächsten Befehl.

git show SHA:path

git show a3b4c5d:src/styles/sidebar.css

Das gibt die komplette Datei aus, wie sie bei diesem Commit existierte. Um zwei Versionen zu vergleichen, führen Sie den Befehl zweimal aus und vergleichen die Ausgabe, oder Sie verwenden git diff a3b4c5d 9f2e1d0 -- src/styles/sidebar.css. Und das wiederholen Sie nun für jeden Kandidaten-Commit. Wenn dreißig Commits die Datei berührt haben, werden Sie eine ganze Weile SHAs kopieren -- und die Unterschiede zwischen den Versionen die ganze Zeit im Kopf behalten.

git blame

git blame src/styles/sidebar.css

Blame annotiert jede Zeile mit dem letzten Commit, der sie verändert hat. Das ist hervorragend, wenn die verdächtige Zeile noch in der Datei steht und Sie wissen wollen, wer sie geschrieben hat. Weniger hilfreich ist es, wenn die Regression von einer Zeile stammt, die gelöscht wurde, oder wenn die jüngste Änderung an einer Zeile eine harmlose Neuformatierung ist, die die Änderung verdeckt, die Sie eigentlich interessiert. Dann finden Sie sich dabei wieder, immer wieder git blame SHA^ -- path auszuführen und die Historie Schicht für Schicht abzutragen.

git bisect

Bisect führt eine binäre Suche über Ihre gesamte Historie aus, um den Commit zu finden, der ein testbares Verhalten kaputt gemacht hat. Wenn "kaputt" bedeutet, dass der Build fehlschlägt oder ein Test rot wird, ist bisect genau das richtige Werkzeug, und nichts in einer GUI ersetzt es. Aber es ist schweres Gerät für eine Frage wie "Wann hat sich diese CSS-Regel geändert?". Sie müssen nicht bei jedem Schritt einen Checkout machen und das Projekt neu bauen -- Sie wollen einfach nur eine Datei über die Zeit hinweg betrachten.

Die CLI-Antwort auf "Sieh dieser Datei beim Wandel zu" lautet also: Commits mit log auflisten, jede Version mit show ausgeben, Paare von Hand vergleichen und den gesamten Zustand im Kopf behalten. Jeder Befehl funktioniert. Der Workflow ist das Problem.

Die Datei-Timeline: eine visuelle Antwort

GitSquid hat die Datei-Timeline in v2.6 ausgeliefert, und sie ist in der Free-Version enthalten. Die Idee ist einfach: Statt die Entwicklung einer Datei Commit für Commit im Kopf zu rekonstruieren, sehen Sie ihr auf dem Bildschirm dabei zu.

Öffnen per Rechtsklick

Klicken Sie mit der rechten Maustaste auf eine beliebige Datei und wählen Sie Verlauf anzeigen. Die Historien-Ansicht der Datei öffnet sich, ganz auf diese eine Datei fokussiert.

Eine Markierung pro Commit

Über dem Datei-Viewer sitzt ein Timeline-Streifen: eine Markierung für jeden Commit, der die Datei berührt hat. Das ganze Leben der Datei, horizontal ausgebreitet. Eine Datei mit drei Commits wirkt ruhig; eine Datei mit sechzig Markierungen verrät Ihnen etwas über ihre Unruhe, bevor Sie auch nur eine einzige Zeile gelesen haben.

Durch die Versionen scrubben

Ziehen Sie den Schieberegler, und der Viewer aktualisiert sich, während Sie ziehen. Das ist der Kern des Features: Sie springen nicht zwischen einzelnen Schnappschüssen hin und her, die Sie im Kopf vergleichen müssen -- Sie sehen der Datei beim Verändern zu. Das Hin- und Herfahren fühlt sich nach dem ersten Durchlauf sofort flüssig an; haben Sie die Historie also einmal durchquert, können Sie frei um eine verdächtige Region pendeln und den genauen Commit eingrenzen, an dem sich etwas geändert hat.

Hovern, um zu sehen, wer was geändert hat

Fahren Sie mit der Maus über eine beliebige Markierung, und Sie erhalten den Autor und die Commit-Infos für diesen Punkt in der Historie. Die Frage "Wer hat das geschrieben und wann?" ist beantwortet, ohne die Timeline zu verlassen -- und ganz ohne blame auszuführen.

Auf Play drücken

Klicken Sie auf , und GitSquid spielt die Historie automatisch ab. Für einen ersten Durchgang durch eine unbekannte Datei ist das der schnellste Weg, Intuition aufzubauen: Sie sehen, wie Strukturen entstehen, wachsen, refaktoriert werden. Es ist der Unterschied zwischen dem Lesen von dreißig Diffs und dem Anschauen eines Zeitraffers.

Snapshot oder Diff

Ein Snapshot / Diff-Umschalter im Kopfbereich wechselt zwischen zwei Ansichten: dem vollständigen Dateiinhalt, wie er bei diesem Commit existierte, oder dem klassischen Diff zwischen Datei und Eltern-Commit. Der Snapshot-Modus beantwortet "Wie sah die Datei damals aus?"; der Diff-Modus beantwortet "Was genau hat dieser Commit geändert?". Die Jagd nach einer Regression beginnt meist im Snapshot-Modus und endet im Diff-Modus.

Zu einer Version springen

Haben Sie die Version gefunden, die Sie interessiert, bringen Sie drei Aktionen auf der rechten Seite weiter: SHA kopieren legt den Commit-Hash in Ihre Zwischenablage, um ihn überall zu verwenden, Commit öffnen springt zum vollständigen Commit, damit Sie sehen, was sich neben Ihrer Datei noch geändert hat, und Checkout detached setzt Ihr Arbeitsverzeichnis exakt auf diesen Commit, wenn Sie den alten Code wirklich ausführen müssen.

Schritt für Schritt: eine CSS-Regression finden

Ein konkretes Beispiel. Die Sidebar Ihrer App hat ihr Padding verloren, und niemand weiß, seit wann. So sieht die Jagd mit der Datei-Timeline aus:

  1. Rechtsklick auf sidebar.css → Verlauf anzeigen. Die Timeline zeigt 24 Markierungen über acht Monate.
  2. Vom Neuesten zum Ältesten scrubben und dabei die Padding-Regel beobachten. Etwa bei zwei Dritteln ändert sich die Regel sichtbar. Nach dem ersten Durchlauf ist das Scrubben verzögerungsfrei, also wackeln Sie mit dem Regler um diese Region herum, bis Sie die exakte Markierung isoliert haben, an der der Wert gekippt ist.
  3. Über die Markierung hovern. Es war ein Teamkollege, vor drei Wochen, in einem Commit, der als Layout-Refactoring beschriftet war. Rätsel halb gelöst.
  4. Auf Diff umschalten. Der Umschalter zeigt den Diff zwischen Datei und Eltern-Commit: Das Padding wurde zu einer Kurzschreibweise zusammengefasst, und dabei ist ein Wert verloren gegangen. Da ist die Regression.
  5. Commit öffnen. Der vollständige Commit zeigt, dass er im Rahmen einer Aufräumaktion zwölf Dateien berührt hat -- die Art von Änderung, die man im Review leicht übersieht. Falls Ihr Team überhaupt erst darüber diskutiert, wie solche Änderungen in der Historie landen sollten, lesen Sie rebase vs merge.
  6. SHA kopieren und beheben. Mit dem identifizierten Übeltäter-Commit können Sie ihn reverten, vorwärts korrigieren oder per cherry-pick umgehen -- unser Leitfaden zum Thema wie man einen Git-Commit rückgängig macht erklärt, welche Option zu welcher Situation passt.

Gesamtzeit: ein paar Minuten, keine auswendig gelernten SHAs, keine Archäologie im Terminal-Verlauf.

Wann blame oder bisect immer noch das richtige Werkzeug ist

Die Timeline ersetzt nicht den Rest des Werkzeugkastens, und etwas anderes zu behaupten wäre unehrlich:

  • Verwenden Sie blame, wenn Sie bereits auf eine bestimmte Zeile schauen und direkt an Ort und Stelle ihren letzten Autor wissen wollen. Für eine einzelne Zeile, die nicht kürzlich neu formatiert wurde, bleibt blame der kürzeste Weg.
  • Verwenden Sie bisect, wenn das Symptom "der Build ist kaputt" oder "ein Test schlägt fehl" lautet und Sie nicht wissen, welche Datei verantwortlich ist. Bisect durchsucht die Historie des gesamten Repositories; die Timeline untersucht eine einzelne Datei. Sie beantworten unterschiedliche Fragen.
  • Verwenden Sie die Timeline, wenn es um die Entwicklung einer einzelnen Datei geht: Wann hat sich das geändert, wer hat es geändert, und wie sah es vorher aus.

Sehen Sie Ihrem eigenen Code beim Wachsen zu

Die Datei-Timeline ist in der Free-Version von GitSquid enthalten -- kein Konto, keine Telemetrie, nativ auf macOS, Windows und Linux. Öffnen Sie ein Repository, klicken Sie mit rechts auf eine Datei, über die Sie sich schon immer gewundert haben, und drücken Sie auf Play.

Laden Sie GitSquid Free herunter und geben Sie Ihrer nächsten Regressionsjagd eine Timeline statt einer SHA-Liste.