Rückblick

log

Filtern und sortieren

$ git log [-n COUNT]

listet die Commit-Historie des aktuellen Zweiges auf.

-n

beschränkt die Anzahl der Commits auf die angegebene Zahl.

$ git log [--after="YYYY-MM-DD"] [--before="YYYY-MM-DD"]

Commit-Historie gefiltert nach Datum.

Auch relative Angaben wie 1 week ago oder yesterday sind zulässig.

$ git log --author="VEIT"

filtert die Commit-Historie nach Autor*innen.

Es kann auch nach mehreren Autor*innen gleichzeitig gesucht werden, z.B.:

$ git log --author="VEIT|VSC"

$ git log --grep="TERM" [-i]

filtert die Commit-Historie nach regulären Ausdrücken in der Commit-Nachricht.

-i

ignoriert Groß- und Kleinschreibung.

$ git log -S"FOO" [-i]

filtert Commits nach bestimmten Zeilen im Quellcode.

-i

ignoriert Groß- und Kleinschreibung.

$ git log -G"BA*"

filtert Commits nach regulären Ausdrücken im Quellcode.

$ git log -- PATH/TO/FILE

filtert die Commit-Historie nach bestimmten Dateien.

$ git log MAIN..FEATURE

filtert nach unterschiedlichen Commits in verschiedenen Zweigen (Branches), in unserem Fall zwischen den Branches MAIN und FEATURE.

Dies ist jedoch nicht dasselbe wie git log FEATURE..MAIN. Nehmen wir folgendes Beispiel.

A - B main
 \
  C - D feature
$ git log MAIN..FEATURE

zeigt Änderungen in FEATURE an, die nicht in MAIN enthalten sind, also die Commits C und D.

$ git log FEATURE..MAIN

zeigt Änderungen in MAIN an, die nicht in FEATURE enthalten sind, also den Commit B.

$ git log MAIN...FEATURE

zeigt die Änderungen auf beiden Seiten an, also die Commits B, C und D.

$ git log --follow PATH/TO/FILE

Dies sorgt dafür, dass das Log Änderungen an einer einzelnen Datei anzeigt, auch wenn diese umbenannt oder verschoben wurde.

Ihr könnt --follow für einzelne Dateiaufrufe standardmäßig aktivieren, indem ihr die Option log.follow in eurer globalen Konfiguration aktiviert:

$ git config --global log.follow true

Dann müsst ihr nicht mehr --follow angeben, sondern nur noch den Dateinamen.

$ git log -L LINE_START_INT|LINE_START_REGEX,LINE_END_INT|LINE_END_REGEX:PATH/TO/FILE
$ git log -L :FUNCNAME_REGEX:PATH/TO/FILE

Mit der Option -L könnt ihr eine verfeinerte Suche durchführen, indem ihr das Log nur eines Teils einer Datei überprüft. Mit dieser Funktion könnt ihr die Historie einer einzelnen Funktion, einer Klasse oder eines anderen Code-Blocks gründlich durchforsten. Sie ist ideal, um herauszufinden, wann etwas erstellt und wie es geändert wurde, so dass ihr es getrost korrigieren, refaktorisieren oder löschen könnt.

Für umfassendere Untersuchungen könnt ihr auch mehrere Blöcke verfolgen. Hierfür könnt ihr mehrere -L-Optionen auf einmal verwenden.

$ git log --reverse

Üblicherweise zeigt das Protokoll den neuesten Commit zuerst an. Ihr könnt dies mit --reverse umkehren. Dies ist besonders nützlich, wenn ihr mit den bereits erwähnten Optionen -S und -G untersucht. Indem ihr die Reihenfolge der Commits umkehrt, könnt ihr schnell den ersten Commit finden, der eine bestimmte Zeichenfolge zur Codebasis hinzugefügt hat.

Ansicht

$ git log --stat --patch|-p
--stat

Den üblichen Metadaten wird noch eine eine Zusammenfassung der Anzahl der geänderten Zeilen pro Datei hinzugefügt.

--patch|-p

ergänzt die Ausgabe um den vollständigen Commit-Diff.

$ git log --oneline --decorate --graph --all|FEATURE

anzeigen des Verlaufsdiagramms mit Referenzen, ein Commit pro Zeile.

--oneline

Ein Commit pro Zeile.

--decorate

Die Präfixe refs/heads/, refs/tags/ und refs/remotes/ werden nicht ausgegeben.

--graph

Üblicherweise glättet das Log historische Zweige und zeigt Commits nacheinander an. Damit wird die parallele Struktur der Historie beim Zusammenführen von Zweigen verborgen. --graph stellt den Verlauf der Zweige in ASCII-Art dar.

--all|FEATURE

--all zeigt das Log für alle Zweige; FEATURE zeigt nur die Commits dieses Zweiges an.

reflog

Mit git reflog wird euer Git-Repository nicht ein zweites Mal überprüft. Stattdessen zeigt es das Reference-Log an, eine Aufzeichnung aller vorgenommenen Commits. Das Reflog verfolgt nicht nur Änderungen an einem Zweig, es zeichnet auch Änderungen am aktuellen Commit, den Wechsel des Zweiges, Rebasing, etc. auf. Ihr könnt es benutzen, um alle unerreichbaren Commits zu finden, sogar solche auf gelöschten Zweigen. Damit könnt ihr viele, ansonsten destruktive Aktionen wieder rückgängig machen.

Schauen wir uns die Grundlagen der Verwendung von Reflog und einige typische Anwendungsfälle an.

Warnung

Das Reflog ist nur Teil eures lokalen Repository. Wenn ihr ein Projektarchiv löscht und neu klont, wird der neue Klon ein frisches, leeres Reflog haben.

Das Reflog für HEAD anzeigen

$ git reflog

Wenn keine Optionen angegeben sind, zeigt der Befehl standardmäßig das Reflog für HEAD an. Es ist die Abkürzung für git reflog show HEAD. git reflog hat weitere Unterbefehle zur Verwaltung des Logs, aber show ist der Standardbefehl, wenn kein Unterbefehl übergeben wird.

1$ git reflog
212bc4d4 (HEAD -> main, my-feature-branch) HEAD@{0}: merge my-feature-branch: Fast-forward
3900844a HEAD@{1}: checkout: moving from my-feature-branch to main
412bc4d4 (HEAD -> main, my-feature-branch) HEAD@{2}: commit (amend): Add my feature and more
5982d93a HEAD@{3}: commit: Add my feature
6900844a HEAD@{4}: checkout: moving from main to my-feature-branch
7900844a HEAD@{5}: commit (initial): Initial commit
  • Die Ausgabe ist ziemlich dicht.

  • Jede Zeile ist ein Reflog-Eintrag, der neueste zuerst.

  • Die Zeilen beginnen mit dem abgekürzten SHA des entsprechenden Commits, z.B. 12bc4d4.

  • Der erste Eintrag ist das, worauf HEAD derzeit verweist: (HEAD -> main, my-feature).

  • Die Namen HEAD@\{N} sind alternative Referenzen für die angegebenen Commits. N ist die Anzahl der zurückgehenden reflog-Einträge.

  • Der restliche Text beschreibt die Änderung. Oben könnt ihr mehrere Arten von Einträgen sehen:

    • commit: MESSAGE für Commits

    • commit (amend): MESSAGE für eine Commit-Änderung

    • checkout: moving from SRC TO DST für einen Zweigwechsel

Es gibt viele weitere mögliche Arten von Einträgen. Der Text sollte so beschreibend sein, dass ihr den Vorgang auch ohne Nachschlagen in der Dokumentation nachvollziehen könnt. In den meisten Fällen werdet ihr solche Reflog-Einträge durchsehen wollen, um den entsprechenden Commit SHA zu finden.

Das Reflog für einen Zweig anzeigen

Ihr könnt euch auf Einträge für einen einzelnen Zweig fokussieren, indem ihr den expliziten Unterbefehl show und dem Zweignamen verwendet:

$ git reflog show my-feature-branch
12bc4d4 (HEAD -> main, my-feature-branch) my-feature-branch@{0}: commit (amend): Add my feature and more
982d93a my-feature-branch@{1}: commit: Add my feature
900844a my-feature-branch@{2}: branch: Created from HEAD

Zeitstempel der Einträge anzeigen

Wenn ihr zwischen ähnlich betitelten Änderungen unterscheiden müsst, können die Zeitstempel helfen. Für relative Zeitstempel könnt ihr --date=relative verwenden:

$ git reflog --date=relative
12bc4d4 (HEAD -> main, my-feature) HEAD@{vor 37 Minuten}: merge my-feature-branch: Fast-forward
900844a HEAD@{vor 37 Minuten}: checkout: moving from my-feature-branch to main
12bc4d4 (HEAD -> main, my-feature-branch) HEAD@{vor 37 Minuten}: commit (amend): Add my feature and more
982d93a HEAD@{vor 38 Minuten}: commit: Add my feature
900844a HEAD@{vor 39 Minuten}: checkout: moving from main to my-feature-branch
900844a HEAD@{vor 40 Minuten}: commit (initial): Initial commit

Und für absolute Zeitstempel könnt ihr auch --date=iso verwenden:

$ git reflog --date=iso
12bc4d4 (HEAD -> main, my-feature) HEAD@{2024-01-11 15:26:53 +0100}: merge my-feature-branch: Fast-forward
900844a HEAD@{2024-01-11 15:26:47 +0100}: checkout: moving from my-feature-branch to main
12bc4d4 (HEAD -> main, my-feature-branch) HEAD@{2024-01-11 15:26:11 +0100}: commit (amend): Add my feature and more
982d93a HEAD@{2024-01-11 15:25:38 +0100}: commit: Add my feature
900844a HEAD@{2024-01-11 15:24:37 +0100}: checkout: moving from main to my-feature-branch
900844a HEAD@{2024-01-11 15:23:56 +0100}: commit (initial): Initial commit

Übergebt alle Optionen, die git log unterstützt

git reflog show hat die gleichen Optionen wie git log. So könnt ihr beispielsweise mit --grep nach Commit-Meldungen suchen, in denen my feature erwähnt wird, ohne die Groß- und Kleinschreibung zu berücksichtigen:

$ git reflog -i --grep 'my feature'
12bc4d4 (HEAD -> main, my-feature-branch) HEAD@{0}: merge my-feature: Fast-forward
12bc4d4 (HEAD -> main, my-feature-branch) HEAD@{2}: commit (amend): Add my feature and more
982d93a HEAD@{3}: commit: Add my feature

Beachtet den Verfall von Einträgen

Reflog-Einträge verfallen nach einer gewissen Zeit, wenn Git den automatischen gc-Prozess für euer Repository ausführt. Diese Verfallszeit wird durch zwei gc.*-Optionen gesteuert:

gc.reflogExpire

Die allgemeine Verfallszeit, die standardmäßig auf 90 Tage eingestellt ist.

gc.reflogExpireUnreachable

Die Verfallszeit für Einträge, die sich auf nicht mehr erreichbare Commits beziehen, ist standardmäßig auf 30 Tage eingestellt.

Ihr könnt diese Optionen auf einen längeren Zeitrahmen erhöhen, was allerdings nur selten sinnvoll sein dürfte.