Як відновити "git rm -r."


378

Я несподівано сказав git rm -r .. Як я одужаю після цього?

Я не вчинив.

Я думаю, що всі файли були позначені для видалення, а також були фізично видалені з моєї місцевої каси.

EDIT: Я міг би (якби знав команду) повернутися до останнього комітету. Але було б набагато краще, якби я міг просто скасувати git rm -r .. Тому що я не дуже впевнений, що я зробив після останнього вчинення та перед цим git rm -r ..


3
Для цього конкретного питання скиньте --hard - це гарне рішення ... він уже вказаний, тому я лише зазначу в цьому коментарі, що ви можете перевірити документацію на наявність git-reflog.
Вільям Перселл

8
Зверніть увагу , що , тому що ви не постачали , -fщоб git rmмерзотник не буде видалено всі файли , які інсценували або unstaged правки тому git reset; git checkout .повинні відновити все.
CB Bailey

Просто стежте - git checkout. видалить усі нестандартні зміни.
PeterB

1
Я просто зробив щось подібне, і я не розумію, чому мої локальні файли, де видалено (і, як і ОП, я ще не вчинив.)
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. Погана форма, але рятує мене кожен раз ...
Нубі

3
Коли я робив git stash pop, він просто видалив файли знову, звичайно, тому що він приховує факт, що я (випадково) видалив деякі файли. Ця відповідь не працює, якщо у вас є невмілі зміни, які ви хочете зберегти.
судо

252

Я git-rm'd кілька файлів і продовжував вносити зміни до мого наступного фіксації, коли зрозумів, що мені потрібні деякі з цих файлів. Замість того, щоб зберігати та скидати, ви можете просто перевірити окремі файли, які ви пропустили / видалили, якщо хочете:

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 #>

4 роки потому, ще рятівник!
ThievingSix

Я написав програму c ++, щоб об'єднати результати (у мене було близько 100 об'єктів, що звисали в моєму репо, зробивши це необхідним). Просто компілюйте та запустіть, а потім перейдіть у свій локальний каталог git repo. raw.githubusercontent.com/bluuman/git-recover-files/master/…
James Meas

14

відмінити git rm

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

відмінити git rm -r

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

відмінити git 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, оскільки це також може видалити незатребувані або поетапні (лише) файли.
jpaugh

git rm -rf fileі git rm -rf dirне видалить жодних незатребуваних файлів.
пісня xu

10

Якщо ви зробили та натиснули зміни, ви можете зробити це, щоб повернути файл

// Replace 2 with the # of commits back before the file was deleted.
git checkout HEAD~2 path/to/file

Це спрацьовувало для "Здійснення змін:", де файл був видалений зі старого git cherry-pick, який мені ще потрібен. Я спробував git скинути HEAD ~ <номер> <файл>, який не працював.
гриб

7

Є вже кілька хороших відповідей, але я можу запропонувати мало використовуваний синтаксис, який не тільки чудово працює, але дуже чітко відповідає тому, що ви хочете (для цього не страшно чи загадково)

git checkout <branch>@{"20 minutes ago"} <filename>

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 -- .

-1

У мене була точно така ж проблема: чистка папок, перестановка та переміщення файлів. Я ввійшов: git rm . і натисніть Enter; а потім відчув, як моє кишечник трохи розпушився. На щастя, я не набрав git commit -m прямо.

Однак наступна команда

git checkout .

все відновив і врятував мені життя.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.