Die Historie einer Datei über Umbenennungen hinweg verfolgen
Eine umbenannte Datei wirkt für git log wie eine neue Datei. Mit --follow bleibt die vollständige Historie sichtbar, allerdings nur unter bestimmten Bedingungen.
Inhaltsverzeichnis
- 1. Warum git log bei Umbenennungen abbricht
- 2. Wie Git Renames tatsächlich erkennt
- 3. git log --follow: Grundlagen und Syntax
- 4. Follow mit Patch-Ausgabe kombinieren
- 5. Grenzen von --follow
- 6. git blame und Rename-Erkennung
- 7. Ähnlichkeitsschwellwert anpassen
- 8. Praxisbeispiel: Mehrfach umbenannte Datei
- 9. Alternativen und ergänzende Werkzeuge
- 10. Zusammenfassung
- 11. FAQ
1. Warum git log bei Umbenennungen abbricht
Wird eine Datei umbenannt oder in ein anderes Verzeichnis verschoben, ändert sich für Git formal ihr Pfad. Ein einfacher Aufruf von git log mit dem aktuellen Dateipfad als Argument zeigt danach nur noch die Commits, die unter diesem Pfad entstanden sind.
Alle Commits, die vor der Umbenennung liegen, verschwinden aus der Ausgabe, obwohl der Inhalt der Datei durchgehend derselbe geblieben ist. Für jemanden, der die Entstehungsgeschichte einer zentralen Klasse nachvollziehen will, ist das ein echtes Problem.
Der Grund liegt in der Funktionsweise von Git selbst: Renames werden nicht als eigener Vorgang gespeichert, sondern erst nachträglich beim Anzeigen der Historie durch einen Aehnlichkeitsvergleich zwischen gelöschten und neu hinzugefügten Dateien erkannt.
# Zeigt nur Commits ab der Umbenennung, alte Historie fehlt
git log -- app/code/Vendor/Module/Model/PriceCalculator.php
# Vorherige Datei hieß anders, taucht hier nicht auf
git log -- app/code/Vendor/Module/Model/Calculator.php
2. Wie Git Renames tatsächlich erkennt
Git speichert bei jedem Commit den vollständigen Zustand des Repositories, nicht eine Kette von Diffs. Es gibt intern kein Feld, das eine Umbenennung explizit als solche markiert, anders als es manche andere Versionsverwaltungen tun.
Beim Erzeugen eines Diffs zwischen zwei Commits vergleicht Git stattdessen alle gelöschten mit allen neu hinzugefügten Dateien und berechnet einen Ähnlichkeitsindex. Überschreitet dieser Index einen Schwellwert, meldet Git die beiden Dateien als Rename, obwohl technisch nur eine Datei gelöscht und eine andere neu angelegt wurde.
Diese nachträgliche Erkennung ist der Grund, warum Rename-Tracking nicht überall gleich funktioniert. Werkzeuge, die keinen Aehnlichkeitsvergleich durchführen, sehen ausschließlich Löschung und Neuanlage, nicht die Umbenennung.
# Aehnlichkeitsindex für einen Commit anzeigen
git show --stat -M <commit-sha>
# R087 Model/Calculator.php Model/PriceCalculator.php
# R087 bedeutet 87 Prozent Aehnlichkeit zwischen alter und neuer Datei
3. git log --follow: Grundlagen und Syntax
Die Option --follow weist Git an, bei der Historie einer einzelnen Datei über erkannte Umbenennungen hinweg weiterzusuchen. Sobald Git in der Vergangenheit einen Commit findet, der die Datei als Rename markiert, springt die Suche automatisch zum vorherigen Pfad und setzt dort fort.
Wichtig ist die Einschränkung auf genau einen Dateipfad. --follow funktioniert nur, wenn nach einer einzelnen Datei gefiltert wird, nicht bei mehreren Pfaden oder Verzeichnissen gleichzeitig. Wird mehr als ein Pfad angegeben, ignoriert Git die Option stillschweigend.
Das Ergebnis ist eine zusammenhängende Historie über alle erkannten Umbenennungen hinweg, inklusive der Commits, die vor der ersten Umbenennung liegen, bis zur allerersten Erstellung der Datei unter irgendeinem ihrer früheren Namen.
# Vollständige Historie inklusive aller Umbenennungen
git log --follow -- app/code/Vendor/Module/Model/PriceCalculator.php
# Kompakter, eine Zeile pro Commit
git log --follow --oneline -- app/code/Vendor/Module/Model/PriceCalculator.php
4. Follow mit Patch-Ausgabe kombinieren
Reine Commit-Metadaten reichen oft nicht aus, wenn nachvollzogen werden soll, wie sich eine Datei inhaltlich verändert hat. Die Kombination aus --follow und -p zeigt für jeden Commit zusätzlich den vollständigen Diff, auch über Rename-Grenzen hinweg.
An der Stelle, an der die Umbenennung stattgefunden hat, zeigt der Diff sowohl den alten als auch den neuen Dateinamen an, oft zusammen mit inhaltlichen Änderungen, die im selben Commit stattgefunden haben. Das macht sichtbar, ob eine Umbenennung isoliert erfolgte oder Teil eines größeren Refactorings war.
Für sehr lange Historien lohnt sich zusätzlich --stat statt des vollen Patches, um zunächst nur die Größe jeder Änderung zu sehen und gezielt einzelne Commits für den vollen Diff auszuwählen.
# Vollständiger Diff über alle erkannten Umbenennungen hinweg
git log --follow -p -- app/code/Vendor/Module/Model/PriceCalculator.php
# Nur Statistik pro Commit, kompakter Überblick
git log --follow --stat -- app/code/Vendor/Module/Model/PriceCalculator.php
5. Grenzen von --follow
Die wichtigste Einschränkung wurde bereits genannt: --follow funktioniert ausschließlich mit genau einem Dateipfad. Wer die Historie mehrerer verschobener Dateien gleichzeitig verfolgen möchte, muss die Befehle einzeln für jede Datei ausführen.
Bei Merge-Commits kann die Rename-Erkennung unzuverlässig werden, insbesondere wenn eine Datei in einem Branch umbenannt und im anderen Branch inhaltlich stark verändert wurde. Der Aehnlichkeitsindex fällt dann unter den Schwellwert und Git erkennt keinen Zusammenhang mehr.
Auch mehrfache, kurz aufeinanderfolgende Umbenennungen mit gleichzeitig starken inhaltlichen Änderungen können die Kette unterbrechen. Je ähnlicher der Dateiinhalt zwischen den Versionen bleibt, desto zuverlässiger funktioniert --follow.
# Funktioniert NICHT: mehrere Pfade gleichzeitig mit --follow
git log --follow -- Model/PriceCalculator.php Model/TaxCalculator.php
# --follow wird hier stillschweigend ignoriert
# Stattdessen einzeln ausführen
git log --follow -- Model/PriceCalculator.php
git log --follow -- Model/TaxCalculator.php
6. git blame und Rename-Erkennung
Während --follow für git log gilt, hat git blame sein eigenes Vorgehen. Standardmäßig erkennt blame Umbenennungen innerhalb der Historie der aktuell betrachteten Datei nur eingeschränkt, verfolgt sie aber über die Option -C aktiv weiter.
Die Option -C weist blame an, auch nach Zeilen zu suchen, die ursprünglich in einer anderen Datei standen, etwa wenn Code aus einer Datei in eine andere kopiert oder verschoben wurde. Mehrfaches -C -C erweitert die Suche zusätzlich auf alle Dateien im selben Commit.
Für die reine Verfolgung eines Umbenennungspfads reicht meist ein einzelnes -C in Kombination mit -M, das explizit die Rename-Erkennung innerhalb einer Datei aktiviert, auch bei zusätzlichen inhaltlichen Änderungen im selben Commit.
# Blame mit aktivierter Rename- und Copy-Erkennung
git blame -C -M app/code/Vendor/Module/Model/PriceCalculator.php
# Blame für eine bestimmte Zeile, samt Ursprungscommit vor der Umbenennung
git blame -C -M -L 42,42 app/code/Vendor/Module/Model/PriceCalculator.php
7. Ähnlichkeitsschwellwert anpassen
Der Standard-Schwellwert für die Rename-Erkennung liegt bei 50 Prozent Aehnlichkeit. Für die meisten Fälle ist das ein sinnvoller Kompromiss, aber bei Dateien, die bei der Umbenennung gleichzeitig stark überarbeitet wurden, kann der Wert zu hoch liegen.
Über -M mit einem expliziten Prozentwert lässt sich der Schwellwert manuell senken, etwa auf 30 Prozent, um auch Umbenennungen mit umfangreicheren inhaltlichen Änderungen zu erkennen. Ein zu niedriger Wert erzeugt allerdings falsch positive Rename-Erkennungen bei völlig unabhängigen Dateien.
Der Parameter lässt sich sowohl bei git log als auch bei git diff und git blame setzen und wirkt sich direkt auf die Qualität der Rename-Erkennung in der jeweiligen Ausgabe aus.
# Schwellwert auf 30 Prozent senken, mehr Renames werden erkannt
git log --follow -M30% -- app/code/Vendor/Module/Model/PriceCalculator.php
# Schwellwert direkt im Diff anzeigen
git diff -M30% HEAD~5 HEAD
8. Praxisbeispiel: Mehrfach umbenannte Datei
In einem typischen Magento-Modul wandert eine zentrale Model-Klasse häufig mehrmals: Erst innerhalb desselben Verzeichnisses umbenannt, später beim Refactoring in ein neues Unterverzeichnis verschoben. --follow rekonstruiert diese gesamte Kette in einem einzigen Befehl.
Praktisch beginnt man mit dem aktuellen Pfad der Datei und lässt Git die ältere Historie selbst finden, statt manuell nach früheren Dateinamen zu suchen. Erst wenn --follow an eine erkennbare Grenze stößt, etwa weil der Aehnlichkeitsindex bei einer bestimmten Umbenennung zu niedrig ausfällt, muss manuell nach dem vermuteten früheren Namen weitergesucht werden.
Ein bewährtes Vorgehen dafür ist die Kombination aus --follow für den automatisierten Teil und einem gezielten git log --diff-filter=D mit einem Namensmuster, um gelöschte Dateien mit ähnlichem Namen manuell zu finden, falls die automatische Erkennung an ihre Grenzen stößt.
# Vollständige Kette rekonstruieren, aktueller Pfad als Startpunkt
git log --follow --oneline --name-status -- app/code/Vendor/Module/Model/PriceCalculator.php
# Falls die Kette abbricht: gezielt nach gelöschten ähnlichen Dateien suchen
git log --diff-filter=D --oneline --name-only -- '*Calculator*'
9. Alternativen und ergänzende Werkzeuge
Für die Historie eines ganzen Verzeichnisses statt einer einzelnen Datei bietet --follow keine Lösung. Hier hilft nur eine manuelle Rekonstruktion über mehrere git log --diff-filter=R Aufrufe, die gezielt nach Rename-Commits im relevanten Zeitraum suchen.
git log --all --full-history zeigt zwar alle Commits, die eine Datei jemals betroffen haben, folgt dabei aber nicht automatisch Umbenennungen und muss deshalb mit dem korrekten, jeweils gültigen Pfad kombiniert werden.
Für eine grafische Darstellung können GUI-Werkzeuge wie GitKraken oder die Historie-Ansicht in PhpStorm hilfreich sein, da sie Rename-Ketten oft visuell als durchgehende Linie darstellen, was das Verständnis komplexer Verschiebungen erleichtert.
# Alle Commits, die als Rename markiert sind, im gesamten Repository
git log --all --diff-filter=R --summary --oneline
# Vollständige Historie ohne Follow, mit explizitem full-history Flag
git log --full-history --oneline -- app/code/Vendor/Module/
| Befehl | Rename-Erkennung | Anwendungsfall | Einschränkung |
|---|---|---|---|
| git log | Keine | Aktuelle Historie ab letztem Pfad | Stoppt an jeder Umbenennung |
| git log --follow | Automatisch, ein Pfad | Komplette Datei-Historie | Nur ein Pfad gleichzeitig |
| git blame -C -M | Aktiv, zeilenbasiert | Ursprung einzelner Zeilen finden | Langsamer bei großen Repos |
| git log --diff-filter=R | Listet Rename-Commits | Manuelle Suche nach Umbenennungen | Kein automatisches Folgen |
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
git log --follow
Kernbefehl
git log --follow mit genau einem Dateipfad
Einschränkung
Funktioniert nur mit genau einem Dateipfad
Für Zeilen
git blame -C -M ergänzt --follow auf Zeilenebene
Schwellwert
Standard 50 Prozent, anpassbar über -M