git log

Git-Protokoll für Fortgeschrittene

Der Zweck eines jeden Versionskontrollsystems ist die Dokumentierung von Änderungen an deinem Code. Dies ermöglicht dir, in deinem Projektverlauf zurückzublicken und herauszufinden, wer was beigetragen hat und wo Fehler eingeführt wurden, damit du problematische Änderungen rückgängig machen kannst. Die Verfügbarkeit dieses ganzen Verlaufs ist jedoch nutzlos, wenn du nicht weißt, wie du dich darin zurechtfindest. Hierfür gibt es den Befehl "git log".

Inzwischen solltest du bereits den grundlegenden Befehl zum Anzeigen von Commits "git log"kennen. Du kannst diese Anzeige jedoch ändern, indem du git log mit verschiedenen Parametern kombinierst.

Die erweiterten Features des Git-Protokolls können in zwei Kategorien unterteilt werden: Formatierung der Anzeige der einzelnen Commits und Filtern der anzuzeigenden Commits. Mithilfe dieser beiden Möglichkeiten bist du in der Lage, jegliche benötigten Informationen in deinem Projekt zu finden.

Protokollausgabe formatieren

In diesem Artikel behandeln wir zunächst die zahlreichen Möglichkeiten zur Formatierung des git log-Outputs. Das geschieht hauptsächlich mithilfe von Flags. Durch Flags kannst du die mit git log angefragten Informationen einschränken oder erweitern.

Wenn dir das Standardformat von git log nicht gefällt, kannst du die Alias-Funktion von git config nutzen, um eine Kurzform für eine der unten beschriebene Formatierungsoptionen festzulegen. Unter Der Befehl "git config" erfährst du, wie du einen Alias einrichtest.

Oneline

Der Zusatz --oneline fasst einen Commit in einer einzigen Zeile zusammen. In der Standardeinstellung wird nur die Commit-ID und die erste Zeile der Commit-Nachricht angezeigt. Normalerweise sieht eine git log --oneline-Ausgabe in etwa folgendermaßen aus:

0e25143 Merge branch 'feature'
ad8621a Fix a bug in the feature
16b36c6 Add a new feature
23ad9ad Add the initial code base

Dies ist äußerst hilfreich, um einen groben Überblick über das Projekt zu erhalten.

Decorate

Oft ist es sinnvoll zu wissen, welche Branches oder Tags mit Commits assoziiert sind. --decorate weist git log an, alle Referenzen (also Branches, Tags usw.) anzuzeigen, die auf den jeweiligen Commit verweisen.

Dies kann mit anderen Konfigurationsoptionen kombiniert werden. Der Befehl git log --oneline --decorate formatiert den Commit-Verlauf z. B. folgendermaßen:

0e25143 (HEAD, master) Merge branch 'feature'
ad8621a (feature) Fix a bug in the feature
16b36c6 Add a new feature
23ad9ad (tag: v0.9) Add the initial code base

Hierdurch erfährst du, dass der oberste Commit ausgecheckt ist (indiziert durch HEAD) und dass er sich an der Spitze des master Branch befindet. Der zweite Commit hat einen anderen Branch namens feature, der auf ihn verweist, und der vierte Commit ist mit v0.9 getaggt.

Branches, Tags, HEAD und der Commit-Verlauf machen nahezu alle Informationen in deinem Git-Repository aus. Darüber kannst du einen umfassenderen Einblick in den logischen Aufbau deines Repositorys erhalten.

Diffs

Der Befehl git log umfasst viele Optionen für die Anzeige von Diffs für jeden Commit. Zwei der gebräuchlichsten Optionen sind --stat und -p.

Mit der Option --stat werden die Anzahl von Einfügungen und Löschungen für jede einzelne Datei, die bei dem jeweiligen Commit geändert werden, angezeigt. (Beachte, dass die Bearbeitung einer Zeile als eine Einfügung und eine Löschung gezählt wird.) Dies ist hilfreich, wenn du eine kurze Zusammenfassung der Änderungen benötigst, die mit jedem Commit hinzukamen. Im folgenden Commit wurden z. B. 67 Zeilen zur Datei hello.py hinzugefügt und 38 Zeilen entfernt.

commit f2a238924e89ca1d4947662928218a06d39068c3
Author: John <john@example.com>
Date: Fri Jun 25 17:30:28 2014 -0500
Add a new feature
hello.py | 105 ++++++++++++++++++++++++-----------------
1 file changed, 67 insertion(+), 38 deletions(-)

Die Anzahl an Zeichen (+ und -) neben dem Dateinamen zeigt dir die relative Anzahl der Änderungen an, die mit einem Commit an einer Datei vorgenommen wurden. Das kann ein Hinweis darauf sein, wo die Änderungen eines Commits zu finden sind.

Wenn du die tatsächlichen Änderungen sehen möchtest, die mit jedem einzelnen Commit hinzukamen, kannst du die Option -p an git log anfügen. Dies gibt den gesamten Patch, der diesen Commit repräsentiert, zurück:

commit 16b36c697eb2d24302f89aa22d9170dfe609855b
Author: Mary <mary@example.com>
Date: Fri Jun 25 17:31:57 2014 -0500
Fix a bug in the feature
diff --git a/hello.py b/hello.py
index 18ca709..c673b40 100644
--- a/hello.py
+++ b/hello.py
@@ -13,14 +13,14 @@ B
-print("Hello, World!")
+print("Hello, Git!")

Bei Commits mit vielen Änderungen kann die Ausgabe recht lang und unübersichtlich sein. Meistens wirst du nach einer bestimmten Änderung suchen, wenn du dir einen vollständigen Patch anzeigen lässt. Hierfür solltest du die Option "Pickaxe" verwenden.

Shortlog

Der Befehl git shortlog ist eine Spezialversion von git log zum Erstellen von Release-Ankündigungen. Es gruppiert alle Commits nach Autoren und zeigt die erste Zeile einer jeden Commit-Nachricht an. So kannst du bequem sehen, wer woran gearbeitet hat.

Wenn z. B. zwei Entwickler fünf Commits zu einem Projekt beigesteuert haben, könnte die Ausgabe vn git shortlog in etwa so aussehen:

Mary (2):
Fix a bug in the feature
Fix a serious security hole in our framework
John (3):
Add the initial code base
Add a new feature
Merge branch 'feature'

Standardmäßig sortiert git shortlog den Output nach Name des Autors. Mit der Option -n kannst du aber auch nach Anzahl der Commits pro Autor sortieren.

Diagramme

Mit der Option --graph wird eine ASCII-Grafik zur Branch-Struktur des Commit-Verlaufs erstellt. Das wird oft zusammen mit den Befehlen --oneline und --decorate genutzt, um besser zu erkennen, welcher Commit zu welchem Branch gehört:

git log --graph --oneline --decorate

Bei einem einfachen Repository mit nur zwei Branches ergibt sich hierdurch Folgendes:

* 0e25143 (HEAD, master) Merge branch 'feature'
|\
| * 16b36c6 Fix a bug in the new feature
| * 23ad9ad Start a new feature
* | ad8621a Fix a critical security issue
|/
* 400e4b7 Fix typos in the documentation
* 160e224 Add the initial code base

Das Sternsymbol zeigt, in welchem Branch sich der Commit befand. Dem obigen Graphen entnehmen wir also, dass die Commits 23ad9ad und 16b36c6 sich auf einem Themen-Branch und die übrigen Commits sich auf dem master Branch befinden.

Für einfache Repositorys ist das zwar eine nette Option, doch bei Projekten mit sehr vielen Branches ist ein Virtualisierungstool mit großem Funktionsumfang wie gitk oder SourceTree vermutlich die bessere Wahl.

Benutzerdefinierte Formatierung

Für alle anderen git log-Formatierungen gibt es die Option --pretty=format:"<String>". Damit kannst du die Anzeige einzelner Commits individuell definieren. Wir empfehlen jedoch Platzhalter im printf-Stil.

Die Zeichen %cn, %h und %cd werden im folgenden Befehl z. B. jeweils mit dem Committer-Namen, dem abgekürzten Commit-Hash und dem Commit-Durchführungsdatum ersetzt.

git log --pretty=format:"%cn hat %h am %cd committet."

Hieraus ergibt sich das folgende Format für die einzelnen Commits:

John committed 400e4b7 on Fri Jun 24 12:30:04 2014 -0500
John committed 89ab2cf on Thu Jun 23 17:09:42 2014 -0500
Mary committed 180e223 on Wed Jun 22 17:21:19 2014 -0500
John committed f12ca28 on Wed Jun 22 13:50:31 2014 -0500

Eine vollständige Liste der Platzhalter findest du auf der git log-Anleitungsseite im Abschnitt zu schönen Formaten.

Abgesehen davon, dass dir nur die Informationen angezeigt werden, die dich interessieren, ist die Option --pretty=format:"<string>" besonders hilfreich, wenn du die Ausgabe von git log mit einem anderen Befehl kombinierst.

Commit-Verläufe filtern

Wenn du weißt, wie du die Commit-Anzeige formatieren kannst, hast du schon die Hälfte aller Vorteile von git log kennengelernt. Wenn du auch weißt, wie du durch den Commit-Verlauf navigieren kannst, hast du aus dem Befehl alles herausgekitzelt. Im Folgenden zeigen wir einige erweiterte Methoden, um mit git log bestimmte Commits in deinem Projektverlauf zu finden. Diese Möglichkeiten kannst du mit allen bereits vorgestellten Formatierungsoptionen kombinieren.

Nach Anzahl

Die grundlegendste Filteroption für git log ist das Einschränken der Anzahl angezeigter Commits. Wenn du nur die letzten Commits sehen möchtest, musst du dich nicht damit abmühen, alle Commits auf einer Seite zu lesen.

Du kannst die Ausgabe von git log beschränken, indem du die Option -<n> hinzufügst. Mit dem folgenden Befehl werden beispielsweise nur die drei neuesten Commits angezeigt.

git log -3

Nach Datum

Wenn du nach einem Commit von einem bestimmten Zeitrahmen suchst, kannst du die Zusätze --after oder --before verwenden, um die Commits nach Datum zu filtern. Beide akzeptieren verschiedene Datumsformate als Parameter. Mit dem folgenden Befehl werden beispielsweise nur Commits angezeigt, die nach (inklusive) dem 1. Juli 2014 erstellt wurden.

git log --after="2014-7-1"

Du kannst auch relative Referenzen wie "1 week ago" und "yesterday" anfügen:

git log --after="yesterday"

Um nach Commits zu suchen, die in einem bestimmten Zeitraum erstellt wurden, kannst du jeweils ein Datum --before (vor) und --after (nach) dem Zeitraum angeben. Wenn du beispielsweise alle Commits anzeigen möchtest, die zwischen dem 1. Juli 2014 und dem 4. Juli 2014 hinzugefügt wurden, gibst du Folgendes ein:

git log --after="2014-7-1" --before="2014-7-4"

Beachte, dass die Zusätze --since und --until synonym mit jeweils --after und --before sind.

Nach Autor

Wenn du nach Commits suchst, die von einem bestimmten Benutzer erstellt wurden, kannst du die Kennzeichnung --author verwenden. Mithilfe eines regulären Ausdrucks werden alle Commits angezeigt, deren Autor diesem Muster entspricht. Falls du genau weißt, nach wem du suchst, kannst du statt eines regulären Ausdrucks auch einen ganz einfachen String verwenden.

git log --author="John"

Hiermit werden alle Commits angezeigt, die den Autorennamen John enthalten. Der Autorenname muss nicht genau übereinstimmen, er muss nur den angegebenen Ausdruck enthalten.

Mit regulären Ausdrücken kannst du eine komplexere Suche durchführen. Zum Beispiel wird mit folgendem Befehl nach Commits gesucht, die entweder von Mary oder von John stammen.

git log --author="John\|Mary"

Zusätzlich zum Autorennamen ist auch dessen E-Mail-Adresse enthalten, sodass du bei dieser Option auch nach E-Mail-Adressen suchen kannst.

Wenn in deinem Workflow Committer von Autoren getrennt werden, funktioniert die Option --committer auf dieselbe Weise.

Nach Nachricht

Zum Filtern nach einer Commit-Nachricht bietet sich die Option --grep an. Sie funktioniert wie die oben besprochene Option --author, sucht aber Übereinstimmungen mit der Commit-Nachricht statt mit dem Autorennamen.

Wenn dein Team beispielsweise in jeder Commit-Nachricht relevante Issue-Nummern angibt, kannst du mit einem Befehl folgender Art alle Commits im Zusammenhang mit diesem Issue herausfiltern:

git log --grep="JRA-224:"

Außerdem kannst du den Parameter -i auf git log anwenden, um Unterschiede in der Groß- und Kleinschreibung beim Abgleich der Muster zu ignorieren.

Nach Datei

Oftmals sind nur die Änderungen an einer spezifischen Datei von Interesse. Um einen dateibezogenen Verlauf anzuzeigen, musst du nur den Dateipfad angeben. Wenn du alle Commits anzeigen möchtest, die entweder foo.py oder bar.py tangieren, gibst du den folgenden Befehl ein:

git log -- foo.py bar.py

Der Parameter -- teilt git log mit, dass die nachfolgenden Argumente Dateipfade und keine Branch-Namen sind. Falls keine Gefahr besteht, diese zu vermischen, kann -- auch weggelassen werden.

Nach Inhalt

Es ist auch möglich, nach Commits zu suchen, die eine bestimmte Zeile Quellcode einführen oder entfernen. Diese Funktion wird Pickaxe genannt und hat die Form -S"<string>". Wenn du z. B. wissen möchtest, wann der String Hallo Welt! zu Dateien des Projekts hinzugefügt wurde, fragst du dies folgendermaßen ab:

git log -S"Hello, World!"

Um die Suche mithilfe eines regulären Ausdrucks statt mit einem String durchzuführen, kannst du stattdessen -G"<regex>" verwenden.

Das ist ein sehr leistungsstarkes Debugging-Tool, da du auf diese Weise alle Commits lokalisieren kannst, die eine bestimmte Codezeile betreffen. Du kannst dir sogar anzeigen lassen, wann eine Zeile kopiert oder in eine andere Datei verschoben wurde.

Nach Bereich

Du kannst git log mit einem Bereich kombinieren, sodass nur dir Commits, die in diesen Bereich fallen, angezeigt werden. Der Bereich wird mit <since> und <until> als Commit-Referenzen spezifiziert:

git log <since>..<until>

Dieser Befehl ist besonders wertvoll, wenn wir Branch-Referenzen als Parameter verwenden. So lassen sich die Unterschiede zwischen zwei Branches mühelos abzurufen. Nehmen wir den folgenden Befehl:

git log master..feature

Der Bereich master..feature enthält alle Commits, die im feature Branch, aber nicht im master Branch enthalten sind. Anders gesagt: Hier sehen wir, wie weit sich der feature Branch entwickelt hat, seit er vom master abgezweigt wurde. Dies kann folgendermaßen visuell dargestellt werden:

Aufspüren einer Fork im Verlauf mithilfe von Bereichen

Hinweis: Wenn du die Reihenfolge umkehrst (feature..master), werden dir alle Commits angezeigt, die sich im master Branch, aber nicht im feature Branch befinden. Wenn git log Commits für beide Versionen ausgibt, weißt du, dass der Verlauf voneinander abweicht.

Filtern von Merge-Commits

Standardmäßig enthält git log Merge Commits in der Ausgabe. Manche Teams verfolgen jedoch eine Always-merge-Strategie: Sie mergen Upstream-Änderungen in Themen-Branches, statt den Themen-Branch auf den Upstream-Branch zu rebasen. Das resultiert in einer großen Menge an Merge-Commits im Projektverlauf.

Wenn du nicht möchtest, dass git log diese Merge-Commits anzeigt, kannst du --no-merges verwenden:

git log --no-merges

Wenn du aber nur an den Merge-Commits interessiert bist, kannst du --merges verwenden:

git log --merges

Hiermit werden alle Commits ausgegeben, für die mindestens zwei Parents vorhanden sind.

Summary

Nun solltest du in der Lage sein, die erweiterten git log-Parameter zur Formatierung der Ausgabe und Auswahl der anzuzeigenden Commits zu verwenden. Du kannst also genau die Informationen aus deinem Projektverlauf entnehmen, die du benötigst.

Diese Fähigkeit ist ein wichtiger Bestandteil im Git-Toolkit, aber git log wird häufig auch in Verbindung mit anderen Befehlen genutzt. Nachdem du den gewünschten Commit gefunden hast, wirst du ihn höchstwahrscheinlich mit git checkout, git revert oder einem anderen Tool weiter manipulieren. Deshalb solltest du dich unbedingt auch in die erweiterten Features von Git einlesen.

Ready to learn git log?

Sieh dir dieses interaktive Tutorial an.

Jetzt loslegen