statt sich auf den reinen End-Diff zu verlassen
Die Standardansicht eines Pull Requests zeigt fast immer nur den kumulierten Diff zwischen Ziel-Branch und letztem Commit. Damit geht verloren, wie eine Änderung tatsächlich entstanden ist: ob sie in einem sauberen, atomaren Commit entstand oder erst über mehrere Korrekturrunden zur finalen Form fand. Dieser Artikel zeigt, wie sich mit git log, git show, git range-diff und gezieltem interaktivem Rebase eine Commit-Historie vor dem Merge tatsächlich prüfen lässt, statt sich allein auf das Endergebnis zu verlassen.
Inhaltsverzeichnis
- 1. Warum der End-Diff beim Review zu kurz greift
- 2. git log als Ausgangspunkt für den Historie-Überblick
- 3. Einzelne Commits gezielt begutachten
- 4. Merge-Commits und First-Parent-Historie richtig lesen
- 5. Zwei-Punkt- und Drei-Punkt-Diff bei Feature-Branches unterscheiden
- 6. Commits über Rebase-Grenzen hinweg vergleichen mit git range-diff
- 7. Historie vor dem Review mit interaktivem Rebase aufräumen
- 8. Commit-für-Commit-Review in der Praxis: eine Checkliste
- 9. Log-Formate, Aliase und Editor-Integration für effizientes Review
- 10. Zusammenfassung
- 11. FAQ
1. Warum der End-Diff beim Review zu kurz greift
Ein Pull Request zeigt in der Standardansicht meist nur den kumulierten Diff zwischen dem Zielbranch und dem letzten Commit des Feature-Branches. Wer ausschließlich diese Ansicht prüft, sieht das Endergebnis, aber nicht den Weg dorthin. Ob eine Zeile in einem sauberen, atomaren Commit entstand oder erst nach drei Korrekturcommits ihre finale Form fand, geht im aggregierten Diff vollständig unter.
Gerade bei größeren Änderungen vermischt der End-Diff oft mehrere unabhängige Anliegen: ein Refactoring, eine Fehlerbehebung und eine neue Funktion erscheinen als eine einzige, unübersichtliche Änderungsmenge. Ein Review, das stattdessen die einzelnen Commits nachvollzieht, kann jede Absicht isoliert bewerten und Risiken deutlich gezielter einschätzen als beim Blick auf das reine Endresultat.
Ein weiterer Nachteil des reinen Diff-Reviews: Fehler, die in einem frühen Commit eingeführt und in einem späteren wieder korrigiert wurden, sind im End-Diff unsichtbar, tauchen aber in der vollständigen Historie klar auf. Das ist relevant, weil solche Muster oft zeigen, dass ein Autor eine Idee erst live im Code testen musste, was auf unzureichende Vorplanung oder auf ein unklares Anforderungsverständnis hindeuten kann.
2. git log als Ausgangspunkt für den Historie-Überblick
Bevor einzelne Commits im Detail geprüft werden, lohnt sich ein schneller Überblick über die Struktur der Historie. Die Kombination aus --oneline, --graph und --stat zeigt auf einen Blick, wie viele Commits ein Feature-Branch enthält, wie sie zueinander verzweigen und welche Dateien jeweils betroffen sind, ohne dass bereits ein einziger Diff-Hunk angezeigt wird.
Besonders die Anzahl der Commits ist ein erster Indikator: Zehn kleine, thematisch klar abgegrenzte Commits lassen sich meist zügiger und präziser prüfen als drei riesige Commits, die jeweils hunderte Zeilen in mehreren Modulen gleichzeitig ändern. Wer die Commit-Liste vor dem eigentlichen Review überfliegt, kann außerdem gezielt entscheiden, mit welchem Commit die tiefere Prüfung beginnt.
# Kompakter Überblick über alle Commits eines Feature-Branches
git log --oneline --graph --stat main..feature/checkout-redesign
# Nur die Commit-Nachrichten und betroffenen Dateien, ohne Diff-Inhalt
git log --stat --no-patch main..feature/checkout-redesign
3. Einzelne Commits gezielt begutachten
Für die eigentliche inhaltliche Prüfung ist git show das zentrale Werkzeug: Es zeigt Commit-Nachricht, Autor, Datum und den vollständigen Diff eines einzelnen Commits isoliert an, ohne den Kontext benachbarter Commits zu vermischen. Damit lässt sich Commit für Commit durch die Historie wandern, wobei jeder Schritt als in sich abgeschlossene Einheit bewertet wird.
Alternativ liefert git log -p dieselbe Information für eine ganze Reihe von Commits am Stück, was sich anbietet, wenn die gesamte Serie linear von Anfang bis Ende durchgegangen werden soll. In Kombination mit --reverse erscheinen die Commits dabei in chronologischer statt in umgekehrter Reihenfolge, was dem tatsächlichen Entstehungsprozess der Änderung entspricht und das Nachvollziehen erleichtert.
# Einen einzelnen Commit inklusive Diff isoliert betrachten
git show a1b2c3d
# Die gesamte Commit-Serie chronologisch, Commit für Commit
git log -p --reverse main..feature/checkout-redesign
4. Merge-Commits und First-Parent-Historie richtig lesen
Sobald ein Feature-Branch selbst Merges aus dem Zielbranch enthält, verändert sich das Bild: Ein normaler git log zeigt dann auch fremde Commits aus dem Zielbranch, die mit der eigentlichen Änderung nichts zu tun haben. Die Option --first-parent reduziert die Historie auf die Commits, die tatsächlich zum Feature-Branch gehören, und blendet die eingemergten Commits des Zielbranches aus.
Für Merge-Commits selbst zeigt git show standardmäßig nur eine Zusammenfassung ohne Diff, da ein Merge-Commit rein technisch zwei Elternteile hat. Mit der Option -m lässt sich der Diff eines Merge-Commits gegenüber jedem einzelnen Elternteil separat anzeigen, was hilfreich ist, um zu verstehen, welche konkreten Änderungen ein Merge gegenüber dem Hauptzweig tatsächlich einbringt.
# Nur die eigenen Commits des Feature-Branches, ohne eingemergte fremde Commits
git log --first-parent --oneline main..feature/checkout-redesign
# Diff eines Merge-Commits gegenüber jedem Elternteil einzeln anzeigen
git show -m 9f8e7d6
5. Zwei-Punkt- und Drei-Punkt-Diff bei Feature-Branches unterscheiden
Ein häufiger Stolperstein beim manuellen Review ist die Verwechslung von git diff main..feature und git diff main...feature. Die Zwei-Punkt-Form vergleicht den aktuellen Stand von main direkt mit dem aktuellen Stand von feature, während die Drei-Punkt-Form stattdessen den gemeinsamen Vorfahren beider Branches, den sogenannten Merge-Base, als Ausgangspunkt nimmt und nur die Änderungen zeigt, die seit dieser Verzweigung im Feature-Branch entstanden sind.
Ist main seit dem Abzweigen des Feature-Branches selbst weitergelaufen, liefern beide Varianten spürbar unterschiedliche Ergebnisse: Die Zwei-Punkt-Form vermischt fremde Änderungen aus main mit den eigentlichen Feature-Änderungen, während die Drei-Punkt-Form ausschließlich die für das Review relevanten Änderungen zeigt. Für ein sauberes Review ist die Drei-Punkt-Form daher fast immer die richtige Wahl.
# Vermischt Änderungen aus main mit den Feature-Änderungen
git diff main..feature/checkout-redesign
# Zeigt nur, was seit dem Abzweigen im Feature-Branch passiert ist
git diff main...feature/checkout-redesign
6. Commits über Rebase-Grenzen hinweg vergleichen mit git range-diff
Wird ein Feature-Branch während eines laufenden Reviews noch einmal rebased, etwa um Review-Kommentare umzusetzen, ändert sich für jeden nachfolgenden Commit die Commit-ID, selbst wenn der eigentliche Inhalt identisch bleibt. Ein einfacher erneuter Diff-Vergleich zeigt dann scheinbar alles als neu, obwohl sich inhaltlich oft nur wenige Zeilen geändert haben.
git range-diff löst genau dieses Problem: Es vergleicht zwei Versionen einer Commit-Serie inhaltlich miteinander, ordnet einander entsprechende Commits automatisch zu und zeigt an, welche Commits unverändert geblieben sind, welche sich inhaltlich verändert haben und welche neu hinzugekommen oder entfernt worden sind. Für Reviewer, die eine überarbeitete Version eines Branches erneut prüfen müssen, spart das erhebliche Zeit gegenüber einem kompletten erneuten Durchgang durch alle Commits.
# Alte gegen neue Version der Commit-Serie vergleichen,
# nach einem Rebase auf einen aktuelleren main-Stand
git range-diff main old-feature-branch@{1} feature/checkout-redesign
7. Historie vor dem Review mit interaktivem Rebase aufräumen
Ein Review wird deutlich einfacher, wenn die Historie vor der Prüfung bereits aufgeräumt ist. Interaktiver Rebase mit git rebase -i erlaubt es Autoren, reine Korrekturcommits wie fixup! oder squash! gezielt mit dem ursprünglichen Commit zu verschmelzen, bevor der Branch überhaupt zur Prüfung eingereicht wird.
Mit git commit --fixup lässt sich ein Korrekturcommit sofort dem passenden Ursprungscommit zuordnen, und git rebase -i --autosquash sortiert und verschmilzt diese Korrekturen automatisch an der richtigen Stelle. Das Ergebnis ist eine Historie, in der jeder verbleibende Commit tatsächlich einen eigenständigen, review-fähigen Gedanken darstellt, statt eine Abfolge von Versuch und Irrtum offenzulegen.
# Korrekturcommit direkt einem früheren Commit zuordnen
git commit --fixup a1b2c3d
# Vor dem Review: Korrekturcommits automatisch einsortieren und verschmelzen
git rebase -i --autosquash main
8. Commit-für-Commit-Review in der Praxis: eine Checkliste
Für ein systematisches Vorgehen hat sich eine kurze Checkliste bewährt: Ist jeder Commit für sich allein sinnvoll und nachvollziehbar? Bleibt der Code nach jedem einzelnen Commit in einem funktionsfähigen Zustand, sodass eine spätere Bisektion mit git bisect nicht an einem kaputten Zwischenschritt scheitert? Beschreibt die Commit-Nachricht das Warum der Änderung, nicht nur das offensichtliche Was?
Zusätzlich lohnt sich die Frage, ob thematisch zusammengehörige Änderungen tatsächlich in einem Commit gebündelt sind oder unnötig über mehrere Commits verstreut wurden. Beide Extreme, ein einziger riesiger Commit für alles und eine übertriebene Zersplitterung in dutzende Mikrocommits, erschweren das Review gleichermaßen, wenn auch aus entgegengesetzten Gründen.
9. Log-Formate, Aliase und Editor-Integration für effizientes Review
Wiederkehrende Log-Aufrufe lassen sich als Git-Alias dauerhaft hinterlegen, sodass ein kurzer Befehl wie git lg die gewohnte, sorgfältig konfigurierte Ausgabe liefert, statt jedes Mal lange Optionsketten erneut zu tippen. Auch eigene Formatstrings über --pretty=format: erlauben es, genau die Informationen anzuzeigen, die für das jeweilige Review relevant sind, etwa Autor, relatives Datum und Commit-Nachricht in einer einzigen Zeile.
Die meisten modernen IDEs, darunter PhpStorm, bieten zusätzlich eine grafische Commit-Historie mit anklickbaren Einzelcommits, Seite-an-Seite-Diffs und Blame-Integration, was den Wechsel zwischen Kommandozeile und visueller Prüfung erleichtert. Für tiefergehende Reviews bleibt die Kommandozeile aber oft die schnellere Wahl, weil sich Bereichsangaben wie Drei-Punkt-Diffs oder range-diff dort präziser und wiederholbarer formulieren lassen.
# Dauerhaften Alias für eine übersichtliche Log-Ausgabe anlegen
git config --global alias.lg "log --graph --oneline --decorate --abbrev-commit"
# Eigenes Format: Kurz-Hash, relatives Datum, Autor, Betreffzeile
git log --pretty=format:"%h %ad %an %s" --date=relative main..feature/checkout-redesign
| Kriterium | Reiner End-Diff-Review | Commit-für-Commit-Review | Empfehlung |
|---|---|---|---|
| Erkennt vermischte Anliegen | Nein, alles erscheint als eine Änderung | Ja, jeder Commit einzeln bewertbar | Commit-für-Commit |
| Zeigt zwischenzeitlich korrigierte Fehler | Nein, im Endresultat unsichtbar | Ja, in der Historie sichtbar | Commit-für-Commit |
| Aufwand bei kleinem, atomarem Branch | Sehr gering | Etwas höher, aber überschaubar | Beide geeignet |
| Aufwand bei großem, unstrukturiertem Branch | Gering, aber wenig aussagekräftig | Hoch, deckt dafür echte Risiken auf | Commit-für-Commit |
| Nützlich für spätere git bisect Läufe | Kein Effekt auf die Historie | Direkt, da jeder Commit geprüft wurde | Commit-für-Commit |
Mironsoft
Git-Workflows, Branching-Strategien und CI-Hooks
Chaotische Git-Historie und unklare Branching-Regeln im Team?
Wir richten saubere Git-Workflows ein, klären Branching-Strategien fürs Team und automatisieren Qualitätschecks über Git-Hooks und CI-Pipelines, damit die Historie nachvollziehbar bleibt.
Workflow-Audit
Bestehende Branching-Strategie und Merge-Praxis auf Schwachstellen prüfen.
Hook-Automatisierung
Pre-Commit- und Pre-Push-Hooks für Linting, Tests und Commit-Konventionen einrichten.
Team-Schulung
Rebase, Cherry-Pick und Konfliktauflösung im Team praxisnah vermitteln.
10. Zusammenfassung
Commit-Historie-Review
Kernproblem
Der End-Diff eines Pull Requests zeigt nur das Ergebnis, nicht den Entstehungsweg mit möglichen Zwischenfehlern.
Zentrale Werkzeuge
git log mit --graph und --stat für den Überblick, git show für einzelne Commits, git range-diff nach Rebases.
Vor dem Review
Historie mit interaktivem Rebase und --autosquash aufräumen, damit jeder Commit ein eigenständiger Gedanke ist.
Faustregel
Drei-Punkt-Diff gegenüber der Merge-Base statt Zwei-Punkt-Diff verwenden, um fremde Änderungen aus dem Vergleich auszuschließen.