Wie kann man Git dazu bringen, eine Datei zu "vergessen", die verfolgt wurde, sich aber jetzt in .gitignore befindet?


5401

Es gibt eine Datei, die verfolgt wurde git, aber jetzt ist die Datei in der .gitignoreListe.

Diese Datei wird jedoch git statusnach der Bearbeitung immer wieder angezeigt. Wie zwingen Sie es, gites komplett zu vergessen?


16
git clean -Xklingt ähnlich, trifft aber in dieser Situation nicht zu (wenn die Dateien noch von Git verfolgt werden). Ich schreibe dies für alle, die nach einer Lösung suchen, um nicht den falschen Weg zu gehen.
imz - Ivan Zakharyaschev

35
Die einzige wirkliche Antwort darauf finden Sie weiter unten git update-index --assume-unchanged. Diese Lösung 1) hält die Datei auf dem Server (Index), 2) ermöglicht es Ihnen, sie lokal frei zu ändern.
Qwerty

8
Sie müssen verwenden --skip-worktree, siehe: stackoverflow.com/questions/13630849/…
Doppelgänger

77
Eine wichtige Frage ist: Soll die Datei im Repository bleiben oder nicht? Wenn beispielsweise jemand das Repo neu klont, sollte er die Datei erhalten oder nicht? Wenn JA dann git update-index --assume-unchanged <file>korrekt ist und die Datei im Repository verbleibt und Änderungen nicht mit hinzugefügt werden git add. Wenn NO (z. B. eine Cache-Datei, eine generierte Datei usw.), git rm --cached <file>wird diese aus dem Repository entfernt.
Martin

9
@Martin @Qwerty Jeder sollte aufhören zu beraten, für --assume-unchangedwelche Leistung, um zu verhindern, dass Git den Status von großen verfolgten Dateien überprüft, bevorzugt jedoch, --skip-worktreewelche für modifizierte verfolgte Dateien, die der Benutzer nicht mehr festschreiben möchte . Siehe stackoverflow.com/questions/13630849/…
Philippe

Antworten:


5703

.gitignoreverhindert, dass nicht verfolgte Dateien (ohne ein add -f) zu dem von git verfolgten Dateisatz hinzugefügt werden. git verfolgt jedoch weiterhin alle Dateien, die bereits verfolgt werden.

Um die Verfolgung einer Datei zu beenden, müssen Sie sie aus dem Index entfernen. Dies kann mit diesem Befehl erreicht werden.

git rm --cached <file>

Wenn Sie einen ganzen Ordner entfernen möchten, müssen Sie alle darin enthaltenen Dateien rekursiv entfernen.

git rm -r --cached <folder>

Das Entfernen der Datei aus der Kopfrevision erfolgt beim nächsten Commit.

WARNUNG: Dadurch wird zwar die physische Datei nicht von Ihrem lokalen Computer entfernt, aber beim nächsten Mal werden die Dateien von anderen Entwicklercomputern entfernt git pull.


55
Der Prozess, der für mich funktioniert hat, war 1. zuerst ausstehende Änderungen festschreiben 2. git rm --cached <Datei> und erneut festschreiben 3. die Datei zu .gitignore hinzufügen, mit dem git-Status prüfen und erneut
festschreiben

117
Sehr wichtiges Hinzufügen. Wenn eine ignorierte Datei geändert wird (aber trotzdem nicht festgeschrieben werden sollte), wird sie nach dem Ändern und Ausführen git add .dem Index hinzugefügt. Und das nächste Commit würde es in das Repository übertragen. Um dies zu vermeiden, führen Sie gleich nach all dem, was Mataal sagte, einen weiteren Befehl aus:git update-index --assume-unchanged <path&filename>
Dao

32
Die Methode von @AkiraYamamoto hat auch bei mir gut funktioniert. In meinem Fall habe ich die Ausgabe unterdrückt, da mein Repository Tausende von Dateien hatte:git rm -r -q --cached .
Aaron Blenkush

85
Dadurch wird die Datei jedoch gelöscht git pull.
Petr Peller

22
git rm --cached <Datei> entfernt einfach die Datei aus dem Repository, git update-index --assume-unverändert <Datei> wird in nicht bereitgestellten Änderungen nicht angezeigt und führt keine neuen Änderungen durch. Aber ich möchte, dass GIT den Inhalt der Datei bitte ignoriert
Igor Semin

2609

Die folgende Befehlsreihe entfernt alle Elemente aus dem Git-Index (nicht aus dem Arbeitsverzeichnis oder dem lokalen Repo) und aktualisiert dann den Git-Index, wobei git ignoriert wird. PS. Index = Cache

Zuerst:

git rm -r --cached . 
git add .

Dann:

git commit -am "Remove ignored files"

Oder einzeilig:

git rm -r --cached . && git add . && git commit -am "Remove ignored files"

197
Um den Unterschied zwischen dieser und der akzeptierten Antwort hervorzuheben: Mit diesen Befehlen müssen Sie die betroffenen Dateien nicht wirklich kennen. (Stellen Sie sich ein temporäres Verzeichnis mit vielen zufälligen Dateien vor, die aus dem Index gelöscht werden sollen.)
Ludwig

53
Gleich wie die akzeptierte Antwort. Dateien werden am gelöscht git pull.
Petr Peller

73
Es wäre schön, dies als Standard-Git-Befehl zu haben. So etwas wie git rmignored.
Berik

12
@gudthing -r steht für "rekursiv"
Mark

14
Damit können Sie möglicherweise andere nutzlose Dateien hinzufügen , die sich derzeit nicht in befinden .gitignore. Was schwierig herauszufinden sein kann, hängt davon ab, wie laut Sie git statusnach diesem Befehl sind. Ein Befehl, der nur neu ignorierte Dateien entfernt, ist besser. Deshalb bevorzuge ich die Antwort von
thSoft

1122

git update-index erledigt den Job für mich:

git update-index --assume-unchanged <file>

Hinweis: Diese Lösung ist tatsächlich unabhängig von, .gitignoreda Gitignore nur für nicht verfolgte Dateien gilt.

Bearbeiten: Da diese Antwort veröffentlicht wurde, wurde eine neue Option erstellt, die bevorzugt werden sollte. Sie sollten --skip-worktreediese Option für geänderte nachverfolgte Dateien verwenden, die der Benutzer nicht mehr --assume-unchangedfestschreiben möchte, und die Leistung beibehalten, um zu verhindern, dass git den Status großer nachverfolgter Dateien überprüft. Weitere Informationen finden Sie unter https://stackoverflow.com/a/13631525/717372 ...

git update-index --skip-worktree <file>

173
Das IST die wirkliche Antwort. Genial eigentlich, sehr einfach, verschmutzt nicht git statusund eigentlich sehr intuitiv. Vielen Dank.
Pablo Olmos de Aguilera C.

4
Ich entschied mich für die rm [...] .Lösung, die gut genug war , da ich zumindest herausfinden konnte, wie es funktionierte. Ich habe keine großartige Dokumentation darüber gefunden, was update-index& --assume-unchangedtun soll. Kann jemand hinzufügen, wie dies im Vergleich zum anderen ist, indem ich alle Dateien entfernen möchte, die ignoriert worden wären? (Oder ein Link zur klaren Erklärung?)
Brady Trainor

25
git update-index --assume-unchanged <path> …bewirkt, dass git Änderungen an den angegebenen Pfaden ignoriert, unabhängig davon .gitignore. Wenn Sie von einer Fernbedienung ziehen und diese Fernbedienung Änderungen an diesem Pfad aufweist, schlägt git die Zusammenführung mit einem Konflikt fehl und Sie müssen manuell zusammenführen. git rm --cached <path> …wird dazu führen, dass git diesen Pfad nicht mehr verfolgt. Wenn Sie den Pfad nicht hinzufügen, .gitignorewird der Pfad in Zukunft angezeigt git status. Die erste Option weist weniger Rauschen im Git-Commit-Verlauf auf und ermöglicht die zukünftige Verteilung von Änderungen an der "ignorierten" Datei.
ManicDee

26
Ich bin ziemlich verwirrt darüber, dass dies nicht die akzeptierte Antwort ist. Die hier akzeptierte Antwort beantwortet eindeutig nicht die tatsächlich gestellte Frage. Diese Antwort ignoriert Änderungen an der Datei im Repository, ohne sie aus dem Repository zu entfernen.
Dave Cooper

11
Diese Antwort wäre viel nützlicher, wenn sie genau erklären würde, was der angegebene Befehl tut, z. B. wie er sich von den anderen vorgeschlagenen Lösungen unterscheidet.
LarsH

283
git ls-files --ignored --exclude-standard -z | xargs -0 git rm --cached
git commit -am "Remove ignored files"

Dadurch wird die Liste der ignorierten Dateien aus dem Index entfernt und die Änderungen werden festgeschrieben.


7
Wenn Sie sie auch aus dem Arbeitsverzeichnis entfernen müssen, führen Sie sie einfach aus git ls-files --ignored --exclude-standard | xargs git rm . Ich glaube, diese Antwort ist die beste! Weil es sehr klar ist, Unix-artig und das Gewünschte direkt ausführt, ohne die Nebenwirkungen anderer, komplexerer Befehle zu komponieren.
imz - Ivan Zakharyaschev

6
Gute Antwort; Der Befehl schlägt jedoch fehl, wenn Sie Pfade mit Leerzeichen in der Mitte haben, z. B.: "My dir / my_ignored_file.txt"
David Hernandez

8
git ls-files --ignored --exclude-standard | sed 's /.*/"&"/' | xargs git rm --cached
David Hernandez

3
git rmwird sich beschweren, wenn ls-filesnichts passt. Verwenden Sie xargs -r git rm ...diese Option xargs, um anzugeben , dass nicht ausgeführt werden soll, git rmwenn keine Dateien übereinstimmen.
Wolfgang

10
Es wäre besser, \ 0 als Trennzeichen zu verwenden:git ls-files --ignored --exclude-standard -z|xargs -0 git rm --cached
Nils-o-mat

83

Ich benutze diesen Befehl immer, um diese nicht verfolgten Dateien zu entfernen. Einzeilige, saubere Ausgabe im Unix-Stil:

git ls-files --ignored --exclude-standard | sed 's/.*/"&"/' | xargs git rm -r --cached

Es listet alle ignorierten Dateien auf, ersetzt stattdessen jede Ausgabezeile durch eine Zeile in Anführungszeichen, um Pfade mit Leerzeichen zu behandeln, und git rm -r --cachedübergibt alles , um die Pfade / Dateien / Verzeichnisse aus dem Index zu entfernen.


3
Tolle Lösung! Hat perfekt funktioniert und fühlt sich korrekter an, als alle Dateien zu entfernen und wieder hinzuzufügen.
Jon Catmull

5
Auch ich fand das "sauberste". Es mag offensichtlich sein, aber wenn Sie nur den ersten Teil git ls-files --ignored --exclude-standardalleine .gitignoreausführen, können Sie zunächst verstehen / überprüfen, welche Dateien Ihre neuen ausschließen / entfernen werden, bevor Sie fortfahren und das Finale ausführen git rm.
JonBrave

Beachten Sie, dass Dateinamen mit bestimmten "bösen" Zeichen fehlschlagen, z \n. Ich habe meine Lösung veröffentlicht, um dies zu berücksichtigen.
JonBrave

3
Eine weitere Einschränkung: Beim Ziehen wird die Datei in den Arbeitsverzeichnissen anderer gelöscht, oder?
LarsH

versucht, aber bei mir nicht funktioniert: sed: 1: "s/.*/": unterminated substitute in regular expressionin einem Filter-Branch-Befehl auf einem Repo mit Leerzeichen. (Schien aber außerhalb des Filterzweigs zu arbeiten). Ich habe stattdessen die Antwortgit ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached von @ JonBrave verwendet.
Goofology

71

Verschieben Sie es heraus, legen Sie es fest und dann wieder hinein. Dies hat in der Vergangenheit bei mir funktioniert. Es gibt wahrscheinlich einen "gittier" Weg, um dies zu erreichen.


2
Dies hat hervorragend funktioniert, wenn Sie eine Reihe von Dateien ignorieren möchten, die zuvor nicht ignoriert wurden. Obwohl, wie Sie sagten, es wahrscheinlich einen besseren Weg dafür gibt.
Oskar Persson

Genau das habe ich getan. Verschieben Sie die Dateien einfach in einen Ordner außerhalb von git und führen Sie dann "git add." Und "git commit" aus. (Dadurch wurden die Dateien entfernt.) Fügen Sie dann den Gitignore hinzu, verweisen Sie auf die Dateien / Ordner, verpflichten Sie sich erneut, die Gitignore-Datei zu Git hinzuzufügen, und kopieren Sie sie dann in die Ordner, und sie sollten ignoriert werden. NB: Es scheint, dass die Dateien aus GIT gelöscht wurden, sodass sie wahrscheinlich aus anderen Checkout / Pulls entfernt werden, wie in den obigen Lösungen erwähnt. Da Sie jedoch anfänglich Kopien davon erstellen, ist dies meiner Meinung nach kein so großes Problem. Lass es einfach den Rest des Teams wissen ...
Del

Dies ist der einfachste Weg, um falsch festgeschriebene Ordner zu entfernen.
Martlark

2
Scheint der einzige Weg zu sein, den ich sehen kann. Es ist ein massiver Fehler (nicht 'Feature') in Git, der, sobald Sie eine Datei / einen Ordner zu .gitignore hinzufügen, diese Datei von diesem Punkt an - für immer - überall nicht einfach ignoriert.
JosephK

Dies funktionierte, nachdem ich sie hinzugefügt hatte, und dann, nachdem sie
hanzolo

66

Wenn Sie git rmeine nachverfolgte Datei nicht verwenden können, weil andere Personen sie möglicherweise benötigen (Warnung, auch wenn Sie git rm --cached , wenn jemand anderes diese Änderung erhält, deren Dateien in seinem Dateisystem gelöscht werden). Diese werden häufig aufgrund von Überschreibungen von Konfigurationsdateien, Authentifizierungsdaten usw. durchgeführt. Weitere Informationen finden Sie unter https://gist.github.com/1423106 für die das Problem haben.

Zusammenfassen:

  • Lassen Sie Ihre Anwendung nach einer ignorierten Datei config-overide.ini suchen und diese über die festgeschriebene Datei config.ini verwenden (oder suchen Sie alternativ nach ~ / .config / myapp.ini oder $ MYCONFIGFILE).
  • Übernehmen Sie die Datei config-sample.ini und ignorieren Sie die Datei config.ini. Lassen Sie die Datei bei Bedarf von einem Skript oder einer ähnlichen Datei kopieren.
  • Versuchen Sie, gitattributes clean / smudge magic zu verwenden, um die Änderungen für Sie anzuwenden und zu entfernen. Verschmieren Sie beispielsweise die Konfigurationsdatei als Checkout aus einem alternativen Zweig und bereinigen Sie die Konfigurationsdatei als Checkout aus HEAD. Das ist kniffliges Zeug, ich empfehle es nicht für Anfänger.
  • Bewahren Sie die Konfigurationsdatei in einem dafür vorgesehenen Bereitstellungszweig auf, der niemals mit dem Master zusammengeführt wird. Wenn Sie bereitstellen / kompilieren / testen möchten, werden Sie zu diesem Zweig zusammengeführt und erhalten diese Datei. Dies ist im Wesentlichen der Smudge / Clean-Ansatz, außer dass Human Merge-Richtlinien und Extra-Git-Module verwendet werden.
  • Anti-Empfehlung: Verwenden Sie nicht unverändert, es wird nur in Tränen enden (weil das Lügen von sich selbst dazu führen kann, dass schlimme Dinge passieren, wie zum Beispiel, dass Ihre Veränderung für immer verloren geht).

7
git würde die Datei nicht entfernen, wenn sie zum Zeitpunkt des Löschens verschmutzt wäre. Und wenn es nicht schmutzig ist, wäre das Abrufen der Datei so einfach wie git checkout <oldref> -- <filename>- aber dann würde es ausgecheckt und ignoriert.
Amenthes

Zu Ihrer letzten Anmerkung (ungefähr --assume-unchanged): Entweder ist dies ein Frachtkult und sollte abgewiesen werden, oder Sie können erklären, warum (von dem ich überzeugt bin) und es wird nützlich.
RomainValeri

57

Verwenden Sie dies, wenn:

1. Sie möchten viele Dateien entfernen, oder

2. Sie haben Ihre Gitignore-Datei aktualisiert

Quelllink: http://www.codeblocq.com/2016/01/Untrack-files-already-added-to-git-repository-based-on-gitignore/

Angenommen, Sie haben bereits einige Dateien zu Ihrem Git-Repository hinzugefügt / festgeschrieben und fügen sie dann Ihrem .gitignore hinzu. Diese Dateien sind weiterhin in Ihrem Repository-Index vorhanden. In diesem Artikel werden wir sehen, wie man sie loswird.

Schritt 1: Übernehmen Sie alle Ihre Änderungen

Stellen Sie vor dem Fortfahren sicher, dass alle Ihre Änderungen festgeschrieben sind, einschließlich Ihrer Gitignore-Datei.

Schritt 2: Entfernen Sie alles aus dem Repository

Verwenden Sie zum Löschen Ihres Repos:

git rm -r --cached .
  • rm ist der Befehl remove
  • -r ermöglicht das rekursive Entfernen
  • –Cached entfernt nur Dateien aus dem Index. Ihre Dateien bleiben erhalten.

Der rmBefehl kann unversöhnlich sein. Wenn Sie vorher ausprobieren möchten, was es tut, fügen Sie das -noder hinzu--dry-run Flag , um die Dinge zu testen.

Schritt 3: Fügen Sie alles erneut hinzu

git add .

Schritt 4: Festschreiben

git commit -m ".gitignore fix"

Dein Repository ist sauber :)

Übertragen Sie die Änderungen auf Ihre Fernbedienung, um zu sehen, ob die Änderungen auch dort wirksam sind.


1
Es werden die Dateien nicht aus dem Remote-Repository gelöscht? Was ist, wenn ich die Dateien sowohl im lokalen Repo als auch im Remote-Repo behalten möchte, aber git sie "vergessen" möchte?
Avishay28

AFAIK dies löscht keine Dateien aus dem Verlauf, da wir keine Befehle zum Ändern des Verlaufs verwenden (korrigieren Sie mich, wenn ich falsch liege). Dies fügt nur ein neues Commit hinzu, indem in gitignore ignorierte Dateien aus git gelöscht werden. Diese Dateien werden dort in sein die historischen
Verpflichtungen

49

Ich habe dies mit Git Filter-Branch erreicht . Der genaue Befehl, den ich verwendet habe, wurde der Manpage entnommen:

WARNUNG : Dadurch wird die Datei aus Ihrem gesamten Verlauf gelöscht

git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD

Dieser Befehl erstellt den gesamten Festschreibungsverlauf neu git rmund wird vor jedem Festschreiben ausgeführt. Dadurch wird die angegebene Datei entfernt. Vergessen Sie nicht , um es wieder auf , bevor der Befehl ausgeführt wird, wie es wird verloren.


9
Dadurch werden alle Festschreibungs-IDs geändert, wodurch Zusammenführungen von Zweigen außerhalb Ihrer Kopie des Repositorys unterbrochen werden.
Bdonlan

19
WARNUNG: Dadurch wird die Datei aus Ihrem gesamten Verlauf gelöscht. Dies war jedoch das, wonach ich gesucht habe, um eine völlig unnötige und übergroße Datei (Ausgabe, die niemals festgeschrieben werden sollte) zu entfernen, die vor langer Zeit im Versionsverlauf festgeschrieben wurde.
Zebediah49

48

Was bei mir nicht funktioniert hat

(Unter Linux) wollte ich die Beiträge hier verwenden, die den ls-files --ignored --exclude-standard | xargs git rm -r --cachedAnsatz vorschlagen . (Einige) der zu entfernenden Dateien hatten jedoch einen eingebetteten Zeilenumbruch / LF / \nin ihren Namen. Keine der Lösungen:

git ls-files --ignored --exclude-standard | xargs -d"\n" git rm --cached
git ls-files --ignored --exclude-standard | sed 's/.*/"&"/' | xargs git rm -r --cached

mit dieser Situation fertig werden (Fehler über nicht gefundene Dateien erhalten).

Also biete ich an

git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached
git commit -am "Remove ignored files"

Dies verwendet das -zArgument für ls-Dateien und das -0Argument für xargs , um "böse" Zeichen in Dateinamen sicher / korrekt zu berücksichtigen.

In der Handbuchseite git-ls-files (1) heißt es:

Wenn die Option -z nicht verwendet wird, werden TAB-, LF- und Backslash-Zeichen in Pfadnamen als \ t, \ n bzw. \\ dargestellt.

Daher denke ich, dass meine Lösung benötigt wird, wenn Dateinamen eines dieser Zeichen enthalten.


1
Für mich ist das die beste Lösung. Es hat eine viel bessere Leistung als ein git add .. Es enthält auch die besten Verbesserungen aus einigen Kommentaren oben.
Nils-o-mat

Können Sie git commit -am "Remove ignored files"Ihrer Antwort anschließend thSoft hinzufügen ? Ihre Antworten zusammen haben mich durch die Dinge gebracht: j
kando

Ich verstehe den Zweck von nicht git commit -a. Für mich git rm --cachedbetrifft genau den Index, so dass keine Notwendigkeit besteht, die Dateien nach ...
Jean Paul

23
  1. Aktualisieren Sie Ihre .gitignoreDatei. Fügen Sie beispielsweise einen Ordner hinzu, in den Sie nicht verfolgen möchten .gitignore.

  2. git rm -r --cached .- Entfernen Sie alle verfolgten Dateien, einschließlich gewünschter und unerwünschter. Ihr Code ist sicher, solange Sie lokal gespeichert haben.

  3. git add .- Alle Dateien werden wieder hinzugefügt, außer denen in .gitignore.


Hutspitze an @AkiraYamamoto für den Hinweis in die richtige Richtung.


1
Wie wäre es mit Downvoted aufgrund der Tatsache, dass es nicht wirklich funktioniert, da Sie ein -r benötigen, um rm sowieso rekursiv auszuführen :) (Jemand hat nicht richtig kopiert)
Aran Mulholland

1
Warnung: Diese Technik bewirkt nicht, dass Git die Datei ignoriert, sondern dass Git die Datei löscht. Das heißt, wenn Sie diese Lösung verwenden, wird die Datei jedes Mal gelöscht, wenn jemand anderes einen Git-Pull ausführt. Es wird also nicht wirklich ignoriert. Eine Lösung für die ursprüngliche Frage finden Sie in der Lösung, in der git update-index --assume-unverändert vorgeschlagen wird.
Orrd

16

Ich denke, dass Git die Datei aufgrund ihrer Konzeption vielleicht nicht völlig vergessen kann ( Abschnitt "Schnappschüsse, keine Unterschiede"). ).

Dieses Problem fehlt beispielsweise bei der Verwendung von CVS. CVS speichert Informationen als Liste dateibasierter Änderungen. Informationen für CVS sind eine Reihe von Dateien und die Änderungen, die im Laufe der Zeit an jeder Datei vorgenommen wurden.

In Git wird jedoch jedes Mal, wenn Sie einen Commit durchführen oder den Status Ihres Projekts speichern, ein Bild davon erstellt, wie alle Ihre Dateien in diesem Moment aussehen, und ein Verweis auf diesen Snapshot gespeichert . Wenn Sie also eine Datei einmal hinzugefügt haben, ist sie in diesem Snapshot immer vorhanden.

Diese 2 Artikel waren hilfreich für mich:

git Annahme-unverändert vs Skip-Worktree und Wie man Änderungen in verfolgten Dateien mit Git ignoriert

Darauf aufbauend mache ich folgendes, wenn die Datei bereits verfolgt wird:

git update-index --skip-worktree <file>

Ab diesem Moment werden alle lokalen Änderungen in dieser Datei ignoriert und nicht mehr auf Remote übertragen. Wenn die Datei auf der Fernbedienung geändert wird, tritt ein Konflikt auf, wenn git pull. Stash wird nicht funktionieren. Um das Problem zu beheben, kopieren Sie den Dateiinhalt an einen sicheren Ort und führen Sie die folgenden Schritte aus:

git update-index --no-skip-worktree <file>
git stash
git pull 

Der Dateiinhalt wird durch den Remote-Inhalt ersetzt. Fügen Sie Ihre Änderungen vom sicheren Ort in die Datei ein und führen Sie sie erneut aus:

git update-index --skip-worktree <file>

Wenn jeder, der mit dem Projekt arbeitet, Leistung erbringt git update-index --skip-worktree <file>, sollten Probleme mit pullfehlen. Diese Lösung ist für Konfigurationsdateien in Ordnung, wenn jeder Entwickler seine eigene Projektkonfiguration hat.

Es ist nicht sehr praktisch, dies jedes Mal zu tun, wenn eine Datei auf einem Remote-Computer geändert wurde, kann sie jedoch vor dem Überschreiben durch Remote-Inhalte schützen.


16

Führen Sie die folgenden Schritte nacheinander aus, es wird Ihnen gut gehen.

1. Entfernen Sie die versehentlich hinzugefügten Dateien aus dem Verzeichnis / Speicher . Sie können den Befehl "rm -r" (für Linux) verwenden oder sie löschen, indem Sie die Verzeichnisse durchsuchen. Oder verschieben Sie sie an einen anderen Ort auf Ihrem PC. [Möglicherweise müssen Sie die IDE schließen, wenn Sie sie zum Verschieben / Entfernen ausführen möchten. ]

2. Fügen Sie die Dateien / Verzeichnisse gitignorejetzt zur Datei hinzu und speichern Sie sie.

3. Entfernen Sie sie jetzt mit diesen Befehlen aus dem Git-Cache (wenn mehr als ein Verzeichnis vorhanden ist, entfernen Sie sie nacheinander, indem Sie diesen Befehl wiederholt ausgeben).

git rm -r --cached path-to-those-files

4.Nehmen Sie jetzt ein Commit und Push , verwenden Sie diese Befehle. Dadurch werden diese Dateien von git remote entfernt und git hört auf, diese Dateien zu verfolgen .

git add .
git commit -m "removed unnecessary files from git"
git push origin

13

Die Antwort zum Kopieren / Einfügen lautet git rm --cached -r .; git add .; git status

Dieser Befehl ignoriert die Dateien, die bereits in ein Git-Repository übernommen wurden, aber jetzt haben wir sie hinzugefügt .gitignore.


9

Die Antwort von Matt Fear war meiner Meinung nach die effektivste. Das Folgende ist nur ein PowerShell-Skript für Windows-Benutzer, mit dem nur Dateien aus ihrem Git-Repo entfernt werden können, die der Ausschlussliste entsprechen.

# Get files matching exclusionsfrom .gitignore
# Excluding comments and empty lines
$ignoreFiles =  gc .gitignore | ?{$_ -notmatch  "#"} |  ?{$_ -match  "\S"} | % {
                    $ignore = "*" + $_ + "*"
                    (gci -r -i $ignore).FullName
                }
$ignoreFiles = $ignoreFiles| ?{$_ -match  "\S"}

# Remove each of these file from Git 
$ignoreFiles | % { git rm $_}

git add .

In welcher Situation entspricht diese Liste von Dateien nicht der rekursiven - zwischengespeicherten?
John Zabroski

8

Verschieben oder kopieren Sie die Datei an einen sicheren Ort, damit Sie sie nicht verlieren. Dann git rm die Datei und Commit. Die Datei wird weiterhin angezeigt, wenn Sie zu einem dieser früheren Commits oder einem anderen Zweig zurückkehren, in dem sie nicht entfernt wurde. Bei allen zukünftigen Commits wird die Datei jedoch nicht mehr angezeigt. Wenn sich die Datei im Git-Ignorier befindet, können Sie sie wieder in den Ordner verschieben, und Git wird sie nicht sehen.


34
git rm --cachedwird die Datei aus dem Index entfernen, ohne sie von der Festplatte zu löschen, so dass Sie sie nicht verschieben / kopieren müssen
bdonlan

7

Die Verwendung des git rm --cachedBefehls beantwortet nicht die ursprüngliche Frage:

Wie erzwingen Sie, git[eine Datei] vollständig zu vergessen?

Tatsächlich führt diese Lösung dazu, dass die Datei in jeder anderen Instanz des Repositorys gelöscht wird, wenn ein git pull!

Der richtige Weg, um Git zum Vergessen einer Datei zu zwingen, wird hier von GitHub dokumentiert .

Ich empfehle die Dokumentation zu lesen, aber im Grunde:

git fetch --all
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch full/path/to/file' --prune-empty --tag-name-filter cat -- --all
git push origin --force --all
git push origin --force --tags
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now

Ersetzen Sie einfach durch full/path/to/fileden vollständigen Pfad der Datei. Stellen Sie sicher, dass Sie die Datei zu Ihrem hinzugefügt haben .gitignore.

Sie müssen auch (vorübergehend) Pushs ohne schnellen Vorlauf in Ihr Repository zulassen , da Sie Ihren Git-Verlauf ändern.


5

Die BFG wurde speziell zum Entfernen unerwünschter Daten wie großer Dateien oder Kennwörter aus Git-Repos entwickelt. Sie verfügt daher über ein einfaches Flag, mit dem große historische Dateien (die nicht in Ihrem aktuellen Commit enthalten sind) entfernt werden: '--strip-blobs- größer als'

$ java -jar bfg.jar --strip-blobs-bigger-than 100M

Wenn Sie Dateien nach Namen angeben möchten, können Sie dies auch tun:

$ java -jar bfg.jar --delete-files *.mp4

Das BFG ist 10-1000x schneller als der Git-Filter-Zweig und im Allgemeinen viel einfacher zu verwenden - lesen Sie die vollständigen Gebrauchsanweisungen und Beispiele Weitere Informationen finden .

Quelle: https://confluence.atlassian.com/bitbucket/reduce-repository-size-321848262.html


5

Wenn Sie die CLI nicht verwenden möchten und unter Windows arbeiten, besteht eine sehr einfache Lösung darin, TortoiseGit zu verwenden. Das Menü enthält die Aktion "Löschen (lokal halten)", die einwandfrei funktioniert.


5

Ich mochte JonBraves Antwort, aber ich habe genug unordentliche Arbeitsverzeichnisse, die mich verpflichten - ein bisschen macht mir ein bisschen Angst, also habe ich Folgendes getan:

git config --global alias.exclude-ignoriert '! git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached && git ls-files -z --ignored --exclude-standard | xargs -0 git stage && git stage .gitignore && git commit -m "neuer gitignore und ignorierte Dateien aus dem Index entfernen" '

Brechen sie ab:

git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached 
git ls-files -z --ignored --exclude-standard | xargs -0 git stage 
git stage .gitignore 
git commit -m "new gitignore and remove ignored files from index"
  • Entfernen Sie ignorierte Dateien aus dem Index
  • Stage .gitignore und die Dateien, die Sie gerade entfernt haben
  • verpflichten

4

Dies ist im neuesten Git (v2.17.1 zum Zeitpunkt des Schreibens) kein Problem mehr .

Das .gitignoreignoriert schließlich verfolgte, aber gelöschte Dateien. Sie können dies selbst testen, indem Sie das folgende Skript ausführen. In der Schlusserklärung git statussollte "nichts zu begehen" angegeben werden.

# Create empty repo
mkdir gitignore-test
cd gitignore-test
git init

# Create a file and commit it
echo "hello" > file
git add file
git commit -m initial

# Add the file to gitignore and commit
echo "file" > .gitignore
git add .gitignore
git commit -m gitignore

# Remove the file and commit
git rm file
git commit -m "removed file"

# Reintroduce the file and check status.
# .gitignore is now respected - status reports "nothing to commit".
echo "hello" > file
git status

Ich bin froh, dass Git das jetzt macht. Das OP fragte jedoch, ob Änderungen an Dateien, die im Gitignore vorhanden sind, nicht verfolgt werden sollten. Nicht gelöschte Dateien, die noch einen Status aufweisen.
Mrturtle

2

Im Falle einer bereits begangenen DS_Store:

find . -name .DS_Store -print0 | xargs -0 git rm --ignore-unmatch

Ignoriere sie durch:

echo ".DS_Store" >> ~/.gitignore_global
echo "._.DS_Store" >> ~/.gitignore_global
echo "**/.DS_Store" >> ~/.gitignore_global
echo "**/._.DS_Store" >> ~/.gitignore_global
git config --global core.excludesfile ~/.gitignore_global

Machen Sie endlich ein Commit!


2

Speziell für die IDE-basierten Dateien verwende ich Folgendes:

Zum Beispiel die slnx.sqlite, ich habe sie gerade komplett wie folgt entfernt:

git rm {PATH_OF_THE_FILE}/slnx.sqlite -f
git commit -m "remove slnx.sqlite"

Denken Sie daran, dass in einigen dieser Dateien einige lokale Benutzereinstellungen und Einstellungen für Projekte gespeichert sind (z. B. welche Dateien Sie geöffnet haben). Jedes Mal, wenn Sie in Ihrer IDE navigieren oder Änderungen vornehmen, wird diese Datei geändert und daher ausgecheckt und angezeigt, wenn nicht festgeschriebene Änderungen vorliegen.


2

Die akzeptierte Antwort lässt Git nicht " eine Datei vergessen ..." (historisch). Git ignoriert die Datei nur in der Gegenwart / Zukunft.

Diese Methode lässt git ignorierte Dateien ( Vergangenheit / Gegenwart / Zukunft) vollständig vergessen , tut dies jedoch nicht löscht alles von Arbeitsverzeichnis (auch bei Wieder gezogen aus der Ferne).

Diese Methode erfordert die Verwendung von /.git/info/exclude(bevorzugt) ODER einer bereits vorhandenen .gitignore in allen Commits, deren Dateien ignoriert / vergessen werden müssen. 1

Alle Methoden zur Durchsetzung von Git ignorieren das Verhalten nachträglich, schreiben den Verlauf effektiv neu und haben daher erhebliche Auswirkungen auf alle öffentlichen / gemeinsam genutzten / kollaborativen Repos, die nach diesem Prozess möglicherweise abgerufen werden. 2

Allgemeiner Rat: Beginnen Sie mit einem sauberen Repo - alles festgeschrieben, nichts steht im Arbeitsverzeichnis oder Index aus, und erstellen Sie ein Backup !

Auch die Kommentare / Revisionsgeschichte von dieser Antwort ( und Revisionsgeschichte von dieser Frage ) kann nützlich sein / erleuchten.

#commit up-to-date .gitignore (if not already existing)
#this command must be run on each branch

git add .gitignore
git commit -m "Create .gitignore"

#apply standard git ignore behavior only to current index, not working directory (--cached)
#if this command returns nothing, ensure /.git/info/exclude AND/OR .gitignore exist
#this command must be run on each branch

git ls-files -z --ignored --exclude-standard | xargs -0 git rm --cached

#Commit to prevent working directory data loss!
#this commit will be automatically deleted by the --prune-empty flag in the following command
#this command must be run on each branch

git commit -m "ignored index"

#Apply standard git ignore behavior RETROACTIVELY to all commits from all branches (--all)
#This step WILL delete ignored files from working directory UNLESS they have been dereferenced from the index by the commit above
#This step will also delete any "empty" commits.  If deliberate "empty" commits should be kept, remove --prune-empty and instead run git reset HEAD^ immediately after this command

git filter-branch --tree-filter 'git ls-files -z --ignored --exclude-standard | xargs -0 git rm -f --ignore-unmatch' --prune-empty --tag-name-filter cat -- --all

#List all still-existing files that are now ignored properly
#if this command returns nothing, it's time to restore from backup and start over
#this command must be run on each branch

git ls-files --other --ignored --exclude-standard

Befolgen Sie abschließend den Rest dieses GitHub-Handbuchs (ab Schritt 6), das wichtige Warnungen / Informationen zu den folgenden Befehlen enthält .

git push origin --force --all
git push origin --force --tags
git for-each-ref --format="delete %(refname)" refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now

Andere Entwickler, die aus dem jetzt modifizierten Remote-Repo ziehen, sollten ein Backup erstellen und dann:

#fetch modified remote

git fetch --all

#"Pull" changes WITHOUT deleting newly-ignored files from working directory
#This will overwrite local tracked files with remote - ensure any local modifications are backed-up/stashed

git reset FETCH_HEAD

Fußnoten

1 Da /.git/info/excludemit den obigen Anweisungen auf alle historischen Commits angewendet werden kann, liegen Details zum Einfügen einer .gitignoreDatei in die historischen Commits, die sie benötigen , möglicherweise über den Rahmen dieser Antwort hinaus. Ich wollte, dass ein richtiger Mitarbeiter .gitignoreim Root-Commit ist, als wäre es das erste, was ich getan habe. Anderen ist es vielleicht egal, da /.git/info/excludesie das Gleiche erreichen können, unabhängig davon, wo sie .gitignorein der Festschreibungshistorie vorhanden sind, und das klare Umschreiben der Historie ist ein sehr heikles Thema, selbst wenn sie sich der Auswirkungen bewusst sind .

FWIW können potenzielle Methoden enthalten git rebaseoder eine git filter-branch, die ein externes .gitignore in jedes Commit kopiert , wie die Antworten auf diese Frage

2 Das Erzwingen des nachträglichen Ignorierens von Git durch Festschreiben der Ergebnisse eines eigenständigen git rm --cachedBefehls kann dazu führen, dass neu ignorierte Dateien in zukünftigen Abrufen von der erzwungenen Fernbedienung gelöscht werden . Das --prune-emptyFlag im folgenden git filter-branchBefehl vermeidet dieses Problem, indem das vorherige Nur-Index-Commit "Alle ignorierten Dateien löschen" automatisch entfernt wird. Durch das Umschreiben des Git-Verlaufs werden auch Commit-Hashes geändert, was bei zukünftigen Abrufen von öffentlichen / gemeinsam genutzten / kollaborativen Repos zu Chaos führen wird . Bitte verstehen Sie die Auswirkungen vollständig, bevor Sie dies für ein solches Repo tun. In diesem GitHub-Handbuch wird Folgendes angegeben:

Weisen Sie Ihre Mitarbeiter an , alle Zweige, die sie aus Ihrem alten (fehlerhaften) Repository-Verlauf erstellt haben, neu zu gründen und nicht zusammenzuführen. Ein Zusammenführungs-Commit könnte einen Teil oder die gesamte verdorbene Geschichte wieder einführen, die Sie gerade mit dem Löschen begonnen haben.

Alternative Lösungen, die das Remote-Repo nicht beeinflussen, sind git update-index --assume-unchanged </path/file>oder git update-index --skip-worktree <file>, Beispiele hierfür finden Sie hier .


0

Wenn jemand unter Windows Schwierigkeiten hat und Sie den gesamten Ordner ignorieren möchten, wählen Sie "cd", um den "Ordner" zu erhalten, und führen Sie "Git Bash Here" aus.

git ls-files -z | xargs -0 git update-index --assume-unchanged

0

In meinem Fall hatte ich mehrere .lock-Dateien in mehreren Verzeichnissen, die ich entfernen musste. Ich habe Folgendes ausgeführt und es hat funktioniert, ohne in jedes Verzeichnis gehen zu müssen, um sie zu entfernen:

git rm -r --cached **/*.lock

Dies ging in jeden Ordner unter dem Stammverzeichnis, in dem ich mich befand, und schloss alle Dateien aus, die dem Muster entsprachen.

Hoffe das hilft anderen!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.