Recover from (nearly) anything, using Git

Ever faced a disaster with git rebase or reset --hard? Don't panic! Today, you'll learn how to undo most mistakes and recover from nearly anything. Perfect for any developer!Turn Git nightmares into success stories!

Recover from (nearly) anything, using Git
Photo by USGS / Unsplash

For some reason, you were sure your rebase had gone right, and you pushed to origin. Or perhaps you reset --hard, but on the wrong commit. Then pushed -f to origin.

But you were wrong. And since you were the only dev on the project, everything you did in the last 4 weeks is now gone.

Absurd, I know. It shouldn't be possible. I agree. But now that we've said that, what should we do? Fixing the process won't recover those weeks of work.

Well, fret not, because your cause might just not be lost. How do I know? I've been there myself. Ten minutes ago.

Recovering from a wrong rebase

I've set up a test repository for you: git-reflog-example. First thing, you'll have to clone it. You should have only a single file: file.txt. Next, checkout the branch feat/remove-file-txt-and-add-readme. file.txt should be gone, and now you should find a new file: our dear old friend, README.md. Now, rebase on origin/feat/rebase. Suppose you push, or force-push this, and nobody else had our feat/remove-file-txt-and-add-readme, we'd be in a pickle, wouldn't we?

via GIPHY

Well, fret not. Just like Pickle Rick had... well.. Rick, we have git.

Run git reflog. It will display all the latest operations. Including our rebase. The first three listed operations will be those related to the rebase we just did. Something along those lines:

e2a6702 (HEAD -> feat/remove-file-txt-and-add-readme) HEAD@{0}: rebase (finish): returning to refs/heads/feat/remove-file-txt-and-add-readme
e2a6702 (HEAD -> feat/remove-file-txt-and-add-readme) HEAD@{1}: rebase (pick): remove file.txt, add readme
2d306b4 (origin/feat/rebase) HEAD@{2}: rebase (start): checkout origin/feat/rebase

The fourth line, however, will be the last thing we did before our rebase.

dfb43f0 (origin/feat/remove-file-txt-and-add-readme) HEAD@{3}: checkout: moving from main to feat/remove-file-txt-and-add-readme

So now, simply run git reset --hard HEAD@{3}, check your directory's content, and welcome README.md back among the living.

Recovering from a hard reset

Delete your local clone, and clone https://github.com/El-Fitz/git-reflog-example again. Checkout feat/remove-file-txt-and-add-readme, and checkout your directory's content. It should contain both README.md .

Now, hard reset to the previous commit: git reset --hard HEAD~1. README.md is gone, again. Nooo... Oh my god! They killed README.md!

via GIPHY

Or did they?

Run git reflog again. See that last line?

967b50e (HEAD -> feat/remove-file-txt-and-add-readme, origin/main, origin/HEAD, main) HEAD@{0}: reset: moving to HEAD~1

That's our hard reset.

Run git reset --hard HEAD@{1}, and check your directory's contents again. Just like that, README.md is back from the grave! Again! Thanks First, CB Bailey!

Epilogue

For a really great git lesson, check out Github co-founder Scott Chacon's FOSDME 2024 So You Think You Know Git talk. It made me realise I didn't even realise how little I knew. So, enjoy!

That's all! I hope it was helpful, and with you all a great day!