If you haven’t seen http://ohshitgit.com yet, stop reading this blog series and go check out that site, then come back here. I’m going to play out this scenario using the Visualizing-Git tool from yesterday.
I need to print this out this accidental-commit-master section and have it laminated on my desk. How many years have I gone to work, fired up Visual Studio, and started typing? And now all of a sudden I have to create a new branch first? I feel like this is the pilot equivalent of having to lower the landing gear before taking off. Nah, I don’t regret my career/life choices at all!
As my above drama illustrates, you’ve been coding along on a new feature and then you realize, “oh no! I’m still on master!” What I’ve done for years is Ctrl+C, Ctrl+V, diff my changes, delete either the last commits and/or working directory, and then create the branch and move over my changes. At least I’m being honest.
We’ll follow these steps from ohshitgit.com via command line. But don’t stress if it doesn’t make sense. Once we rinse and repeat from Visualizing Git, it will make much more sense!
Part 1 – Command Line to the rescue!
Let’s say you’ve been working, working, working on your code, and suddenly you realize all these files you’ve added have been to master instead of a new feature branch!
First, don’t panic. Take a deep breath and don’t delete anything 🙂
Next, create a branch (git branch branch-name), but don’t check it out, so no `git checkout -b branch-name` shortcut!
Now do `git reset –hard <commit ID to roll back to>`, e.g. I want files 1-6 added to my feature-work branch, so I’ll use the commit ID for the readme.
Note: since you are using the –hard, in the future, you’ll need to make sure that you don’t want to keep anything in your staging or working directory.
What?? Is our work gone?? There’s no commit logs for files 1-6. and doing a `ls -la` or `dir` or a `git ls-files` only shows the readme!
It might not seem like it but our work is still there. To quote my inner matrix, “the answer are coming.”
Now finish this by checking out the branch…
WTF? Don’t give up. The answers are coming. I promise. (This is a conversation I would have had with myself from a week ago.)
Part 2 – Visualizing Git to the rescue’s rescue
Okay how on Earth did that work? Let’s rinse and repeat using the Visualizing Git tool.
First I’ll commit a readme and then 6 files.
now we’ll create that branch, but don’t check it out!
Remember that a branch is a pointer. Reminds me of a high school teacher who said “A logarithm is an exponent” over and over and over again in hopes we wouldn’t panic when we had to deal with logarithms in the future.
But now we can see that the branch points to where master (another branch) is pointing. This is my ah-ha moment! In my mental model I’ve been visualizing a branch as a collection of commits from some starting point to some ending point, but here I can clearly see it is just pointing to the last commit I created it at.
Now let’s break down`git resert –hard commitID`
- git reset means that it is moving where the current branch is pointing at (aka the tip) back to some previous commit.
- — hard means Git will reset both staging and working directory to the changes you’re resetting to, so make sure `git status` is clean
- some instructions show HEAD~. HEAD is a pointer as shown in the illustration. HEAD~ means move back one commit (HEAD~1 does the same as HEAD~). But since we want to remove all the files from master and not just file 6, we’d either have to do commitID or HEAD~6. CommitID is just easier to follow in this example.
When you type in `git resert –hard <commitID-for-readme>` you’ll see the following:
Now things are making A LOT more sense. The feature-work pointer still points to all of our work since we’re only moving the tip of the master branch back.
and for the grand finally, you can now switch to that branch.
And just to finish this all off since we’ve come this far after all, you can either do a merge (which will automatically do a fast-forward because no conflicts) or if you want to show that this work was always on a branch, you could do 1. `git checkout master` and 2. `git merge –no-ff feature-work`but we’ll talk about this in future tips.