Anleitung

git log, diff, show und blame: die Projekthistorie in Git lesen

Aktualisiert: · Skillaria.Top

git log zeigt die Liste der Commits und filtert sie nach Autor, Datum, Datei und Text; git diff vergleicht Arbeitsverzeichnis, Index und beliebige Commits; git show gibt einen Commit vollständig aus; git blame zeigt, welcher Commit jede Zeile einer Datei zuletzt geändert hat.

Vier Befehle beantworten fast alle Fragen zur Projekthistorie. git log beantwortet „was ist passiert“, git diff – „was genau hat sich geändert“, git show – „was steckt in einem bestimmten Commit“, git blame – „wer hat diese Zeile wann geschrieben“. Unten finden Sie praxiserprobte Techniken für jeden davon, mit den Flags, die im Entwickleralltag wirklich verwendet werden.

git log: die Liste der Commits

Ohne Argumente gibt git log die Commits des aktuellen Branches von neu nach alt aus: vollständiger SHA-1-Hash, Autor, Datum und Nachricht. Geblättert wird im Pager (meist less): Leertaste – nächste Seite, /text – Suche, q – Beenden.

commit 7be41d0c9a2e4f1b8d6c3e5a7f9b0c2d4e6f8a1b
Author: Anna Petrova <anna@example.com>
Date:   Mon Oct 5 14:22:10 2026 +0300

    feat: Caching von API-Antworten

Den Hash müssen Sie nicht vollständig kopieren: Git versteht jedes eindeutige Präfix ab 4 Zeichen, in der Praxis reichen 7.

Kompakte Ausgabe: --oneline

git log --oneline -10
# 7be41d0 (HEAD -> main, origin/main) feat: Caching von API-Antworten
# 1c02e8f fix: Request-Timeout
# 9a4b3c2 refactor: Client in eigenes Modul ausgelagert

Das Flag -10 (oder -n 10) begrenzt die Anzahl der Commits. In Klammern stehen die Zeiger: wo HEAD, lokale und Remote-Branches sowie Tags liegen.

Branch-Graph: git log --graph

Wer nach „git graph“ sucht, meint meist genau das: eine Visualisierung von Verzweigungen und Merges direkt im Terminal.

git log --oneline --graph --all
# * 3e1f0aa (feature/auth) feat: Login per Token
# | * 7be41d0 (HEAD -> main) feat: Caching von API-Antworten
# |/
# * 1c02e8f fix: Request-Timeout
# *   5d2c7b1 Merge branch 'feature/search'
# |\
# | * 8f3a9e0 feat: Suche
# |/
# * 9a4b3c2 refactor: Client in eigenes Modul ausgelagert

--all zeigt alle Branches, nicht nur den aktuellen. Praktisch ist ein Alias: git config --global alias.lg "log --oneline --graph --all --decorate", danach genügt git lg.

Eigenes Format: --pretty=format

git log --pretty=format:"%h %ad %an %s" --date=short
# 7be41d0 2026-10-05 Anna Petrova feat: Caching von API-Antworten

Wichtige Platzhalter: %h – kurzer Hash, %H – vollständiger, %an – Autor, %ae – dessen E-Mail, %ad – Autorendatum, %ar – relatives Datum („2 days ago“), %s – Betreffzeile der Nachricht.

Die Historie in git log filtern

Nach Autor und Datum

git log --author="Anna"
git log --since="2 weeks ago" --until="2026-10-01"
git log --since=yesterday --oneline

--author akzeptiert einen regulären Ausdruck und durchsucht Name und E-Mail. Datumsangaben versteht Git sowohl in freier Form als auch in ISO.

Nach Text der Commit-Nachricht

git log --grep="fix" -i --oneline

-i macht die Suche unabhängig von Groß- und Kleinschreibung. Wenn Ihr Team Ticketnummern in die Nachrichten schreibt, finden Sie so schnell alle Commits zu einem Ticket.

Nach Datei oder Ordner

git log --oneline -- src/api/client.py
git log --follow -p -- src/api/client.py

Der doppelte Bindestrich trennt Pfade von Branches. --follow verfolgt die Historie einer Datei über Umbenennungen hinweg (funktioniert für eine Datei), -p zeigt den Patch jedes Commits.

Nach geändertem Code: die „Pickaxe“-Suche

git log -S "retry_count" --oneline     # Commits, in denen sich die Anzahl der Vorkommen des Strings geändert hat
git log -G "timeout\s*=" --oneline    # Commits, deren diff Zeilen enthält, die zum Regex passen

-S findet den Commit, in dem eine Funktion oder Variable hinzugefügt oder entfernt wurde – unverzichtbar, wenn Sie verstehen müssen, wohin ein Stück Code verschwunden ist.

Commit-Bereiche

git log main..feature      # was in feature ist, aber nicht in main
git log origin/main..HEAD  # meine lokalen, noch nicht gepushten Commits
git log --no-merges        # ohne Merge-Commits
git log --stat             # welche Dateien und wie viele Zeilen geändert wurden

git diff: was genau hat sich geändert

Das Wichtigste bei git diff: Welche zwei Zustände vergleicht er? Verwechslungen hier sind der Grund für die Frage „warum ist der diff leer, ich habe doch alles geändert“.

BefehlWas verglichen wird
git diffArbeitsverzeichnis gegen Index (nicht vorgemerkte Änderungen)
git diff --staged (--cached)Index gegen letzten Commit (was in den Commit eingeht)
git diff HEADArbeitsverzeichnis gegen letzten Commit (alles zusammen)
git diff A Bzwei Commits, Branches oder Tags
git diff A...BÄnderungen in B seit der Abzweigung von A

Nach git add wird ein normales git diff leer – die Änderungen liegen bereits im Index, schauen Sie mit --staged. Neue, nie hinzugefügte Dateien zeigt diff überhaupt nicht an.

Die diff-Ausgabe lesen

diff --git a/config.py b/config.py
index 3b18e51..a1c4f02 100644
--- a/config.py
+++ b/config.py
@@ -10,7 +10,7 @@ DEFAULTS = {
     "host": "localhost",
-    "timeout": 5,
+    "timeout": 30,
     "retries": 3,

Zeilen mit - wurden entfernt, mit + hinzugefügt, der Rest ist Kontext. Der Header @@ -10,7 +10,7 @@ bedeutet: Der Abschnitt beginnt in Zeile 10 und umfasst 7 Zeilen in der alten und der neuen Version.

Nützliche Flags für git diff

git diff --stat main feature      # Übersicht pro Datei
git diff --name-only HEAD~3       # nur die Namen geänderter Dateien
git diff --word-diff               # Änderungen wortweise, praktisch für Texte
git diff -w                        # Whitespace-Änderungen ignorieren
git diff main feature -- src/      # auf einen Ordner beschränken

Vor jedem Commit lohnt sich ein Blick auf git diff --staged: Das ist die letzte Chance, ein vergessenes Debug-print oder eine versehentlich hinzugefügte Datei zu bemerken.

git show: einen Commit vollständig anzeigen

git show gibt die Metadaten eines Commits und seinen diff gegenüber dem Eltern-Commit aus. Ohne Argumente – den letzten Commit.

git show 7be41d0
git show HEAD~2 --stat           # ohne Patch, nur Übersicht
git show v1.2.0                  # Tag: Annotation und Commit
git show main:src/config.py      # Datei so, wie sie im Commit war

Die letzte Form <revision>:<pfad> ist besonders nützlich: Sie sehen eine alte Version einer Datei, ohne zu ihr zu wechseln. Leiten Sie die Ausgabe in eine Datei um, und Sie stellen gelöschten Inhalt ohne checkout wieder her.

git blame: wer hat diese Zeile geändert

git blame datei zeigt für jede Zeile den letzten Commit, der sie geändert hat, sowie Autor und Datum. Der Name klingt nach Schuldzuweisung, tatsächlich ist es ein Werkzeug zur Kontextsuche: den Commit finden, die Nachricht lesen und verstehen, warum etwas so gemacht wurde.

git blame -L 40,60 src/api/client.py
# 1c02e8f3 (Anna Petrova 2026-09-28 11:04:51 +0300 41)     timeout = settings.timeout
# 9a4b3c2e (Ivan Smirnov 2026-09-14 18:30:02 +0300 42)     session = build_session()
  • -L 40,60 – nur ein Zeilenbereich; möglich ist auch -L :funktionsname.
  • -w – Whitespace-Änderungen ignorieren, um nicht bei Formatierungs-Commits zu landen.
  • -C – Zeilen verfolgen, die aus anderen Dateien verschoben wurden.
  • --ignore-rev <hash> oder die Datei .git-blame-ignore-revs – Massen-Commits wie automatisches Formatieren überspringen.

Typischer Ablauf einer Untersuchung: git blame findet den Commit, git show zeigt ihn vollständig, git log für die Datei liefert die benachbarten Änderungen.

Auf Commits können Sie nicht nur per Hash verweisen. HEAD~1 ist der Eltern-Commit des aktuellen, HEAD~3 der Urgroßelternteil. HEAD^2 ist der zweite Elternteil eines Merge-Commits. Auch Namen von Branches, Tags und Remote-Branches funktionieren: origin/main~2. Das gesamte Projekt in einem alten Commit sehen Sie mit git switch --detach <hash>, zurück geht es mit git switch -.

Gute und schlechte Historie

All diese Befehle sind genau so nützlich, wie die Historie aussagekräftig ist. Nachrichten wie „fix“, „wip“, „noch Änderungen“ machen git log --grep und git blame nutzlos. Ein guter Commit ist eine logische Änderung mit einer Betreffzeile, die erklärt, was und warum: fix: API-Timeout wegen langsamem Gateway auf 30 s erhöht. Genau so einen Commit findet blame in einem halben Jahr und spart Ihnen eine Stunde.

Praxis: einen Bug anhand der Historie aufklären

Angenommen, nach dem letzten Release schlagen API-Anfragen wegen Timeouts fehl. So führt die Kombination der Befehle in wenigen Minuten zur Ursache.

  1. Wir sehen nach, was ins Release eingegangen ist: git log v1.4.0..v1.5.0 --oneline. Die Liste ist kurz, aber anhand der Betreffzeilen ist der Schuldige nicht offensichtlich.
  2. Wir grenzen nach Datei ein: git log v1.4.0..v1.5.0 --oneline -- src/api/. Es bleiben zwei Commits.
  3. Wir suchen im Code: git log -S "timeout" --oneline -- src/api/ findet den Commit, in dem sich der Timeout-Wert geändert hat.
  4. Wir sehen ihn uns vollständig an: git show 1c02e8f. Im diff ist zu sehen, dass der Timeout von 30 auf 5 Sekunden reduziert wurde, in der Nachricht steht die Begründung – „UI-Reaktion beschleunigen“.
  5. Wir prüfen, wer diese Zeile noch angefasst hat: git blame -L :build_session src/api/client.py.

Ab hier ist die Lösung eine technische Entscheidung: den Wert zurücksetzen, den Timeout in die Einstellungen auslagern oder den Commit per git revert rückgängig machen. Gibt es dagegen Hunderte Commits und lässt sich der Schuldige nicht mit bloßem Auge finden, hilft git bisect – eine binäre Suche in der Historie, die in wenigen Schritten den Commit findet, der das Verhalten kaputt gemacht hat.

Einstellungen, die das Leben leichter machen

git config --global log.date iso            # Datumsformat in log
git config --global diff.colorMoved zebra   # verschobene Zeilen im diff hervorheben
git config --global core.pager "less -FRX"  # Pager bei kurzer Ausgabe nicht öffnen

Wenn die Ausgabe per Skript verarbeitet werden soll, schalten Sie Farben und Pager ab: git --no-pager log --format="%H %s" --no-color. Verwenden Sie für die maschinelle Verarbeitung den vollständigen Hash %H: Kurze Präfixe können in einem großen Repository mit der Zeit mehrdeutig werden.

Fazit

git log mit den Filtern --oneline, --graph, --author, -S und Pfaden beantwortet die Frage „was ist passiert“. git diff vergleicht Arbeitsverzeichnis, Index und Commits – wichtig ist, sich zu merken, was er standardmäßig vergleicht. git show öffnet einen einzelnen Commit oder eine alte Dateiversion, und git blame führt von einer Codezeile zur Entscheidung, die sie hervorgebracht hat. Das Lesen der Historie und die Navigation zwischen Commits üben wir praktisch in unserem Git-Kurs.

Häufige Fragen

Wie beende ich git log?

Drücken Sie q – die Ausgabe ist im Pager less geöffnet; um ohne Pager auszugeben, verwenden Sie git --no-pager log oder das Flag -n mit einer kleinen Zahl.

Wie sehe ich die Historie einer gelöschten Datei?

Führen Sie git log --oneline -- pfad/zur/datei aus (mit doppeltem Bindestrich), den Inhalt vor dem Löschen zeigt git show &lt;hash&gt;^:pfad/zur/datei.

Wie vergleiche ich einen lokalen Branch mit dem Remote-Branch?

Zuerst git fetch, dann git diff origin/main oder git log origin/main..HEAD, um Ihre noch nicht gepushten Commits zu sehen.

Gibt es eine grafische Ansicht der Historie?

Ja, Git bringt gitk mit, außerdem ist ein Historien-Graph in VS Code, JetBrains-IDEs und den Weboberflächen von GitHub und GitLab integriert.

Warum zeigt git diff nichts an?

Höchstwahrscheinlich sind die Änderungen bereits per git add im Index – schauen Sie mit git diff --staged; neue, nicht getrackte Dateien zeigt git diff überhaupt nicht.

Das Thema im Video lernen

Dieses Thema wird im Kurs „Git vom Anfänger zum versierten Entwickler“ ausführlich mit Praxis behandelt.

Zum Kurs