This is extremely easy to fix. First, I'll tell you what to type. Then, I'll tell you how it works, so that you can adjust the solutions to your own needs.
What to Type:1) Commit your changes. It's ok if they're not finished; you'll come back to these later.
2) git branch feature_branch_name
3) git reset --hard origin/master
Bam, your changes are saved off on feature_branch_name, your current working directory matches what was in the origin repo last time you fetched (or pulled) from it, and you are ready to start work on the bug.
1) After your changes are committed, you're still on the master branch. git status looks like:
# On branch master # Your branch is ahead of 'origin/master' by 2 commits. # nothing to commit (working directory clean)and in gitx (if you're on a Mac, please download gitx):
2) git branch
This operation does not check out the new branch; master is still your current branch. Git status has not changed, and gitx has that new label on it:
3) Now the real magic. "git reset --hard origin/master" does three things. Primarily, it moves the "master" label (your current branch) to wherever "origin/master" is. That's what reset does: it moves labels around.
The output is:
HEAD is now at 0562dac Some commit that's already been pushed to originThis tells you the second thing it did: it moved the HEAD label, which marks where you're currently working. You're now working on master, which is now before you did your feature-related changes.
Git status looks the same. Gitx says:
"--hard" tells git to rejigger all your files.
Why is "--hard" not dangerous? well, it can be. But we're safe because
1) we committed changes
2) we gave that commit a label.
Git will always and forever remember the exact state of your code at any commit that has a label, or is in the history of any commit with a label. If a commit is reachable in the history from any reference (branch, HEAD, tag), then it is safe.
The critical point to this operation -- the reason this is really easy for me now, but was super-hard before I understood the commit graph -- is that we don't have to move any code. We don't have to move any commits to a branch: instead we move the labels around. Branches are simply pointers to a commit. We can move them around all day. In this example, we added a new pointer for the branch, moved the "master" pointer back to where it was before our changes, and replaced our working directory files with the older stuff.
This contrasts sharply with the overhead of branching in Subversion. Yay Git!