Как отключить большое количество файлов без удаления содержимого

Я случайно добавил много временных файлов, используя 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. Но, к сожалению, мои файлы также были удалены при выполнении, хотя я дал параметр кеша. Как я могу очистить индекс без потери содержимого?

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

Ответ 1

git reset

Если все, что вы хотите, - это отменить чрезмерный "git add" run:

git reset

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


НЕ git reset --hard.

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

Ответ 2

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

rm .git/index

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


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

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

Ответ 3

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

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

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

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

Ответ 4

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

git rm -rf --cached .

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

Ответ 5

git stash && git stash pop

Ответ 6

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

Использование 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 означает, что вы хотите только имена файлов (full), а --diff-filter=D означает, что вы заинтересованы только в удаленных файлах. (Эй, разве мы не просто удалили кучу вещей?) Затем он передается в xargs -0, который мы видели ранее, который вызывает git rm --cached на них, что означает, что они удаляются из кеша, в то время как рабочее дерево должно быть оставлено в покое - за исключением того, что вы только что удалили все файлы из своего рабочее дерево. Теперь они также удалены из вашего индекса.

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


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

Ответ 7

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

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

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

Ответ 8

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

git reset --soft HEAD

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

git reset --hard HEAD