.git-blame-ignore-revs: Formatierungs-Commits aus git blame ausblenden
AI generated
git
HEAD
Git · Code-Historie
.git-blame-ignore-revs
Formatierungs-Commits aus der Blame-Historie ausblenden

Ein einzelner großflächiger Formatierungs-Commit reicht aus, um git blame für eine ganze Datei nutzlos zu machen, weil jede Zeile plötzlich auf diesen einen Commit zeigt statt auf die eigentliche fachliche Änderung. Die Datei .git-blame-ignore-revs löst genau dieses Problem, ohne die Commit-Historie selbst anzufassen.

9 Min. Lesezeit Git git blame Code-Historie

1. Wie Formatierungs-Commits die Blame-Historie zerstören

Sobald ein Team einen automatischen Formatter wie Prettier, PHP-CS-Fixer oder Black einführt, entsteht meist ein einziger grosser Commit, der den kompletten bestehenden Code auf einen Schlag umformatiert. Das ist inhaltlich sinnvoll, hat aber einen unangenehmen Nebeneffekt: git blame zeigt für praktisch jede Zeile im Projekt anschließend genau diesen Formatierungs-Commit an, unabhängig davon, wer die Zeile fachlich zuletzt geändert hat und warum.

Damit verliert git blame genau dort seinen Nutzen, wo er am wichtigsten ist, nämlich bei der Frage, wer eine bestimmte Zeile aus welchem Grund eingeführt hat. Wer nach der Formatierung eine Zeile untersucht, landet immer wieder beim selben Formatierungs-Commit und muss sich mühsam mit git log -L oder wiederholtem blame auf den Elter-Commit durch die eigentliche Historie durchhangeln.

2. Grundlagen: die Datei .git-blame-ignore-revs

Seit Git 2.23 unterstützt git blame die Option --ignore-revs-file, die eine Liste von Commit-Hashes entgegennimmt, die bei der Blame-Berechnung übersprungen werden sollen. Trifft eine Zeile auf einen ignorierten Commit, sucht Git automatisch im Elter-Commit weiter, bis eine Zeile bei einem nicht ignorierten Commit landet, der die fachliche Änderung tatsächlich repräsentiert.

Die Konvention hat sich etabliert, diese Liste in einer Datei namens .git-blame-ignore-revs im Wurzelverzeichnis des Repositories zu pflegen, mit einem Commit-Hash pro Zeile und optionalen Kommentaren, die mit einer Raute beginnen. Diese Datei wird ganz normal mitversioniert und wächst mit jedem weiteren großflächigen, rein mechanischen Commit.


# .git-blame-ignore-revs
# Einführung von Prettier über das gesamte Projekt
a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2

# PHP-CS-Fixer Regelsatz auf PSR-12 aktualisiert
9f8e7d6c5b4a9f8e7d6c5b4a9f8e7d6c5b4a9f8e

# Einmalige manuelle Anwendung mit dieser Datei
git blame --ignore-revs-file=.git-blame-ignore-revs pfad/zur/datei.php

3. Dauerhafte Konfiguration mit blame.ignoreRevsFile

Den Pfad bei jedem git blame Aufruf manuell anzugeben, ist unpraktisch, deshalb erlaubt Git, die Datei über git config blame.ignoreRevsFile dauerhaft zu hinterlegen. Danach berücksichtigt jeder git blame Aufruf im Repository automatisch die Liste, ohne dass zusätzliche Flags nötig sind.

Diese Konfiguration ist lokal und muss von jedem Entwickler einmal gesetzt werden, weshalb sich ein Hinweis in der README oder ein automatisiertes Setup-Skript anbietet, ähnlich wie bei anderen lokalen git config Einstellungen. Alternativ kann ein Team die Einstellung auch projektweit über eine gemeinsame .gitconfig mit include.path verteilen.


git config blame.ignoreRevsFile .git-blame-ignore-revs

# Danach reicht der normale Aufruf
git blame pfad/zur/datei.php

4. Unterstützung in PhpStorm und VS Code

Sowohl PhpStorm als auch Visual Studio Code respektieren die blame.ignoreRevsFile Konfiguration, sofern sie über git config lokal gesetzt ist, weil beide Editoren letztlich das systemweite Git-Binary mit der lokalen Konfiguration aufrufen. Das bedeutet, dass die Annotate- beziehungsweise Blame-Ansicht im Editor automatisch die ignorierten Commits überspringt, sobald die Konfiguration einmal gesetzt wurde, ganz ohne editor-spezifische Einstellung.

In der Praxis lohnt es sich trotzdem, nach einem Editor-Update oder einer Neuinstallation kurz zu prüfen, ob die Blame-Ansicht die erwarteten Commits überspringt, da manche Editor-Versionen die Konfiguration erst nach einem Neustart oder einer expliziten Cache-Invalidierung übernehmen.

5. Unterstützung in GitHub und GitLab

GitHub berücksichtigt eine Datei namens .git-blame-ignore-revs im Wurzelverzeichnis automatisch in der Web-Oberfläche der Blame-Ansicht, ohne dass eine zusätzliche Konfiguration nötig ist, solange die Datei exakt diesen Namen trägt. GitLab bietet eine vergleichbare Unterstützung über dieselbe Konvention, sodass ein Team, das die Datei einmal korrekt pflegt, von konsistentem Verhalten in Editor, Terminal und Web-Oberfläche profitiert.

Wichtig ist, dass beide Plattformen ausschließlich den Dateinamen im Wurzelverzeichnis erkennen und keine alternative Konfiguration über git config respektieren, weil sie schließlich nicht auf der lokalen Konfiguration eines einzelnen Entwicklers basieren können. Die Datei ist damit der einzige portable Ort, um diese Information plattformübergreifend zu teilen.

6. Grenzen: git log, bisect und Rebase

Die Ignore-Liste wirkt ausschließlich auf git blame und die davon abgeleiteten Annotate-Ansichten, nicht auf git log, git bisect oder andere Befehle, die die Commit-Historie durchsuchen. Ein Formatierungs-Commit taucht also weiterhin ganz normal in git log auf und kann bei einer git bisect Sitzung als regulärer Commit getestet werden, was gelegentlich zu falsch-positiven Ergebnissen führt, wenn der Formatierungs-Commit selbst versehentlich Verhalten verändert hat.

Bei einem interaktiven Rebase, der Commits vor dem Formatierungs-Commit verändert, ändern sich zwangsläufig auch dessen Hash und der aller nachfolgenden Commits, wodurch die Einträge in .git-blame-ignore-revs ungültig werden. Für Branches, die regelmässig rebased werden, lohnt es sich deshalb, die Ignore-Liste erst nach dem endgültigen Merge in den Hauptbranch zu pflegen, wo die Hashes stabil bleiben.

7. Workflow: einen neuen Formatierungs-Commit eintragen

Ein bewährter Ablauf besteht darin, den Formatierungs-Commit isoliert zu erstellen, ohne fachliche Änderungen im selben Commit, damit er später sauber ignoriert werden kann, ohne versehentlich echte Änderungen mit zu verstecken. Direkt nach dem Commit wird dessen Hash mit git log -1 --format=%H ermittelt und mit einem kurzen Kommentar in die Datei eingetragen.

Sinnvoll ist zusätzlich, diesen Schritt in die Pull-Request-Checkliste für großflächige, rein mechanische Änderungen aufzunehmen, damit er nicht vom individuellen Erinnerungsvermögen abhängt. Manche Teams automatisieren den Eintrag sogar über ein kleines Skript, das nach einem Formatter-Lauf automatisch den letzten Commit-Hash anhängt.


#!/usr/bin/env bash
# scripts/track-formatting-commit.sh
set -euo pipefail

HASH="$(git log -1 --format=%H)"
MESSAGE="$(git log -1 --format=%s)"

{
  echo ""
  echo "# ${MESSAGE}"
  echo "${HASH}"
} >> .git-blame-ignore-revs

echo "Commit ${HASH} zu .git-blame-ignore-revs hinzugefügt."

8. Automatisierung: CI-Check auf Aktualität der Datei

Damit die Ignore-Liste nicht schleichend veraltet, lohnt sich eine automatisierte Erinnerung im Pull-Request-Prozess: Ein CI-Job kann prüfen, ob ein Commit ausschließlich Whitespace- oder Formatierungs-Änderungen enthält, etwa über git diff --ignore-all-space im Vergleich zu einem regulären Diff, und in diesem Fall eine Warnung ausgeben, falls der Commit-Hash noch nicht in .git-blame-ignore-revs auftaucht.

Ein solcher Check ersetzt keine menschliche Entscheidung, weil nicht jeder grosse Diff automatisch ein reiner Formatierungs-Commit ist, aber er verhindert zuverlässig, dass ein Team schlicht vergisst, den Eintrag zu ergänzen, was in der Praxis der häufigste Grund für eine veraltete Ignore-Liste ist.

9. Alternative Strategien zur Vermeidung des Problems

Statt das Problem nachträglich zu lösen, lässt es sich teilweise von vornherein vermeiden, indem Formatierungs-Änderungen in kleinere, thematisch abgegrenzte Commits aufgeteilt werden, etwa pro Verzeichnis oder Modul statt für das gesamte Repository auf einmal. Das reduziert zwar nicht die Anzahl der betroffenen Zeilen, verteilt aber die Ignore-Einträge feiner und macht jeden einzelnen Commit leichter nachvollziehbar.

Eine ergänzende Strategie ist, Formatierungsregeln von Anfang an über einen Pre-Commit-Hook durchzusetzen, sodass gar keine grossen nachträglichen Formatierungs-Commits mehr nötig werden, weil jeder Commit bereits beim Erstellen automatisch korrekt formatiert ist. Für bereits bestehende Repositories bleibt .git-blame-ignore-revs aber der pragmatischste Weg, weil er die Vergangenheit nicht anfasst und sofort wirkt.

Werkzeug Beachtet .git-blame-ignore-revs Konfigurationsweg Wirkt auf git log
git blame (Terminal) Ja blame.ignoreRevsFile Nein
PhpStorm Annotate Ja Lokale git config Nein
VS Code GitLens/Blame Ja Lokale git config Nein
GitHub Web-Blame Ja Dateiname im Root Nein
GitLab Web-Blame Ja Dateiname im Root Nein

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-blame-ignore-revs

Mechanismus

git blame --ignore-revs-file springt zum Elter-Commit

Konfiguration

git config blame.ignoreRevsFile .git-blame-ignore-revs

Plattformen

GitHub und GitLab erkennen die Datei automatisch im Root

Grenze

Wirkt nicht auf git log, bisect oder die Historie selbst

11. FAQ: .git-blame-ignore-revs

1Ab welcher Git-Version funktioniert --ignore-revs-file?
Die Option wurde in Git 2.23 eingeführt, das seit Ende 2019 verfügbar ist. Praktisch jede aktuell genutzte Git-Installation unterstützt sie damit bereits, eine gesonderte Prüfung ist in modernen Teams selten nötig.
2Muss jeder Entwickler blame.ignoreRevsFile selbst konfigurieren?
Ja, weil es sich um eine lokale git config Einstellung handelt, die nicht automatisch aus dem Repository übernommen wird. Ein Setup-Skript oder ein Hinweis in der README stellt sicher, dass niemand diesen Schritt vergisst.
3Was passiert, wenn ein Commit-Hash in der Datei nicht existiert, etwa nach einem Rebase?
git blame ignoriert ungültige oder nicht auffindbare Hashes stillschweigend, ohne einen Fehler zu werfen. Das bedeutet allerdings auch, dass die betroffenen Zeilen nach einem Rebase wieder auf dem ursprünglichen, nun veralteten Formatierungs-Commit landen können.
4Kann ich mehrere Ignore-Dateien gleichzeitig verwenden?
Ja, mit mehreren --ignore-revs-file Flags oder mehreren blame.ignoreRevsFile Konfigurationszeilen lassen sich mehrere Dateien kombinieren, etwa eine gemeinsame Team-Datei und eine persönliche lokale Ergänzung.
5Beeinflusst die Ignore-Liste den Output von git log -p oder git show?
Nein, diese Befehle zeigen den Commit weiterhin vollständig an. Die Ignore-Liste wirkt ausschließlich auf die zeilenweise Zuordnung in git blame und den davon abgeleiteten Annotate-Ansichten in Editoren und Web-Oberflächen.
6Sollte ich sehr alte Formatierungs-Commits nachträglich noch eintragen?
Das lohnt sich, sofern der Commit-Hash noch bekannt und im Repository vorhanden ist, weil die Datei rückwirkend für die gesamte Historie wirkt. Bei sehr alten, häufig überschriebenen Bereichen ist der Nutzen allerdings geringer als bei kürzlich erfolgten Formatierungen.
7Wie gehe ich mit einem Commit um, der Formatierung UND eine echte Bugfix-Zeile enthält?
Solche gemischten Commits sollten möglichst vermieden werden, indem Formatierung und fachliche Änderung in getrennten Commits erfolgen. Ist der Commit bereits vermischt entstanden, sollte er nicht in die Ignore-Liste aufgenommen werden, weil sonst auch die fachliche Änderung in der Blame-Historie verschwindet.
8Funktioniert die Ignore-Datei auch bei git blame über die GitHub REST API oder GraphQL API?
Nein, die offiziellen APIs von GitHub berücksichtigen die Datei aktuell nicht, nur die Web-Oberfläche selbst wertet sie aus. Wer Blame-Daten programmatisch abruft, muss die Ignore-Liste selbst anwenden.
9Kann ich die Datei auch für squash-gemergte Feature-Branches nutzen?
Ja, sobald der Squash-Merge-Commit im Zielbranch existiert, kann sein Hash regulär in die Datei eingetragen werden, etwa wenn ein ganzes Feature nachträglich als reine Formatierungs-Umstellung erkannt wird.
10Gibt es ein Limit für die Anzahl der Einträge in .git-blame-ignore-revs?
Kein technisches Limit, die Datei kann beliebig viele Zeilen enthalten. In der Praxis bleibt sie bei den meisten Projekten überschaubar, weil großflächige Formatierungs-Commits selten und bewusst gesetzte Ereignisse sind.