CLI AI

Passwort aus der Git-Historie entfernen

2026-06-01

Ein Passwort aus der Git-Historie zu entfernen bedeutet, die Commits, die es enthalten, mit git filter-repo --invert-paths --path <file> umzuschreiben und danach den Reflog ablaufen zu lassen und Garbage Collection auszuführen, damit die alten Commits auch aus .git verschwinden. Mach das erst, nachdem du den Schlüssel rotiert hast — ein geleaktes Secret gilt in dem Moment als kompromittiert, in dem es committet wird, egal ob du die Historie später bereinigst. .gitignore und git rm --cached haben keinerlei Wirkung auf bereits existierende Commits.

1. Prüfen, ob das Secret noch in der Historie steckt

clai
$ clai prüfe, ob dieser Schlüssel noch irgendwo in der Repository-Historie steckt→ git log --all --oneline -S 'sk-live-abc123secret'0fb8c94 stop tracking .env4c1d9ff add app and env

-S findet Commits, bei denen sich die Anzahl der Vorkommen dieses Strings geändert hat — also wo das Secret hinzugefügt und wo es entfernt wurde. Die Suche läuft über die gesamte Historie aller Branches, nicht über das Arbeitsverzeichnis.

2. Bestätigen, dass Entfernen aus dem Index nichts gebracht hat

clai
$ clai hol die Datei .env aus dem Commit, in dem sie hinzugefügt wurde→ git show 4c1d9ff:.envAPI_KEY=sk-live-abc123secret

Das ist das ganze Problem in einem Befehl. .env ist aus dem Arbeitsverzeichnis verschwunden, steht in .gitignore, und git rm --cached wurde bereits ausgeführt — trotzdem holt jeder mit einem Klon das Secret mit einem einzigen Befehl heraus. Der Commit enthält weiterhin den vollständigen Inhalt.

3. Prüfen, in welchen Commits der Pfad vorkommt

clai
$ clai zeig alle Commits, die die Datei .env erwähnen→ git log --all --oneline -- .env0fb8c94 stop tracking .env4c1d9ff add app and env

Das ist die Liste dessen, was umgeschrieben werden muss. Zwei Commits, und du kommst glimpflich davon. Zweihundert, verteilt über mehrere Branches, und du musst dich erst mit dem ganzen Team abstimmen.

4. Erst rotieren, dann bereinigen

Ein Secret, das es in git geschafft hat, muss man als geleakt behandeln, ohne Ausnahme. Das Repository könnte längst geklont, geforkt, von einem Bot indexiert oder von CI gecacht worden sein, bevor der Fehler überhaupt auffällt. Widerrufe den Schlüssel und stelle einen neuen aus, bevor du die Historie anfasst: eine saubere Historie mit einem noch gültigen gestohlenen Schlüssel ist schlimmer als eine unaufgeräumte Historie mit einem bereits widerrufenen.

5. Historie mit dem richtigen Werkzeug umschreiben

clai
$ clai entferne die Datei .env aus der gesamten Repository-Historie→ git filter-repo --invert-paths --path .env⚠ DANGER — rewrites all history, every commit hash changes

git filter-repo ist das, was das git-Projekt selbst empfiehlt. git filter-branch gilt als veraltet: um Größenordnungen langsamer, und bei unvorsichtiger Nutzung kann es ein Repository stillschweigend beschädigen. BFG Repo-Cleaner ist die andere Option: schneller bei großen Repositories und kann einen String durch ***REMOVED*** ersetzen, statt die ganze Datei zu löschen.

6. Aufräumen, was lokal übrig bleibt

clai
$ clai lass alte Refs verfallen und führe aggressive Garbage Collection aus→ git reflog expire --expire=now --all && git gc --prune=now --aggressive

Nach dem Umschreiben bleiben die alten Commits über den Reflog erreichbar — das Secret liegt also weiterhin in .git. Dieser Befehl entfernt sie endgültig. Bei GitHub oder GitLab musst du separat den Support bitten, ihren Cache zu leeren, und um Forks kümmert sich niemand.

Fallstricke

  • Eine umgeschriebene Historie zerstört jeden Klon im Team. Nach dem Force-Push muss jeder neu klonen oder git rebase --onto machen. Warne die anderen vorher, sonst pusht jemand die alte Historie wieder zurück.
  • Forks und Pull Requests überleben. Auf GitHub kann ein Commit aus einem geschlossenen PR per Direktlink erreichbar bleiben, selbst nachdem das Hauptrepository bereinigt wurde. Noch ein Grund, den Schlüssel zu rotieren.
  • git filter-branch ist veraltet. Git selbst gibt beim Ausführen eine Warnung aus und verweist auf filter-repo. Die Hälfte der Artikel, die dafür ranken, weiß das noch nicht.

Verwandte Fragen

Reicht es, die Datei in .gitignore einzutragen? Nein. .gitignore betrifft nur neue Dateien. Alles bereits Committete bleibt vollständig in der Historie.

Wie verhindere ich das künftig? Ein Pre-Commit-Hook mit einem Secret-Scanner: gitleaks, detect-secrets oder trufflehog. Sie fangen den Schlüssel vor dem Commit ab, nicht danach.

Was, wenn das Secret schon auf GitHub ist? Sofort den Schlüssel widerrufen, dann die Historie bereinigen, dann den GitHub-Support bitten, gecachte Ansichten zu löschen. Genau in dieser Reihenfolge.

Siehe auch

CliAI stuft git filter-repo als DANGER ein und verlangt eine getippte Bestätigung, bevor auch nur ein Commit angefasst wird. In einer Zeile installieren.