When to create a branch in Git?

Upon reflection:

$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 297 commits.

I think maybe I should have created a branch…

7 Comments

Its not too late. Something like branching from origin/master, record the commit hash here. Merge from your local master. Then checkout master and revert it to that recorded commit hash. Of course that last step is destructive, so be VERY careful before you do it.

Also, "git rebase -i " ftw. :)

It's *very* nice to be able to reorganize and squash several related commits to one. Makes the commit history so much easier to manage.

$ git co -b whatever-it-is
$ git update-ref refs/heads/master origin/master

Creates and checks out a new local branch where you are right now, then drops local master back to its last published state.

Git means never having to say you’re sorry.

(update-ref is plumbing and requires the refs/heads/ longhand. You can do roughly the same thing using “git branch -f master origin/master” but it has more potential side effects – naturally, as a porcelain command.)

About moving "master" back to "origin" ...

#  On master branch.
git reset --hard  point-to-move-to

Is git reset --hard any more different than git branch -f ... above?

You can do it that way. If you are more comfortable with it, there is no reason not to use it.

The reason I didn’t suggest is because you can do a lot better than what reset will allow.

First of all, reset alone will lose your place, i.e. the commit you were previously at. If you want to get back to it and don’t want to dig it out of the reflog, you need this sequence:

$ git branch whatever-it-is
$ git reset --hard origin/master
$ git checkout whatever-it-s

First you drop a bookmark wherever you are, then you move the current branch pointer, then you check out the bookmark.

But if you have uncommitted changes in the working tree, they will get thrown away. Then you must funnel them through the stash to prevent that:

$ git stash
$ git branch whatever-it-is
$ git reset --hard origin/master
$ git checkout whatever-it-s
$ git stash pop

Except for the git branch though, all these steps will modify your working tree – for no reason in this case. After all, all you wanted to achieve is to make master something else and give the current lineage a new branch name, but otherwise stay in exactly the same place.

So now you have more than twice as many steps, and they all involve a lot more work. On a repository with a large directory structure and many files (e.g. perl5.git), this can take minutes. The approach I outlined will not touch the working tree whatsoever – nor the index. There is no need to ensure that you preserve any unrelated state, because no unrelated state gets touched. It only updates references. That also is an O(1) manipulation of 3 files and less than 100 bytes so it will be instant no matter the repository – even over NFS in a checkout of the Linux kernel.

But, the less optimal approach is not wrong. If you prefer, you can stick with it and achieve the same.

Aristotle, actually your reply reminded me of the occasional problem that sometimes come with reset --hard and related avoidance procedure. I will change my way of hard reset to reference update. Thank you.

Leave a comment

About Mark Leighton Fisher

user-pic Perl/CPAN user since 1992.