So you know you should pretty much
never hack directly on master when working with git. Instead, you should create branches and merge them later. Beyond best practices for their own sake, some github projects really want you creating pull requests from a certain branch.
Sometimes, however, I get in
the zone and forget to checkout a branch because I want to get this feature DONE! In my haste, I commit to master directly. I don't want my pull request to be rejected just because I hacked on master.
What do we do now?
Luckily, recovery is extremely simple. We can fix the repo up to get back in line with branching best practices.
So say we've just committed to master and we're currently on the master branch.
$ git log
commit 9huuh23tnhubazhuxbeeashebcdjis3hl2iidu
Author: Joseph McCullough <joseph@vertstudios.com>
Date: Wed Apr 11 22:15:10 2012 -0500
Refactor new feature X to be more awesome
commit xotnhnt234ub23st2b323hb23tu2bh32bu23uu
Author: Joseph McCullough <joseph@vertstudios.com>
Date: Wed Apr 11 22:05:10 2012 -0500
New feature X
commit b232udh24xub2394d249ud394ub34bu9348ub9
Author: Joseph McCullough <joseph@vertstudios.com>
Date: Wed Apr 11 12:05:10 2012 -0500
Some upstream master commit
The last two commits needed to be on their own branch, say
new_feature. Your local master branch needs to be at "Some upstream master commit". Here's how we can accomplish this.
Step 1) Create the new_feature branch
Since master is currently in the state we want the new_feature branch to be in (since we've just added our new feature commit), we can just branch off of master.
$ git branch new_feature
So new_feature is just a direct copy of master at this point.
Right now, we're still on the master branch. As stated above, we want the master branch to be at "Some upstream master commit". We can accomplish this via
git reset --hard.
Step 2) Resetting the master branch
A side note regarding git reset --hard:
It's important to note that git reset --hard is NOT a safe operation. You CAN lose work if you don't use it carefully. Luckily, in this context, there's nothing to worry about since I'm guiding you through the process...but just for your toolbelt, visit this
StackOverflow answer thread if you ever accidentally lose work to git reset --hard.
Anyway, to get the master branch back to "Some upstream master commit", we can copy the SHA of the commit from git log to our clipboard and execute
$ git checkout master
$ git reset --hard b232udh24xub2394d249ud394ub34bu9348ub9
HEAD is now at ... Some upstream master commit
Also, for convenience, we can use the HEAD alias. In this example, we wanted to reference the commit that was 2 commits behind the latest commit. We could have equally executed
$ git checkout master
$ git reset --hard HEAD~2
The git log should now look like the following:
$ git log
commit b232udh24xub2394d249ud394ub34bu9348ub9
Author: Joseph McCullough <joseph@vertstudios.com>
Date: Wed Apr 11 12:05:10 2012 -0500
Some upstream master commit
Step 3) Verification
We've verified the master branch is where it should be, so now we should checkout the new_feature branch and run a git log.
$ git checkout new_feature
Switched to branch 'new_feature'
$ git log
commit 9huuh23tnhubazhuxbeeashebcdjis3hl2iidu
Author: Joseph McCullough <joseph@vertstudios.com>
Date: Wed Apr 11 22:15:10 2012 -0500
Refactor new feature X to be more awesome
commit xotnhnt234ub23st2b323hb23tu2bh32bu23uu
Author: Joseph McCullough <joseph@vertstudios.com>
Date: Wed Apr 11 22:05:10 2012 -0500
New feature X
commit b232udh24xub2394d249ud394ub34bu9348ub9
Author: Joseph McCullough <joseph@vertstudios.com>
Date: Wed Apr 11 12:05:10 2012 -0500
Some upstream master commit
So we still have our work, but it's on a feature branch, as it should be! We're now free to send a pull request without any bickering from the project owner, or we can merge the new_feature branch later once it's ready for production.
April 12, 2012