Git has been gaining popularity the past few years, together with awesome web-interfaces from Github, Bitbucket etc. people are adopting the tools quicker than ever. For most people, when dealing with git, git-add, git-rm, git-commit, git-push, git-branch and git-pull are more than sufficient. It is not until you have ruined the versioned copies – e.g. hard reset, would you wish you could have a recovery command.
Oops
Say, you issued the following command without much thinking:
# The --hard flag makes this command dangerous
git reset HEAD~1 --hard
This basically bring you back to the previous commit (HEAD~1), while trashing all the non-committed local-files. What if there’s certain working copies that are important, but you only realize it after you have mistakenly hard-reset the file? That’s where git-reflog comes into play.
git-reflog
git-reflog in fact recorded all the action you have done on the repository, such that you can always reference previous works.
Taking the above as an example, to remedy the problem and restore the deleted files, you can first do a git-reflog on the repository. It will show you all the actions that was done on the current repository.
[master] > git reflog
393a76b HEAD@{0}: reset: moving to HEAD~1
bb8271a HEAD@{1}: commit: Fixed stackoverflow error
109d879 HEAD@{2}: commit: Updated content
f76d677 HEAD@{3}: commit: Added new keybindings including json pretty print & fix open-new-line misbehaviour
d91dcc7 HEAD@{4}: commit: Sync up
393a76b HEAD@{5}: commit (initial): Initial Commit
Here, 393a76b is the reset action we have done above, and what follows are the previous action updates on the repository before the reset.
To recover the deleted files, you can either do a git-reset to bb8271a or git-cherry-pick on bb8271a.
# git reset --hard
[master] > git reset bb8271a --hard
HEAD is now at bb8271a Fixed stackoverflow error
# or git cherry-pick
[master] > git cherry-pick bb8271a
[master bb8271a] Fixed stackoverflow error
1 file changed, 1 insertion(+)
Doing a git-log now shall find the commit being restored. And you can feel free issuing a git-reset, this time using the –soft flag.
Save some space
In order to provide git-reflog functions, repository would need to maintain enough information for each action entries, which takes up repository space. If space is critical, say you have a huge repository or very frequent commits, the following commands could help to reclaim some space.
# Expire reflog history that were older than 7 days
git reflog expire --expire=7.day
# or expire reflog history that were older than 7 days
# and unreachable from the current branch
# git reflog expire --expire-unreachable=7.day
git prune
git gc
Though if space isn’t that much of a problem, I wouldn’t suggest running the above command; Besides, by default, historic entries that are > 30 days would be expired automatically.
So
git-reflog is such a great recovery tools, not just for hardreset, but could also save you from bad merges or undoing repository actions. For more details on how to use git-reflog, read the manpage.