{April 7, 2010}   git branch surgery

Arno just wrote about his solution to forgetting what git branch you’re on. I suffer from the same problem – I’d forget me own head if it wasn’t screwed on – but I came up with a different solution. :)

I’m been using git-svn more and more, to the point where I actually won’t write code without it if I expect the patch to take more than a few hours. I’ve accumulated several of these git-svn repos now (often within svn) and I’ve been getting more comfortable working with git, so I’ve started performing minor branch surgery.

say you were on branch foo yesterday, hacking away at a cool feature. Today, you start thinking about feature bar, and hack a bit on that. A few commits later, you remember where you’re committing to, and realise this feature doesn’t belong in that branch. However, it does *depend* on feature foo, or at least you know you’ll be dcommitting foo before bar, so you at least have things in the right order.

Now, first you create a branch to keep bar safe.
git checkout -b bar
now that that’s safe… well, I’m sure there’s a better way to do this, but the *easy* way is to first get rid of foo:
git branch -d foo
then look up the hash of the last commit that actually should belong to foo (copy&paste is your friend):
git log
run over to that commit:
git checkout <hash>
and recreate the branch there:
git checkout -b foo

ta-daa! now branch foo has gone back in time to where it should have ended, and branch bar builds on foo with your latest commits. :) and if you’d forgotten to create bar first, git would have refused to delete foo, so you don’t have to worry much about losing anything to a typo (so long as that typo is not -D. stay away from the dragons ;)

oh, and do remember to go back to branch bar before you continue hacking. :)

RichiH says:

You could use zsh with the vcs_info plugin. That way, you would never forget on what branch you are :)


Tobias Wich says:

What you describe here can be done with git reset. You just have to create a new branch bar, as you described above, then checkout branch foo and type git reset –hard some-sha1.
This can also be done with gitk. I like it better, because you see where you are. Right click on the commits and you can move branches as they are only pointers to commits.

To see on which branch you are, you can modify your PS1 shell variable. I use the following code for that.

GITPS1=’$(__git_ps1 “:%s “)’
PS1=”${GREEN}\w${RS} ${YELLOW}${GITPS1}${RS}\\$ “

Simon says:

A slightly easier way that does not involve checking out multiple times:

Create a branch to keep bar safe.
$ git branch bar
then look up the hash of the last commit that actually should belong to foo
$ git log
Reset foo to the correct hash. Make sure you don’t have uncommitted or staged changes first.
$ git reset –hard
Check out bar and continue workiing
$ git checkout bar

You really should steal Arno’s bash foo there, I have a similar solution. I think I would have broken many commits without it.

Simon says:

Oops. the third command should be:
$ git reset –hard <hash>

Josh says:

$ git reset –hard HEAD^n
where n is the number of commits to remove from the branch.

Comments are closed.

et cetera
%d bloggers like this: