3 min read

How to recover from a git reset --hard

Etienne Marais

Today I was tired after writing pretty complex code without getting up for a break. I added some Log::info statements in a file that I didn't want to commit and I hopped over to the console to reset the file but instead I did

git reset --hard

I swore pretty loudly :D

Can I even recover after resetting everything?

Yes, and no. It depends. Did you do a git add . before? Then yes.

git add . adds all modified and new (untracked) files in the current directory and all subdirectories to the staging area (a.k.a. the index), thus preparing them to be included in the next git commit source - Thx Klas

This will cache the changed files but the question is where can I find them?

git help fsck

There is a git command that does the following:

Verifies the connectivity and validity of the objects in the database. If no objects are given, git fsck defaults to using the index file, all SHA-1 references in refs namespace, and all reflogs (unless --no-reflogs is given) as heads.

After you did a hard reset there will be a couple of dangling objects in the index even though they are not visible.

--lost-found
    Write dangling objects into .git/lost-found/commit/ or 
    .git/lost-found/other/, depending on type. If the object 
    is a blob, the contents are written into the file, 
    rather than its object name.

I hopped over the the project folder <repo>/.git/lost-found/other/ and there they were, my whole day.

╰ git fsck --lost-found
Checking object directories: 100% (256/256), done.
Checking objects: 100% (205137/205137), done.
dangling blob c09fc80f517bbc2488cb0cecfbe6385454c1bcd6
dangling blob e0a0d8b9c328c3b5234b5813e8030935be42e21b
dangling blob 0dd2c05c9b277f5085cf01643fa17ab84f3193d1
dangling blob dc4a0a051fd9c7243f82adde04400b4ae0b2db21
dangling blob 2f725a9f33aec8f82522f216d8b15c0e74ed2878
dangling blob 55739268f20c19898745c6d74ac0efa1cb7a9b40
dangling tag 03d80ac79c928f6bf24a5c0b7c43a6464e3408f2
dangling blob c1db6a451ccaeb5ac0a6fd065528c674340eb728
dangling blob a58d0b0dc1e13b26c95f2ab736df3d68e1ce5ba5
dangling blob 9b3a7cf27dc20de680daf578611f0549b1bb2053
dangling blob 403665fd1dd5bbbaee9d5327564c2a80fe4556ee
dangling blob 693645b2694d03243c501a3c7e5abedc44d3c119
dangling blob ea84e5fa3034faf8d8320419456e8ff8d776c630
dangling blob e19ef6dc9d87cbd69a03ef04b9d2dc60afce4d14
dangling blob 9dd376c984889c42119636352898ad8d708788e7
dangling blob 0fbe175b4553bfdf7426da18834b0a2f4b3e9578

Here comes the manual part, you have to open those files and find your changes but it's generally easy to scan over them and add them back into to be committed.

Takeaways

First of all, commit often. Kind of self explanatory. But if you want to unstage a file use git reset HEAD <file> and git checkout -- <file> and forget about about git reset --hard unless you are working on a hackathon or just messing around and need to clean everything.

Thanks for staying.