8100 Stimmen

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

Es gibt eine Datei, die von Git verfolgt wurde, aber jetzt ist die Datei in der .gitignore Liste.

Diese Datei taucht jedoch weiterhin in git status nachdem es bearbeitet wurde. Wie kann man Git zwingen, es komplett zu vergessen?

14voto

Skeets Punkte 3701

Die Verwendung des git rm --cached Befehl keine Antwort auf die ursprüngliche Frage:

Wie zwingt man git [eine Datei] komplett zu vergessen?

Diese Lösung führt nämlich dazu, dass die Datei gelöscht in jeder anderen Instanz des Repositorys bei der Ausführung einer git pull !

Die korrekte Vorgehensweise, um Git zu zwingen, eine Datei zu vergessen, ist bei GitHub dokumentiert aquí .

Ich empfehle, die Dokumentation zu lesen, aber im Grunde genommen:

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

Einfach ersetzen full/path/to/file mit dem vollständigen Pfad der Datei. Stellen Sie sicher, dass Sie die Datei zu Ihrem .gitignore Datei.

Außerdem müssen Sie (vorübergehend) nicht-schnelle Weiterleitungen in Ihr Repository erlauben da Sie Ihren Git-Verlauf ändern.

13voto

Apreche Punkte 26583

Verschieben oder kopieren Sie die Datei an einen sicheren Ort, damit sie nicht verloren geht. Dann "git rm" die Datei und Commit.

Die Datei wird immer noch angezeigt, wenn Sie zu einem dieser früheren Commits oder einem anderen Zweig zurückkehren, aus dem sie nicht entfernt wurde. In allen zukünftigen Übertragungen werden Sie die Datei jedoch nicht mehr sehen. Wenn sich die Datei im Git-Ignore befindet, können Sie sie zurück in den Ordner verschieben, und Git wird sie nicht mehr sehen.

12voto

Ameer Deen Punkte 668

El Antwort von Matt Frear war IMHO am wirksamsten. Im Folgenden finden Sie ein PowerShell-Skript für Windows-Nutzer, mit dem nur Dateien aus dem Git-Repository entfernt werden, 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 .

11voto

Good Pen Punkte 391

git rm --cached -r <YOUR_files_or_folders>

--cached | nur Dateien aus dem Index entfernen

9voto

goofology Punkte 767

Die akzeptierte Antwort macht nicht "Git "vergessen" über eine Akte..." (historisch). Es macht nur Git ignorieren. die Datei in der Gegenwart/Zukunft.

Diese Methode macht Git völlig vergessen ignorierte Dateien ( Vergangenheit /Gegenwart/Zukunft), aber es ist no alles aus dem Arbeitsverzeichnis zu löschen (auch wenn es aus der Ferne neu geholt wird).

Diese Methode erfordert die Verwendung der Datei /.git/info/exclude (bevorzugt) ou a bereits existierende .gitignore en todo die Commits, die Dateien haben, die ignoriert/vergessen werden sollen. 1

Alle Methoden zur nachträglichen Durchsetzung des Git-Ignorierverhaltens schreiben die Geschichte um und haben daher erhebliche Auswirkungen für alle öffentlichen/gemeinsamen/kollaborativen Repositories, die nach diesem Prozess gezogen werden könnten. 2

Allgemeine Hinweise: mit einem sauberen Repository beginnen - alles übertragen, nichts im Arbeitsverzeichnis oder im Index ausstehend, und eine Sicherungskopie erstellen !

Auch die Kommentare/ Revisionsgeschichte de diese Antwort ( und Revisionsgeschichte de diese Frage ) kann nützlich/erhellend sein.

#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 the current index, not the 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

Folgen Sie schließlich dem Rest dieser GitHub-Anleitung (beginnend bei Schritt 6) die 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 von dem nun geänderten entfernten Repository beziehen, 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 Denn /.git/info/exclude kann mit den obigen Anweisungen auf alle historischen Übertragungen angewandt werden, vielleicht auch auf Details zum Erhalt einer .gitignore Datei in die historische(n) Verpflichtung(en), die dies erfordern, übersteigt den Rahmen dieser Antwort. Ich wollte eine richtige .gitignore Datei im Root-Commit, als ob es das erste wäre, was ich getan habe. Andere mag das nicht interessieren, da /.git/info/exclude kann dasselbe bewirken, unabhängig davon, wo die .gitignore Datei in der Commit-Historie existiert, und das Umschreiben der Historie ist eindeutig eine sehr heikles Thema, selbst wenn man sich der Verzweigungen .

FWIW, mögliche Methoden können sein git rebase oder eine git filter-branch die eine Kopie eines extern .gitignore in jeder Übergabe, wie die Antworten auf diese Frage .

2 Erzwingen des Git-Ignorierverhaltens im Nachhinein durch Übertragen der Ergebnisse einer eigenständigen git rm --cached kann zu einer neu ignorierten Datei führen Löschung in Zukunft von der kraftbetriebenen Fernbedienung abziehen. Die --prune-empty Flagge im Folgenden git filter-branch Befehl vermeidet dieses Problem, indem er automatisch den vorherigen "Alle ignorierten Dateien löschen"-Commit entfernt, der nur den Index betrifft. Das Umschreiben der Git-Historie ändert auch die Commit-Hashes, was dazu führt, dass Verheerungen anrichten bei künftigen Abrufen aus öffentlichen/gemeinsamen/kollaborativen Repositories. Bitte verstehen Sie die Verzweigungen bevor Sie dies mit einem solchen Repository tun. Diese GitHub-Anleitung spezifiziert das Folgende:

Sagen Sie Ihren Mitarbeitern, dass sie neu gründen , no zusammenführen, alle Zweige, die sie aus Ihrer alten (verdorbenen) Repository-Historie erstellt haben. Ein einziger Merge-Commit könnte einen Teil oder die gesamte verunreinigte Historie wieder einführen, die Sie gerade mühsam bereinigt haben.

Alternative Lösungen, die nicht das entfernte Repository betreffen, sind git update-index --assume-unchanged </path/file> o git update-index --skip-worktree <file> Beispiele dafür finden Sie unter aquí .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X