Oops, I Lost My Git Commits! Here’s How to Bring Them Back from the Dead
OH NO MY CODE IS GONE!!! RefLog to the rescue
I’m dropping this here as much as a reminder to myself as anything else. This had me in a panic when I nearly lost a couple of days’ worth of commits hours before a demo.
The Problem
Imagine this scenario: you’re working on a branch and committing regularly things are going well and looking good for an upcoming demo. Suddenly, your colleague force-pushes changes to the same branch, and when you pull, you realise that your recent commits have vanished. You can still see them on GitHub, but they appear orphaned. Frustrating, right? Thankfully, there’s a way to recover them.
Step 1: Identify the Lost Commits with Git Reflog
The first step is to determine where those lost commits went. Git keeps a record of all the actions taken in your repository — including commits that aren’t part of any current branch — in a magical place known as reflog.
Run the following command to see your reflog:
git reflog
This command will list all of the recent actions in your repository, including commits, checkouts, resets, and more. Each action will have a commit hash (SHA) next to it. Look through this list to find the commit hashes of the missing commits.
For example, let’s say the commits you’re interested in are:
abc1234
: test: update provider render logicdef5678
: refactor: implement PR feedback tweaksghi9012
: refactor: tidy tests and styles
Step 2: Create a Recovery Branch
To safely work on recovering the lost commits, it’s a good idea to first, create a new branch:
git checkout -b recovery-branch
This way, you can make changes without affecting the current state of your working branch.
Step 3: Cherry-Pick the Commits
With the commit hashes identified, you can use git cherry-pick to apply those commits to your recovery branch:
git cherry-pick abc1234
git cherry-pick def5678
git cherry-pick ghi9012
This will apply each of these commits to your current branch, effectively “recovering” them.
Step 4: Merge or Rebase Onto the Original Branch
Once you’re confident that all the commits have been recovered, it’s time to merge or rebase them back onto your original branch (feat/item-2008/add-new-feature
).
First, switch back to your original branch:
git checkout feat/item-2008/add-new-feature
Then, either merge the recovery branch:
git merge recovery-branch
Or, if you want the recovered commits to look like they were never lost, rebase them:
git rebase recovery-branch
Step 5: Resolve Conflicts (If Any)
If conflicts arise during the cherry-pick or rebase process, Git will notify you. To resolve conflicts:
- Open the conflicting files in your editor and make the necessary changes.
- Mark the conflicts as resolved:
git add <file>
3. Continue the rebase or cherry-pick:
git rebase --continue
Step 6: Push the Recovered Commits
Once everything is in order, push the recovered commits back to the remote repository. Since the commit history has changed, you will need to force-push:
git push origin feat/item-2008/add-new-feature --force
Conclusion
A force push can lead to unexpected situations, but Git’s powerful features like reflog and cherry-pick make recovering lost commits possible. By following these steps, you can ensure that your hard work isn’t lost forever.
I would be interested to hear about any other issues people have encountered in their dev days.