461

I accidentely said git rm -r .. How do I recover from this?

I did not commit.

I think all files were marked for deletion and were also physically removed from my local checkout.

EDIT: I could (if I knew the command) revert to the last commit. But it would be a lot better if I could just undo the git rm -r .. Because I am not really sure what I did after the last commit and before the git rm -r ..

BuZZ-dEE
  • 6,075
  • 12
  • 66
  • 96
user89021
  • 14,784
  • 16
  • 53
  • 65
  • 3
    For this particular question, reset --hard is a good solution...it's already listed so I'll just mention in this comment that you might want to check the documentation for git-reflog. – William Pursell Jan 24 '10 at 05:42
  • 11
    Note that because you didn't supply `-f` to `git rm` git won't have removed any files that had staged or unstaged changes so a `git reset; git checkout .` should recover everything. – CB Bailey Jan 24 '10 at 08:47
  • 1
    Just watch out - git checkout . will wipe out all unstaged changes. – PeterB Oct 11 '11 at 15:30
  • 2
    I just did something like this, and I do not understand why my local files where deleted (and, like the OP, I have not committed yet.) – Xonatron Aug 26 '15 at 02:38
  • With Git 2.23+ (August 2019), you would restore files with `git restore`: `git restore -s@ -SW -- .`. See [my answer below](https://stackoverflow.com/a/58753735/6309). – VonC Nov 07 '19 at 17:04

13 Answers13

539
git reset HEAD

Should do it. If you don't have any uncommitted changes that you care about, then

git reset --hard HEAD

should forcibly reset everything to your last commit. If you do have uncommitted changes, but the first command doesn't work, then save your uncommitted changes with git stash:

git stash
git reset --hard HEAD
git stash pop
Brian Campbell
  • 322,767
  • 57
  • 360
  • 340
  • 30
    Note that `git reset --hard HEAD` destroys any useful changes you have made in parent directories of the current working directory. – Alex Brown Feb 05 '10 at 14:41
  • 15
    @Mild: I'm still wearing a cold sweat! – hoipolloi Aug 04 '11 at 21:00
  • 9
    I didn't down vote, but I just tried stash, reset hard, pop and lost all of my recent changes. Maybe I misread the answer. – Greg M. Krsak Feb 11 '12 at 20:23
  • 2
    This rarely works for me, and I'm so glad I work in a Dropbox folder. Poor form, but saves me every time... – Nuby Mar 13 '13 at 15:58
  • 5
    When I did git stash pop, it just removed the files again, of course because it stashes the fact that I (accidentally) removed some files. This answer doesn't work if you have uncommited changes you want to keep. – sudo Jul 02 '15 at 18:47
  • 1
    This also did not work for me. The files are still missing. – Xonatron Aug 26 '15 at 02:44
  • This does not answer the question. `git rm -r .` could be executed in any sub-directly. This will reset the entire tree. See @Jaime Bellmyer answer. – niry Feb 09 '16 at 04:43
  • 1
    You may need `git stash -u`/`git stash --include-untracked` if your recent changes include new (untracked) files. – sam Apr 20 '18 at 19:52
  • 1
    @sudo Instead of using `git stash pop` you can use `git stash apply`. This way if there's a merge conflict or you want to discard the changes without them being removed from the top of the stash. – Marcin Wolniewicz May 10 '18 at 22:15
  • `git stash; git reset --hard HEAD; git stash pop` Did the trick for me! Thanks! – Reaz Murshed Oct 02 '19 at 00:15
  • This doesn't help in any way. – Christian Rolle Aug 28 '20 at 09:02
  • `git checkout HEAD .` recovered all my folders and files. – Hmerman6006 Dec 28 '20 at 22:19
  • This solution does not work. Popping the stash back leads to untracked but still deleted files and folders. The following two options work -- (1) `git stash; git reset HEAD; git stash drop 0` (here you are stashing the deleted files/folders and resetting to head and then dropping your stash with deleted changes) (2) `git checkout HEAD .` – Anagha Feb 24 '22 at 23:53
  • i really made a huge mistake – Irvan Hilmi Mar 02 '23 at 10:23
  • If you can read this, be calm. Backup everything before trying any of those git commands. – Alessandro_Russo Mar 29 '23 at 16:19
  • If you have already committed, try `git reset HEAD~n`. (n is the number of how many previous commits you want to go backward. You can also use `^` together with `~` for better control.) – starriet May 04 '23 at 13:34
290

I git-rm'd a few files and went on making changes before my next commit when I realized I needed some of those files back. Rather than stash and reset, you can simply checkout the individual files you missed/removed if you want:

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

This leaves your other uncommitted changes intact with no workarounds.

fash jr
  • 7
  • 4
Jaime Bellmyer
  • 23,051
  • 7
  • 53
  • 50
  • 9
    This helped because I had other uncommitted changes. – Dan Aug 25 '14 at 04:50
  • 6
    This answer helps for those of us that stumbled upon this question looking to revert a single `git rm` rather than an entire recursive `git rm -r`. For a full recursive delete, the other solutions may be better, depending on the amount of files removed. – tresf Mar 15 '16 at 01:43
72

To regain some single files or folders one may use the following

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

This will first recreate the index entries for path/to/file and recreate the file as it was in the last commit, i.e.HEAD.

Hint: one may pass a commit hash to both commands to recreate files from an older commit. See git reset --help and git checkout --help for details.

Arne L.
  • 2,194
  • 19
  • 19
  • 1
    Best answer. Easy surgical 'undo' of a single `git rm` operation without wiping out other uncommitted changes. – wberry Jul 08 '19 at 20:09
36

undo git rm

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

undo git rm -r

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

undo git rm -rf

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

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

song xu
  • 361
  • 3
  • 6
33

Update:

Since git rm . deletes all files in this and child directories in the working checkout as well as in the index, you need to undo each of these changes:

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

This should do what you want. It does not affect parent folders of your checked-out code or index.


Old answer that wasn't:

reset HEAD

will do the trick, and will not erase any uncommitted changes you have made to your files.

after that you need to repeat any git add commands you had queued up.

Alex Brown
  • 41,819
  • 10
  • 94
  • 108
30

If you end up with none of the above working, you might be able to retrieve data using the suggestion from here: http://www.spinics.net/lists/git/msg62499.html

git prune -n
git cat-file -p <blob #>
Skippy VonDrake
  • 806
  • 8
  • 21
  • 1
    4 years later, still a lifesaver! – ThievingSix Sep 18 '16 at 06:23
  • 1
    I wrote a c++ program to concatenate the results (I had some 100 objects dangling in my repo, making this necessary). Just compile and run, then pass in your git repo local directory. https://raw.githubusercontent.com/bluuman/git-recover-files/master/main.cpp – James Meas Jun 20 '18 at 05:28
  • This is a good method, after running the `git prune -n`, I got many lines, those lines are either `tree` or `blob` or `commit`, and I fill out all the hash string of `blob`, and I try to use the second command to `git cat-file -p `, and I still can't find the lost file. My situation is quite simple, I have create a new file named `a.cpp`, and I add this file to the index, and later I use the `git rm -f` to remove this file, and I see that `a.cpp` get lost. – ollydbg23 Apr 27 '21 at 06:00
  • Sorry about my previous comment, I tested again, it can recover the `git rm -f` deleted file, I'm not sure why the previous test does not works, thanks! – ollydbg23 Apr 27 '21 at 08:18
  • Just a note that while this works, it cannot recover filenames or paths, so if you're like me and you just deleted a 5k file nested folder system you were trying to create a repo for, you are basically completely out of luck. – Mordred Aug 03 '22 at 03:27
12

If you've committed and pushed the changes, you can do this to get the file back

// Replace 2 with the # of commits back before the file was deleted.
git checkout HEAD~2 path/to/file
Cory Danielson
  • 14,314
  • 3
  • 44
  • 51
  • This worked for 'Changes to be committed:' where a file was deleted from an old git cherry-pick which I still needed.I had tried git reset HEAD~ which didn't work. – mushcraft Jun 06 '16 at 15:48
7

There are some good answers already, but I might suggest a little-used syntax that not only works great, but is very explicit in what you want (therefor not scary or mysterious)

git checkout <branch>@{"20 minutes ago"} <filename>
krethika
  • 3,908
  • 1
  • 24
  • 27
4

If you execute the command git rm -r --cached . on a repo with changes that are not staged (so not committed either), you can undo the operation (unstage from deletion) with the command git restore --staged .

So in a nutshell, to undo git rm -r --cached . you only need to run git restore --staged .

Narnia_Optimus
  • 326
  • 1
  • 16
  • This worked for me luckily before I did a commit but for clarity you have to append the file that you removed to the end as in: `git restore --staged completePathToRemovedFile` – Lance Samaria Jun 26 '23 at 08:17
3

Get list commit

git log  --oneline

For example, Stable commit has hash: 45ff319c360cd7bd5442c0fbbe14202d20ccdf81

git reset --hard 45ff319c360cd7bd5442c0fbbe14202d20ccdf81
git push -ff origin master
Vy Do
  • 46,709
  • 59
  • 215
  • 313
3

With Git 2.23+ (August 2019), the proper command to restore files (and the index) woud be to use... git restore (not reset --hard or the confusing git checkout command)

That is:

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

Or its abbreviated form:

git restore -s@ -SW -- .
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
2

I had an identical situation. In my case the solution was:

git checkout -- .
Artur
  • 445
  • 3
  • 13
-1

I had exactly the same issue: was cleaning up my folders, rearranging and moving files. I entered: git rm . and hit enter; and then felt my bowels loosen a bit. Luckily, I didn't type in git commit -m "" straightaway.

However, the following command

git checkout .

restored everything, and saved my life.