Jak przywrócić „git rm -r.”?

378

Przypadkowo powiedziałem git rm -r .. Jak mogę się z tego zrezygnować?

Nie zobowiązałem się.

Myślę, że wszystkie pliki zostały oznaczone do usunięcia, a także zostały fizycznie usunięte z mojej lokalnej kasy.

EDYCJA: Mógłbym (gdybym znał polecenie) powrócić do ostatniego zatwierdzenia. Ale byłoby znacznie lepiej, gdybym mógł po prostu cofnąć git rm -r .. Ponieważ nie jestem do końca pewien, co zrobiłem po ostatnim zatwierdzeniu i przed git rm -r ..

użytkownik89021
źródło
3
W przypadku tego konkretnego pytania reset --hard jest dobrym rozwiązaniem ... jest już na liście, więc wspomnę tylko w tym komentarzu, że możesz chcieć sprawdzić dokumentację git-reflog.
William Pursell
8
Zauważ, że ponieważ nie dostarczyłeś -fdo git rmgita, nie usuniesz żadnych plików, które miały zmiany etapowe lub niestacjonarne, więc git reset; git checkout .powinieneś wszystko odzyskać.
CB Bailey,
Tylko uważaj - kup kasę. usunie wszystkie nieustawione zmiany.
PeterB
1
Właśnie zrobiłem coś takiego i nie rozumiem, dlaczego moje lokalne pliki zostały usunięte (i, podobnie jak OP, jeszcze nie popełniłem).
Xonatron
Z Git 2.23+ (sierpień 2019), by przywrócić pliki z git restore: git restore -s@ -SW -- .. Zobacz moją odpowiedź poniżej .
VonC

Odpowiedzi:

468
git reset HEAD

Powinien to zrobić. Jeśli nie masz żadnych niezatwierdzonych zmian, na których ci zależy

git reset --hard HEAD

powinien siłą zresetować wszystko do ostatniego zatwierdzenia. Jeśli masz niezatwierdzone zmiany, ale pierwsze polecenie nie działa, zapisz swoje niezatwierdzone zmiany za pomocą git stash:

git stash
git reset --hard HEAD
git stash pop
Brian Campbell
źródło
22
Zauważ, że git reset --hard HEADniszczy wszelkie przydatne zmiany, które wprowadziłeś w katalogach nadrzędnych bieżącego katalogu roboczego.
Alex Brown
10
@Mild: Nadal mam zimny pot!
hoipolloi
6
Nie oddałem głosu, ale po prostu spróbowałem ukryć, zresetować mocno, pop i straciłem wszystkie moje ostatnie zmiany. Może źle odczytałem odpowiedź.
Greg M. Krsak
1
To rzadko działa dla mnie i cieszę się, że pracuję w folderze Dropbox. Zła forma, ale ratuje mnie za każdym razem ...
Nuby
3
Kiedy zrobiłem git stash pop, po prostu ponownie usunąłem pliki, oczywiście, ponieważ ukrywa fakt, że (przypadkowo) usunąłem niektóre pliki. Ta odpowiedź nie działa, jeśli masz niezaangażowane zmiany, które chcesz zachować.
sudo
252

Dostałem kilka plików i zacząłem wprowadzać zmiany przed kolejnym zatwierdzeniem, kiedy zdałem sobie sprawę, że potrzebuję niektórych z tych plików. Zamiast ukrywać i resetować, możesz po prostu sprawdzić poszczególne pliki, które zostały pominięte / usunięte, jeśli chcesz:

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

Pozostawia to Twoje inne niezatwierdzone zmiany bez zmian.

Jaime Bellmyer
źródło
6
Pomogło to, ponieważ miałem inne niezaangażowane zmiany.
Dan
4
Ta odpowiedź pomaga tym z nas, którzy natknęli się na to pytanie, próbując cofnąć jeden, git rma nie cały cykl rekurencyjny git rm -r. W przypadku pełnego rekurencyjnego usuwania inne rozwiązania mogą być lepsze, w zależności od liczby usuniętych plików.
tresf
Ty, mój człowieku, zasługujesz na nagrodę.
Salamit
Gdybym mógł, kliknąłbym go 100 razy !!!
Wagner Braga
57

Aby odzyskać niektóre pojedyncze pliki lub foldery, można użyć następujących

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

To najpierw odtworzy wpisy indeksu path/to/filei odtworzy plik tak, jak był w ostatnim zatwierdzeniu, tj HEAD.

Wskazówka: do obu poleceń można przesłać skrót zatwierdzenia, aby odtworzyć pliki ze starszego zatwierdzenia. Zobacz git reset --helpi git checkout --helpszczegóły.

Arne L.
źródło
Najlepsza odpowiedź. Łatwe chirurgiczne „cofnięcie” jednej git rmoperacji bez usuwania innych niezamierzonych zmian.
wberry
Pomógł mi! najlepsza odpowiedź.
Akram
28

Aktualizacja:

Ponieważ git rm .usuwa wszystkie pliki z tego i podrzędnych katalogów w działającym kasie, a także w indeksie, musisz cofnąć każdą z tych zmian:

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

To powinno zrobić, co chcesz. Nie wpływa to na foldery nadrzędne wyrejestrowanego kodu lub indeksu.


Stara odpowiedź, która nie była:

reset HEAD

zrobi to samo i nie usunie żadnych niezatwierdzonych zmian , które wprowadziłeś w swoich plikach.

potem musisz powtórzyć wszystkie git addpolecenia, które ustawiłeś w kolejce.

Alex Brown
źródło
1
przepraszam, zawsze konfiguruję git alias.co="checkout"tak, aby git cokasę.
Alex Brown,
25

Jeśli żadna z powyższych czynności nie zadziała, być może będziesz w stanie odzyskać dane, korzystając z sugestii dostępnej tutaj: http://www.spinics.net/lists/git/msg62499.html

git prune -n
git cat-file -p <blob #>
Skippy VonDrake
źródło
4 lata później wciąż ratownik!
ThievingSix
Napisałem program c ++ do łączenia wyników (miałem w mojej repozytorium około 100 obiektów, co czyniło to koniecznym). Po prostu skompiluj i uruchom, a następnie przekaż do lokalnego katalogu git repo. raw.githubusercontent.com/bluuman/git-recover-files/master/…
James Meas
14

cofnij git rm

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

cofnij git rm -r

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

cofnij git rm -rf

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

Uncommitted changesobejmuje not staged changes, staged changes but not committed.

piosenka xu
źródło
Oczywiście niczego nie można cofnąć git rm -rf, ponieważ może to również usunąć pliki bez śledzenia lub przemieszczane (tylko).
jpaugh
git rm -rf filei git rm -rf dirnie usunie żadnych nieśledzonych plików.
piosenka xu
10

Jeśli zatwierdziłeś i wypchnąłeś zmiany, możesz to zrobić, aby odzyskać plik

// Replace 2 with the # of commits back before the file was deleted.
git checkout HEAD~2 path/to/file
Cory Danielson
źródło
To zadziałało w przypadku „Zmiany do zatwierdzenia:”, w której plik został usunięty ze starego git cherry-pick, którego wciąż potrzebowałem. Próbowałem git zresetować HEAD ~ <numer> <plik>, który nie działał.
mushcraft
7

Istnieje już kilka dobrych odpowiedzi, ale mogę zasugerować mało używaną składnię, która nie tylko działa świetnie, ale jest bardzo wyraźna w tym, czego chcesz (w związku z tym nie jest przerażająca ani tajemnicza)

git checkout <branch>@{"20 minutes ago"} <filename>
mehtunguh
źródło
3

Pobierz listę zatwierdzeń

git log  --oneline

Na przykład hash stabilnego zatwierdzenia: 45ff319c360cd7bd5442c0fbbe14202d20ccdf81

git reset --hard 45ff319c360cd7bd5442c0fbbe14202d20ccdf81
git push -ff origin master
Do Nhu Vy
źródło
1

Miałem identyczną sytuację. W moim przypadku rozwiązaniem było:

git checkout -- .
Artur
źródło
0

W Git 2.23+ (sierpień 2019 r.) Właściwym poleceniem przywracania plików (i indeksu) byłoby użycie ... git restore(nie reset --hardlub mylące git checkoutpolecenie )

To jest:

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

Lub jego skrócona forma:

git restore -s@ -SW -- .
VonC
źródło
-1

Miałem dokładnie ten sam problem: czyściłem moje foldery, przestawiałem i przenosiłem pliki. Wszedłem: git rm . i naciśnij enter; i poczułam, jak moje wnętrzności się trochę rozluźniają. Na szczęście nie wpisałem od razu git commit -m.

Jednak następujące polecenie

git checkout .

przywrócił wszystko i uratował mi życie.

Wai-Ming Lee
źródło