Как вернуть «git rm -r.»?

378

Я случайно сказал git rm -r .. Как мне восстановиться после этого?

Я не совершал.

Я думаю, что все файлы были помечены для удаления, а также были физически удалены из моей локальной проверки.

РЕДАКТИРОВАТЬ: Я мог (если бы я знал команду) вернуться к последнему коммиту. Но было бы намного лучше, если бы я мог просто отменить git rm -r .. Потому что я не совсем уверен, что я сделал после последнего коммита и до git rm -r ..

user89021
источник
3
Для этого конкретного вопроса сброс --hard является хорошим решением ... он уже указан, поэтому я просто упомяну в этом комментарии, что вы можете проверить документацию для git-reflog.
Уильям Перселл
8
Обратите внимание , что , потому что вы не снабжали , -fчтобы git rmмерзавец не будут удалены все файлы , которые инсценировали или unstaged правки поэтому git reset; git checkout .должны восстановить все.
CB Bailey
Просто остерегайтесь - git checkout. уничтожит все неустановленные изменения.
PeterB
1
Я просто сделал что-то вроде этого, и я не понимаю, почему мои локальные файлы были удалены (и, как и OP, я еще не зафиксировал.)
Xonatron
С Git 2.23+ (август 2019), вы восстановите файлы git restore: git restore -s@ -SW -- .. Смотрите мой ответ ниже .
VonC

Ответы:

468
git reset HEAD

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

git reset --hard HEAD

должен принудительно сбросить все до вашего последнего коммита. Если у вас есть незафиксированные изменения, но первая команда не работает, сохраните незафиксированные изменения с помощью git stash:

git stash
git reset --hard HEAD
git stash pop
Брайан Кэмпбелл
источник
22
Обратите внимание, что git reset --hard HEADуничтожает любые полезные изменения, которые вы сделали в родительских каталогах текущего рабочего каталога.
Алекс Браун
10
@Mild: Я все еще ношу холодный пот!
hoipolloi
6
Я не отказался от голосования, но я просто попытался спрятать, перезагрузить, потерял все мои недавние изменения. Может быть, я неправильно понял ответ.
Грег М. Крсак
1
Это редко работает для меня, и я так рад, что работаю в папке Dropbox. Плохая форма, но спасает меня каждый раз ...
Nuby
3
Когда я делал git stash pop, он просто снова удалял файлы, конечно, потому что он скрывает тот факт, что я (случайно) удалил некоторые файлы. Этот ответ не работает, если у вас есть незафиксированные изменения, которые вы хотите сохранить.
Судо
252

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

git checkout HEAD path/to/file path/to/another_file

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

Хайме Беллмайер
источник
6
Это помогло, потому что у меня были другие незафиксированные изменения.
Дан
4
Этот ответ помогает тем из нас, кто наткнулся на этот вопрос, пытаясь вернуть git rmрекурсивную единицу, а не целую git rm -r. Для полного рекурсивного удаления другие решения могут быть лучше, в зависимости от количества удаленных файлов.
Tresf
Вы, мой человек, заслуживаете награду.
Саламит
Если бы я мог, я бы нажал на это 100 раз!
Вагнер Брага
57

Чтобы восстановить отдельные файлы или папки, можно использовать следующие

git reset -- path/to/file
git checkout -- path/to/file

Сначала будут созданы записи индекса path/to/fileи файл будет таким же, каким он был при последнем коммите, т.е.HEAD .

Подсказка: можно передать хеш коммита обеим командам, чтобы воссоздать файлы из старого коммита. Смотрите git reset --helpи git checkout --helpдля деталей.

Арне Л.
источник
Лучший ответ. Простое хирургическое «отмена» одной git rmоперации без уничтожения других незафиксированных изменений.
Wberry
Выручил меня! лучший ответ.
Акрам
28

Обновить:

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

git reset HEAD . # This undoes the index changes
git checkout .   # This checks out files in this and child directories from the HEAD

Это должно делать то, что вы хотите. Это не влияет на родительские папки вашего извлеченного кода или индекса.


Старый ответ, которого не было:

reset HEAD

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

после этого вам нужно повторить любые git addкоманды, которые вы поставили в очередь.

Алекс Браун
источник
1
извините, я всегда настраиваюсь git alias.co="checkout"так, чтобы git coоформить заказ.
Алекс Браун
25

Если у вас не получится ничего из вышеперечисленного, вы можете получить данные, используя предложенное здесь: http://www.spinics.net/lists/git/msg62499.html

git prune -n
git cat-file -p <blob #>
Skippy VonDrake
источник
4 года спустя, еще спасатель!
ThivingSix
Я написал программу на С ++ для объединения результатов (в моем репо было около 100 объектов, что сделало это необходимым). Просто скомпилируйте и запустите, затем перейдите в локальный каталог вашего git repo. raw.githubusercontent.com/bluuman/git-recover-files/master/…
Джеймс
15

отменить мерзавца

git rm file             # delete file & update index
git checkout HEAD file  # restore file & index from HEAD

отменить мерзавца

git rm -r dir          # delete tracked files in dir & update index
git checkout HEAD dir  # restore file & index from HEAD

отменить мерзавца rm -rf

git rm -r dir          # delete tracked files & delete uncommitted changes
not possible           # `uncommitted changes` can not be restored.

Uncommitted changesвключает в себя not staged changes, staged changes but not committed.

песня Сюй
источник
Конечно, ничто не может отменить git rm -rf, поскольку это может также удалить неотслеживаемые или промежуточные (только) файлы.
августа
git rm -rf fileи git rm -rf dirне будет удалять неотслеживаемые файлы.
песня Сюй
10

Если вы зафиксировали и отправили изменения, вы можете сделать это, чтобы получить файл обратно

// Replace 2 with the # of commits back before the file was deleted.
git checkout HEAD~2 path/to/file
Кори Дэниелсон
источник
Это сработало для «Изменений, которые нужно зафиксировать:», когда файл был удален из старого git cherry-pick, который мне все еще был нужен. Я попытался выполнить git reset HEAD ~ <number> <file>, который не сработал.
mushcraft
7

Уже есть несколько хороших ответов, но я мог бы предложить малоиспользуемый синтаксис, который не только прекрасно работает, но и очень явно выражает то, что вы хотите (поэтому не страшно и не таинственно)

git checkout <branch>@{"20 minutes ago"} <filename>
mehtunguh
источник
3

Получить список коммитов

git log  --oneline

Например, стабильный коммит имеет хэш: 45ff319c360cd7bd5442c0fbbe14202d20ccdf81

git reset --hard 45ff319c360cd7bd5442c0fbbe14202d20ccdf81
git push -ff origin master
До Нху Вы
источник
1

У меня была идентичная ситуация. В моем случае решение было:

git checkout -- .
Артур
источник
0

В Git 2.23+ (август 2019 г.) правильная команда для восстановления файлов (и индекса) должна использоваться ... git restore(нет reset --hardили запутанная git checkoutкоманда )

Это:

git restore -s=HEAD --staged --worktree -- .

Или его сокращенная форма:

git restore -s@ -SW -- .
VonC
источник
-1

У меня была точно такая же проблема: чистила папки, переставляла и перемещала файлы. Я вошел: Git RM .и нажмите ввод; и затем почувствовал, что мои кишки немного ослабли. К счастью, я не набрал git commit -m "" сразу.

Тем не менее, следующая команда

git checkout .

все восстановил и спас мне жизнь.

Вай-Мин Ли
источник