Как удалить большое количество файлов без удаления контента - PullRequest
412 голосов
/ 18 августа 2011

Я случайно добавил много временных файлов, используя git add -A

Мне удалось разархивировать файлы с помощью следующих команд и удалить грязный индекс.

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

Вышеуказанные команды перечислены в git help rm.Но, к сожалению, мои файлы также были удалены при исполнении, хотя я и выбрал опцию кэширования.Как я могу очистить индекс без потери содержимого?

Также было бы полезно, если бы кто-то мог объяснить, как работает эта конвейерная операция.

Ответы [ 8 ]

899 голосов
/ 03 июля 2014

git reset

Если все, что вам нужно, это отменить чрезмерно усердный прогон "git add":

git reset

Ваши изменения будут без изменений и готовы для повторного добавления какпожалуйста.


НЕ ЗАПУСКАТЬ git reset --hard.

Это не только отключит добавленные вами файлы, но и отменит любые изменения, внесенные вами в работу.каталог.Если вы создали какие-либо новые файлы в рабочем каталоге, он не будет удалять их.

34 голосов
/ 18 августа 2011

Если у вас нетронутый репо (или HEAD не установлен) [1] вы можете просто

rm .git/index

Конечно, это потребует от вас повторного добавления файлов, которые вы действительно хотели добавить.


[1] Обратите внимание (как объяснено в комментариях), это обычно происходит только тогда, когда репо является совершенно новым («нетронутым») или если не было сделано никаких коммитов. Более технически, когда нет проверки или рабочего дерева.

Просто сделав это более понятным:)

14 голосов
/ 18 августа 2011

Используйте git reset HEAD для сброса индекса без удаления файлов. (Если вы хотите сбросить только определенный файл в индексе, вы можете использовать git reset HEAD -- /path/to/file для этого.)

Оператор канала в оболочке принимает stdout процесса слева и передает его как stdin процессу справа. Это по существу эквивалент:

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

но вместо этого $ proc1 | proc2, второй процесс может начать получать данные до того, как первый завершит их вывод, и фактический файл не используется.

8 голосов
/ 23 января 2013

Если HEAD не установлен, вы также можете сделать

git rm -rf --cached .

чтобы все отключить. По сути, это то же самое, что и решение Sehe, но позволяет избежать взлома с помощью Git.

8 голосов
/ 10 декабря 2012
git stash && git stash pop
5 голосов
/ 15 августа 2016

Предупреждение: не используйте следующую команду, если не хотите потерять незавершенную работу!

Использование git reset было объяснено, но вы также запросили объяснение переданных команд, поэтому здесь идет речь:

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

Команда git ls-files выводит список всех файлов, о которых знает git. Опция -z налагает на них определенный формат, ожидаемый xargs -0 формат, который затем вызывает для них rm -f, что означает удаление их без проверки вашего одобрения.

Другими словами, «перечислите все файлы, которые знает git и удалите вашу локальную копию».

Затем мы переходим к git diff, который показывает изменения между различными версиями элементов, о которых знает git. Это могут быть изменения между разными деревьями, различия между локальными и удаленными копиями и т. Д.
Как здесь используется, он показывает неустановленные изменения; файлы, которые вы изменили, но еще не зафиксировали. Опция --name-only означает, что вам нужны только (полные) имена файлов, а --diff-filter=D означает, что вы заинтересованы только в удаленных файлах. (Эй, разве мы не удалили кучу вещей?) Затем он попадает в xargs -0, который мы видели ранее, что вызывает git rm --cached для них, что означает, что они удаляются из кэша, а рабочее дерево должно быть оставлено в покое - за исключением того, что вы только что удалили все файлы из вашего рабочее дерево. Теперь они также удалены из вашего индекса.

Другими словами, все изменения, поэтапные или неустановленные, пропали, и ваше рабочее дерево пусто. Плачите, проверяйте свои файлы, свежие из источника или удаленного, и переделайте свою работу. Прокляни садиста, который написал эти адские строки; Я понятия не имею, почему кто-то хотел бы сделать это.


TL; DR: вы просто все надули; начните сначала и используйте git reset с этого момента.

2 голосов
/ 18 августа 2011

Боюсь, что первая из этих командных строк безоговорочно удалила из рабочей копии все файлы, находящиеся в промежуточной области git.Второй unstaged все файлы, которые были отслежены, но теперь были удалены.К сожалению, это означает, что вы потеряете все незафиксированные изменения в этих файлах.

Если вы хотите получить свою рабочую копию и индексировать обратно, как они были при последнем коммите , вы можете ( осторожно ) используйте следующую команду:

git reset --hard

Я говорю «осторожно», поскольку git reset --hard уничтожит незафиксированные изменения в вашей рабочей копии и индексе.Однако в этой ситуации это звучит так, как будто вы просто хотите вернуться к состоянию при последнем коммите, а незафиксированные изменения все равно были потеряны.

Обновление: это звучит из ваших комментариев к Амберответьте, что вы еще не создали никаких коммитов (поскольку HEAD не может быть разрешен), так что, боюсь, это не поможет.

Что касается работы этих каналов: git ls-files -z иgit diff --name-only --diff-filter=D -z оба выводят список имен файлов, разделенных байтом 0.(Это полезно, поскольку, в отличие от новых строк, гарантировано, что 0 байтов не встречается в именах файлов в Unix-подобных системах.) Программа xargs по существу строит командные строки из своего стандартного ввода, по умолчанию беря строки из стандартного вводаи добавив их в конец командной строки.Опция -0 говорит, что стандартный ввод вводится через 0 байтов.xargs может вызвать команду несколько раз, чтобы использовать все параметры из стандартного ввода, убедившись, что командная строка никогда не становится слишком длинной.

В качестве простого примера, если у вас есть файл с именем test.txtсо следующим содержанием:

hello
goodbye
hello again

... тогда команда xargs echo whatever < test.txt вызовет команду:

echo whatever hello goodbye hello again
1 голос
/ 04 февраля 2016

Если вы хотите отменить удаление всех изменений, используйте приведенную ниже команду,

git reset --soft HEAD

В случае, если вы хотите отменить удаление изменений и отменить их из рабочего каталога,

git reset --hard HEAD
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...