So entfernen Sie eine große Anzahl von Dateien, ohne den Inhalt zu löschen

454

Ich habe versehentlich viele temporäre Dateien mit hinzugefügt git add -A

Ich habe es geschafft, die Dateien mit den folgenden Befehlen zu entfernen und den schmutzigen Index zu entfernen.

git ls-files -z | xargs -0 rm -f
git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached

Die obigen Befehle sind in der Liste aufgeführt git help rm. Leider wurden meine Dateien auch bei der Ausführung gelöscht, obwohl ich die Cache-Option angegeben hatte. Wie kann ich den Index löschen, ohne den Inhalt zu verlieren?

Es wäre auch hilfreich, wenn jemand erklären könnte, wie dieser Rohrbetrieb funktioniert.

Sarat
quelle
8
rm -fist kein git-Befehl und hat keine --cachedOption. Ihre lokalen Dateien wurden vor Ihrer Ausführung gelöscht, daher können Sie git rmmeiner Meinung nach nicht git rmfür irgendetwas verantwortlich gemacht werden.
CB Bailey
8
@sarat, beachten Sie bitte die richtige Antwort auf die sehr upvoted Antwort von wechselndem Ian Maddox , da das git reset --hardist nicht die richtige Antwort und wird in der Tat den Inhalt löschen. Dies wird die Benutzer verwirren - genau wie ich.
Marco Pashkov
2
@ Sarat wie Marco sagt, mach weiter. Diese Seite bekommt viel Verkehr.
Ross
@ MarcoPashkov & Ross danke Jungs. Erledigt.
Sarat

Antworten:

986

git reset

Wenn Sie nur einen übereifrigen "git add" -Lauf rückgängig machen möchten:

git reset

Ihre Änderungen werden nicht bereitgestellt und können nach Belieben erneut hinzugefügt werden.


NICHT LAUFEN git reset --hard.

Dadurch werden nicht nur Ihre hinzugefügten Dateien entfernt, sondern alle Änderungen, die Sie in Ihrem Arbeitsverzeichnis vorgenommen haben, werden zurückgesetzt. Wenn Sie neue Dateien im Arbeitsverzeichnis erstellt haben, werden diese jedoch nicht gelöscht.

Ian Maddox
quelle
15
Ich schulde dir ein Pint Ian
DasBooten
1
Oft finde ich ich ausführen müssen git checkout -- *auch
Den-Jason
1
Sie haben viel Mühe gespart. Danke Mann
RajnikantDixit
35

Wenn Sie ein makelloses Repo haben (oder HEAD nicht eingestellt ist) [1], können Sie dies einfach tun

rm .git/index

Natürlich wird dies Sie benötigen die Dateien erneut hinzufügen , dass Sie haben hinzugefügt werden soll.


[1] Beachten Sie (wie in den Kommentaren erläutert), dass dies normalerweise nur dann geschieht, wenn das Repo brandneu ("makellos") ist oder wenn keine Commits vorgenommen wurden. Technisch gesehen immer dann, wenn es keine Kasse oder keinen Arbeitsbaum gibt.

Nur um es klarer zu machen :)

sehe sehen
quelle
Ja, es ist eher so, als würde man den erstellten Index selbst löschen. Gut ist, dass ich git nicht neu initialisieren muss. Vielen Dank!
Sarat
Sind Sie sicher, dass es sich um eine sichere Operation handelt? Ich habe dies gerade getan (tatsächlich den Index aus dem Weg geräumt) und alle anderen Dateien zum Löschen bereitgestellt.
Inger
@inger "Wenn Sie ein makelloses Repo haben". Das hattest du eindeutig nicht.
sehe
Eigentlich habe ich mich gefragt, was du mit "makellosem Repo" meinst (ich habe auch kein Glück mit Google). Also hast du eigentlich ein leeres Repo gemeint?
Inger
1
@inger zustimmen. Ich musste davon ausgehen, dass das OP genau diese Situation hatte - er spezifiziert es nicht, aber seine Beschreibung lässt die Möglichkeit. Wie auch immer, ich teile nur Informationen und kann die Abstimmung nicht beeinflussen :(. Habe dem Antworttext ein warnendes Wort hinzugefügt, falls es anderen in Zukunft hilft.
sehe
15

Verwenden Sie git reset HEADdiese Option, um den Index zurückzusetzen, ohne Dateien zu entfernen. (Wenn Sie nur eine bestimmte Datei im Index zurücksetzen möchten, können Sie dies git reset HEAD -- /path/to/filetun.)

Der Rohrbetreiber nimmt in einer Schale stdoutden Prozess auf der linken Seite und leitet ihn stdinan den Prozess auf der rechten Seite weiter. Es ist im Wesentlichen das Äquivalent von:

$ proc1 > proc1.out
$ proc2 < proc1.out
$ rm proc1.out

Stattdessen kann $ proc1 | proc2der zweite Prozess Daten abrufen, bevor der erste die Ausgabe beendet hat, und es ist keine tatsächliche Datei beteiligt.

Bernstein
quelle
aber wie man es mit mehreren Dateien verwendet. Ich habe diese Dateien noch nie festgeschrieben.
Sarat
3
Geben Sie einfach ein, git reset HEADohne etwas anderes anzugeben, und der gesamte Index wird zurückgesetzt. Sie können dann nur die gewünschten Dateien erneut hinzufügen.
Amber
Ich habe den folgenden Fehler erhalten. Ich habe diese Gegenstände noch nie begangen. $ git reset HEAD fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree. Use '--' to separate paths from revisions
Sarat
1
Versuchen Sie es einfach git resetdann, ohne die HEAD.
Amber
Ich habe bereits versucht, dass ich im folgenden Fehler gelandet bin. $ git reset fatal: Failed to resolve 'HEAD' as a valid ref.
Sarat
9
git stash && git stash pop
Bijan
quelle
2
Ich würde 'git stash && git stash pop' machen, damit der Stash auch gelöscht wird. 'apply' würde den Stash in der Stash-Liste belassen.
Chitti
8

Wenn HEAD nicht festgelegt ist (dh Sie haben noch keine Commits, möchten aber nicht einfach wegblasen, .gitweil Sie bereits eine andere Repo-Konfiguration eingerichtet haben, die Sie beibehalten möchten), können Sie dies auch tun

git rm -rf --cached .

alles zu inszenieren. Dies ist praktisch das Gleiche wie die Lösung von sehe, vermeidet jedoch das Durcheinander mit Git-Interna.

jjlin
quelle
Dies weist Git an, alles im zwischengespeicherten Bereich zu löschen.
Visionary Software Solutions
1
Der Cache wird auch als Staging-Bereich bezeichnet, daher bin ich mir nicht sicher, worauf Sie hinaus wollen.
JJlin
Von sehe ist rm .git / index sehr gefährlich - lesen Sie unbedingt den HINWEIS, den er über ein brandneues Repo hat! Dies ist für die anderen 99,999% der Zeit viel sicherer. Ich habe nicht sorgfältig gelesen und musste meine Arbeitskopie wegblasen und neu klonen, nachdem ich rm .git / index für meine Arbeitskopie ausgeführt hatte.
Phpguru
Verwenden Sie diesen Befehl NICHT! Dadurch wird ALLES Projekt in den Status "Nicht verfolgt" versetzt (einschließlich solcher, die nicht bereitgestellt wurden). Dies ist keine Lösung für die ursprüngliche Frage. Die richtige Lösung mit dem Befehl 'git rm' besteht darin, NUR die Dateien anzugeben, die nicht bereitgestellt werden sollen: git rm -rf --cached <Dateien, die Sie entfernen möchten>.
Monte Creasor
Sie sollten diesen Befehl nur verwenden, wenn Sie ein neues Repo ohne Commits haben (dies bedeutet "HEAD is not set"), aber Sie möchten nicht einfach wegblasen, .gitweil Sie eine andere Repo-Konfiguration eingerichtet haben behalten wollen. Ich habe bearbeitet, um dies zu verdeutlichen.
jjlin
5

Warnung: Verwenden Sie den folgenden Befehl nur, wenn Sie nicht festgeschriebene Arbeit verlieren möchten!

Die Verwendung git resetwurde erklärt, aber Sie haben auch um eine Erklärung der Pipe-Befehle gebeten.

git ls-files -z | xargs -0 rm -f
git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached

Der Befehl git ls-fileslistet alle Dateien auf, die git kennt. Die Option -zlegt ihnen ein bestimmtes Format auf, das von ihnen erwartete Format xargs -0, das sie dann aufruft. Dies rm -fbedeutet, dass sie entfernt werden müssen, ohne auf Ihre Zustimmung zu prüfen.

Mit anderen Worten: "Listen Sie alle Dateien auf, die git kennt, und entfernen Sie Ihre lokale Kopie".

Dann kommen wir zu git diff, was Änderungen zwischen verschiedenen Versionen von Elementen zeigt, über die Git Bescheid weiß. Dies können Änderungen zwischen verschiedenen Bäumen, Unterschiede zwischen lokalen Kopien und Remote-Kopien usw. sein.
Wie hier verwendet, werden die nicht bereitgestellten Änderungen angezeigt. die Dateien, die Sie geändert, aber noch nicht festgeschrieben haben. Die Option --name-onlybedeutet, dass Sie nur die (vollständigen) Dateinamen möchten und --diff-filter=Ddass Sie nur an gelöschten Dateien interessiert sind. (Hey, haben wir nicht einfach ein paar Sachen gelöscht?) Dies wird dann in das xargs -0zuvor gesehene geleitet, was sie aufruft git rm --cached, was bedeutet, dass sie aus dem Cache entfernt werden, während der Arbeitsbaum in Ruhe gelassen werden sollte - außer das Sie haben gerade alle Dateien aus Ihrem Arbeitsbaum entfernt. Jetzt werden sie auch aus Ihrem Index entfernt.

Mit anderen Worten, alle bereitgestellten oder nicht bereitgestellten Änderungen sind weg und Ihr Arbeitsbaum ist leer. Weinen Sie, checken Sie Ihre Dateien frisch vom Ursprung oder von der Fernbedienung aus und wiederholen Sie Ihre Arbeit. Verfluche den Sadisten, der diese höllischen Zeilen geschrieben hat; Ich habe überhaupt keine Ahnung, warum jemand dies tun möchte.


TL; DR: Sie haben einfach alles abgespritzt; von vorne beginnen und git resetvon nun an verwenden.

SQB
quelle
2

Ich befürchte, dass die erste dieser Befehlszeilen alle Dateien, die sich im Staging-Bereich von git befinden, bedingungslos aus der Arbeitskopie gelöscht hat. Die zweite hat alle Dateien aufgehoben, die verfolgt wurden, aber jetzt gelöscht wurden. Leider bedeutet dies, dass Sie alle nicht festgeschriebenen Änderungen an diesen Dateien verloren haben.

Wenn Sie Ihre Arbeitskopie und Ihren Index wieder auf den Stand beim letzten Festschreiben bringen möchten , können Sie den folgenden Befehl ( vorsichtig ) verwenden:

git reset --hard

Ich sage "vorsichtig", da git reset --hard nicht festgeschriebene Änderungen in Ihrer Arbeitskopie und Ihrem Index verwischt werden. In dieser Situation klingt es jedoch so, als ob Sie bei Ihrem letzten Commit nur in den Status zurückkehren möchten, und die nicht festgeschriebenen Änderungen sind trotzdem verloren gegangen.

Update: Aus Ihren Kommentaren zu Bernsteins Antwort geht hervor, dass Sie noch keine Commits erstellt haben (da HEAD nicht aufgelöst werden kann). Dies wird also leider nicht helfen.

Wie diese Pipes funktionieren: git ls-files -zund git diff --name-only --diff-filter=D -zbeide geben eine Liste von Dateinamen aus, die durch das Byte getrennt sind 0. (Dies ist nützlich, da im Gegensatz zu Zeilenumbrüchen 0Bytes in Dateinamen auf Unix-ähnlichen Systemen garantiert nicht vorkommen.) Das Programm erstellt xargsBefehlszeilen im Wesentlichen aus seiner Standardeingabe, indem standardmäßig Zeilen aus der Standardeingabe übernommen und am Ende hinzugefügt werden der Kommandozeile. Die -0Option besagt, dass die Standardeingabe durch 0Bytes getrennt erwartet wird . xargsMöglicherweise wird der Befehl mehrmals aufgerufen, um alle Parameter aus der Standardeingabe zu verbrauchen und sicherzustellen, dass die Befehlszeile niemals zu lang wird.

Als einfaches Beispiel, wenn Sie eine Datei test.txtmit dem folgenden Inhalt aufgerufen haben :

hello
goodbye
hello again

... dann xargs echo whatever < test.txtruft der Befehl den Befehl auf:

echo whatever hello goodbye hello again
Mark Longair
quelle
Ich habe nie irgendwelche Verpflichtungen eingegangen, daher heißt es, dass HEAD nicht aufgelöst werden kann. Was wir in solchen Situationen tun. Vielen Dank für die ausführliche Erklärung von Pipe.
Sarat
8
Wenn Sie gerade Ihr Git-Ignorieren geändert haben und Git-Add hinzugefügt haben, um viele Dateien einzuschließen, führen Sie KEIN Git-Reset aus, um sie zu entfernen. SIE WERDEN GELÖSCHT !!
Ajoy
5
Uwaaahh !! Vielleicht müssen Sie das Wort "sorgfältig" hervorheben . Ich habe gerade diese drei Wörter "git reset --hard" gesehen und alle meine nicht bereitgestellten Dateien sind ... fufff !! Weg!!!!!
Vineeth Chitteti
1

Wenn Sie alle Änderungen aufheben möchten, verwenden Sie den folgenden Befehl:

git reset --soft HEAD

Wenn Sie Änderungen entfernen und aus dem Arbeitsverzeichnis zurücksetzen möchten,

git reset --hard HEAD
027
quelle