Yesterday I ran into a situation with git where I was working away on some code, finished what I was doing and committed the changes. Immediately after making the commit, I realized that I was still sitting in my master branch instead and had made the commits there instead of on a topic branch like I meant to.
If I were using subversion, at this point I would create a branch from the head of where I committed and then revert the original commits. The subversion history would show that I made the mistake and anyone that pulled changes from the original location would get the commits applied and then rolled back.
Git makes this situation trivial, and no one will ever have to know that you accidentally made a commit to the wrong branch, first. :)
Git Reset To The Rescue!
The first thing you want to do is snap off a new branch, just like you would in subversion. I normally like to use the ‘checkout’ shortcut to create the branch and switch to the branch at the same time:
1: git checkout -b mytopicbranch
but in this case, I don’t actually want to checkout the branch yet, so I’m just going to create a branch without switching to it:
1: git branch mytopicbranch
At this point, both mytopicbranch and master are pointing to the same location.
What we really want, though, is for master to still be back at “initial commit” and mytopicbranch to contain the two commits that were made after that. To do this, we need to know the sha fingerprint of the commit we want (which we can see in the above image) and we need to use the ‘git reset’ command. The great thing about reset is that is doesn’t do anything to the contents of the repository like a revert would do. Rather, the reset command just moves the branch pointer (the HEAD of the branch) to the commit that you specify.
Run this command:
1: git reset 2f7efb32 --hard
and you will see git move the HEAD of the master branch to that commit:
Now when we look at the repository again, we see master where we want it and we see mytopicbranch where it should be, as well!
No changes were made to the content of the repository. We only moved the HEAD pointer for the master branch around and made it look like we actually created our branch before making those other two commits. :)