Have you ever committed something, tried to git rebase
, and everything went horribly horribly wrong? Or accidentally git reset --hard HEAD^
when you meant to git reset HEAD^
? Have no fear, git reflog
is here!
When you use git, commits are never lost. You can always get back to any repository state as long as you committed your changes. The only time commits are actually deleted is if you git gc --prune
(so be careful with that one!).
If you run git reflog
right now in a repository you’ve been working in, you’ll see lots of changes that look something like this:
c5c3a82... HEAD@{0}: pull origin featureB: Merge made by recursive. 49d0608... HEAD@{1}: reset --hard HEAD^: updating HEAD 3ed01b1... HEAD@{2}: pull origin featureA: Merge made by recursive. 49d0608... HEAD@{3}: pull origin bugfixJ: Merge made by recursive. 854d44e... HEAD@{4}: commit: Add more cowbell to foo.c 6dbc22d... HEAD@{5}: pull origin bugfixI: Merge made by recursive. 9bdb763... HEAD@{6}: commit: Remove weevils 8518f9d... HEAD@{7}: checkout: moving from wickedfeature to master
These lines can be broken down into 4 parts: commit hash, commit pointer, action, and extra info.
It’s great that you can see this information but what use is it to us, you ask? Remember that git branches are just pointers. The only reason there is history associated with a branch is because the commit it points to has parents.
If we wanted to get back the commit that was lost at HEAD@{1}
, we could just git reset --hard HEAD@{2}
. Now our current branch (and working copy) are set to the repository state before we did the reset.
If we wanted to just see what that state was, we could git checkout -b temp HEAD@{2}
(or git checkout HEAD@{2}
if you have git 1.5.0 and up).
Being aware of git reflog
will make you feel that much more comfortable when running commands that alter history. Just remember, as long as you’ve committed it, it’s still there!
References:
8 comments
Comments feed for this article
April 6, 2008 at 9:20 am
Dusty
You jumped the gun by not git-fuing git-rebase. I’m still a bit unclear on that one.
Is git-fuing a word? What do you say? git-fu his ass!
June 10, 2008 at 6:06 pm
Dusty
Git reflog just failed me. It doesn’t really help much if you git reset –hard when you really wanted to keep all the changes in your working copy. đŸ˜¥
June 10, 2008 at 9:21 pm
xentac
That’s right, git reflog only works on commits. Git mostly ignores uncommited changes in the working copy.
June 11, 2008 at 10:25 pm
Dusty
The moral of the story is its always better to git-commit things even if you know they’re wrong. At least then you have a reference to it. Although in this case, I thought I had git-committed them, but some files were missed.
The moral of the new story is always run git status.
April 16, 2012 at 11:50 pm
alsuren
I pretty much always use git stash before reset –hard. It means that my gitg window is normally full of stash cruft, but it does mean that I never get screwed. Maybe I should set up an alias from git-hard-reset to git stash; git stash drop; git reset $*. That would solve *all* of my problems.
August 16, 2008 at 3:32 am
Experiences with Mercurial and Git - Emil Sit: Thoughts and Observations
[…] pointers to some commit on a commit graph and its constant tracking of your commit history with reflogs around allows you to develop without fear of losing your work, even when arranging things so that […]
September 17, 2008 at 2:57 am
albcamus
>That’s right, git reflog only works on commits. Git mostly ignores uncommited >changes in the working copy.
FYI, you can use git stash to ‘stash’ any uncommitted changed in your working dir, and restore it later.
October 5, 2008 at 4:29 pm
Dev
This post just saved a huge chunk of work that I accidentally “git reset –hard”ed away. If I hadn’t found this post I would have assumed it was just gone.