I often do this – I work away on my master branch and suddenly realise ‘damn I should have branched before I started this’. Usually this happens because what I think will be a trivial change snowballs into something much more sweeping. I thought I would record here how to deal with situations like this by retroactively creating a branch and rolling master back to a previous state. Note: backup your data first and this is only ideal if you haven’t pushed changes to a remote repo yet.
So here was the situation. My last ‘known good’ state was 8399227db and I wanted to move all subsequent work out of master and into a branch. So first lets create that branch starting from the last known good state:
git branch refactor_branch 8399227db
Next I check out the branch and merge all the changes from master into it:
git checkout refactor_branch git merge master
Now I switch back to master and chuck away all changes made since the branch point (did I mention you should backup your work first?):
git checkout master git reset --hard 8399227db
So I rebased the master branch to an older commit. Now I push my branch up to the remote repository and breath a sigh of relief that my work is backed up in the cloud and master remains usable for others working on it:
git push origin refactor_branch
As a last couple of steps, I remove my local branch and checkout the remote branch as a tracking branch:
git branch -D riab_to_inasafe git branch --track riab_to_inasafe origin/riab_to_inasafe git checkout riab_to_inasafe
Git being git, there are probably a thousand other ways to accomplish the same thing, but the above process works for me!
Nathan Woodrow
Are you sure git rebase SHA1 works? It just tell me the current branch is up to date.
I find using:
git reset –hard {SHA1}
works if you need to move the HEAD commit back.
Tim Sutton
Hi
Sorry you are absolutely right it was probably a cut & paste error. Here is a minimal test showing reset –hard doing its job:
timlinux@ultrabook:/tmp$ mkdir testtimlinux@ultrabook:/tmp$ cd test
timlinux@ultrabook:/tmp/test$ git init
Initialized empty Git repository in /tmp/test/.git/
timlinux@ultrabook:/tmp/test$ echo "Hello" > readme
timlinux@ultrabook:/tmp/test$ git add readme
timlinux@ultrabook:/tmp/test$ git commit -m "Version 1"
[master (root-commit) 6ef3224] Version 1
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 readme
timlinux@ultrabook:/tmp/test$ echo "World" > readme
timlinux@ultrabook:/tmp/test$ git commit -m "Version 2" -a
[master 9162717] Version 2
1 files changed, 1 insertions(+), 1 deletions(-)
timlinux@ultrabook:/tmp/test$ git branch testbranch
timlinux@ultrabook:/tmp/test$ git log
commit 91627170c4ff126dc8eda55f83ec961d904b31f6
Author: Tim Sutton
Date: Thu Mar 22 12:14:08 2012 +0200
Version 2
commit 6ef3224f61adb6424d9a6dacf5febd29324f53bb
Author: Tim Sutton
Date: Thu Mar 22 12:13:42 2012 +0200
Version 1
timlinux@ultrabook:/tmp/test$ git reset --hard 6ef3224f61adb6424d9a6dacf5febd29324f53bb
HEAD is now at 6ef3224 Version 1
timlinux@ultrabook:/tmp/test$ cat readme
Hello
timlinux@ultrabook:/tmp/test$ git checkout testbranch
Switched to branch 'testbranch'
timlinux@ultrabook:/tmp/test$ cat readme
World
timlinux@ultrabook:/tmp/test$ git merge master
Already up-to-date.
timlinux@ultrabook:/tmp/test$ cat readme
World
timlinux@ultrabook:/tmp/test$ git checkout master
Switched to branch 'master'
timlinux@ultrabook:/tmp/test$ cat readme
Hello
I will adjust the article accordingly.