Git: Wie sorgt man dafür, dass eine bereits getrackte Datei ignoriert wird?
Du hast etwas committet, das du nicht hättest committen sollen — eine .env,
ein Build-Verzeichnis — es danach in .gitignore eingetragen, und es taucht
weiterhin auf. Das ist keine kaputte Ignore-Regel. .gitignore wird für
Dateien, die git bereits verfolgt, gar nicht herangezogen.
Warum die Ignore-Regel nichts bewirkt
.gitignore : .env
tracked : .env .gitignore app.py
Die Datei ist gleichzeitig ignoriert und getrackt, und das Tracking gewinnt:
after editing it, status : M .env
.gitignore entscheidet, welche
ungetrackten Dateien git erwähnt und bei git add . mitnimmt. Sobald eine
Datei im Index steht, wird diese Liste für sie nicht mehr befragt. Die Regel tut
genau das, was sie sagt — sie gilt nur für diese Datei nicht.
Aus der Verfolgung nehmen
user@pc:~$ git rm --cached .env
user@pc:~$ git commit -m "stop tracking .env"
tracked : .gitignore app.py
on disk : .env .git .gitignore app.py
status : D .env
Das D sieht beunruhigend aus. Es bedeutet, dass eine Löschung gestaged
ist — aus Sicht von git verschwindet die Datei, und genau darum geht es. Die
Datei selbst liegt weiterhin auf der Platte, wie die Auflistung zeigt.
Nach dem Commit ist sie ungetrackt, .gitignore greift zum ersten Mal für sie,
und git status ist still:
after commit, status : ''
Ein Flag daneben und sie ist gelöscht
user@pc:~$ git rm .env # entfernt sie aus dem Index UND von der Platte
after 'git rm .env' : .git .gitignore app.py
Die Datei ist weg. Bei einer .env mit Zugangsdaten ist das ein schlechter
Nachmittag — es lohnt sich also, sich anzugewöhnen, --cached zu tippen bevor
man den Dateinamen tippt.
Für ein Verzeichnis
user@pc:~$ git rm -r --cached build
-r für rekursiv, wie bei rm. Alles darunter wird auf einmal aus der
Verfolgung genommen, und von der Platte verschwindet nichts.
.gitignore auf den ganzen Baum neu anwenden
Wenn sich mehrere Dateien eingeschlichen haben, mach es in einem Rutsch:
user@pc:~$ git rm -r --cached .
user@pc:~$ git add .
user@pc:~$ git commit -m "apply .gitignore"
Das nimmt alles aus der Verfolgung und fügt es wieder hinzu — und das
Wiederhinzufügen beachtet .gitignore sehr wohl, was auf eine Regel passt
bleibt also draußen. Gestaged bleibt genau die Menge an Dateien, die von Anfang
an hätte ignoriert werden sollen:
D .env
Aus deinem Arbeitsverzeichnis wird nichts gelöscht, nur der Index neu aufgebaut. Committe oder stashe trotzdem vorher deine eigentliche Arbeit, damit im anschließenden Diff nur das hier steht.
In der Historie bleibt sie trotzdem
Das ist der Teil, auf den es ankommt, wenn in der Datei ein Geheimnis stand:
user@pc:~$ git show HEAD~1:.env
SECRET=1
Eine Datei aus der Verfolgung zu nehmen ändert die Zukunft, nicht die Vergangenheit. Jeder Commit, der sie enthielt, enthält sie weiterhin, und jeder mit einem Klon hat sie.
Wenn also Zugangsdaten abgeflossen sind: wechsle sie. Das ist die Lösung.
Die Historie mit git filter-repo oder BFG umzuschreiben entfernt sie aus dem
Repository und ist der Ordnung halber sinnvoll — rückgängig macht es das Leck
aber nicht. Die alten Commits können längst in fremden Klonen, in CI-Caches, in
Forks und in Sicherungen liegen. Behandle das Umschreiben als Aufräumen nach der
eigentlichen Maßnahme, nicht als die Maßnahme.
Hinweis zu Netcup (Werbung)
Der deutsche Hoster Netcup bietet unter anderem günstige und zugleich leistungsstarke Webhosting Pakete, KVM-basierte Root Server und dezidierte Server an. Mit unseren Gutscheincodes kannst du noch mehr Geld sparen (6€ bei deiner ersten Bestellung, 30% Rabatt auf alle KVM-basierten Root Server, ...).