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, ...).