You are viewing gitster

January 13th, 2009


Previous Entry Share Next Entry
02:36 pm - Committing to a different branch

While I was working on preparing a release branch during the day job, a colleague came to me and said he found a buglet.

       o----o----o release branch
      /
     /
----o origin
     \
      \
       o---o my master

I had the release branch checked out, and I took a look at the issue in the release branch.  In a few minutes, we came up with a three-liner fix inside my work tree.

       o----o----o....* (uncommitted changes)
      /          ^ release branch
     /
----o origin
     \
      \
       o---o my master

We shouldn't be committing this to the release branch, as this fix applies to everybody and not just to this particular customer. What is the correct procedure to handle this?

Here is what you would do:

$ git checkout origin

This detaches my HEAD at origin (which is a remote tracking branch, so you cannot check it out directly), taking the uncommitted changes with me.  It lets me pretend as if I started making my uncommitted changes starting from the commit that is at origin.

       o----o----o
      /          ^ release branch
     /
----o....* (uncommitted changes)
     \
      \
       o---o my master

Then, after testing to make sure that the fix applies to the context of the origin branch, I can make a commit, still keeping my HEAD detached:

$ git add as necessary
$ git commit
 

       o----o----o
      /          ^ release branch
     /
----o----o HEAD (quick fix)
     \
      \
       o---o master
Detached HEAD means I am not on any branch.  Why didn't I switch to my master branch instead to create this fix?

This is because there is a reason why my master is still ahead of the origin branch.  These are a handful of more involved commits that are not ready for public consumption; I have been testing them privately.  I do not want to have this quick fix we just made on top of these unproven larger changes.

I want the quick fix first, and then my work-in-progress should come on top of it, so that I can push out only the quick fix for the general public.  To prepare such a history:

$ git rebase HEAD master
 
This will replay the work-in-progress commits that are on my master branches on top of the detached HEAD state (which is the quick fix immediately on top of the origin), and creates a history like this:

       o----o----o
      /          ^ release branch
     /
----o----o (quick fix)
          \
           \
            o---o master
Two remaining tasks are
  1. Push the quick-fix out to the central repository; and
  2. Incorporate the quick-fix to the release.
Here is how:

$ git push origin master~2:master
 
This updates the master branch at the central repository with the third commit from the tip of my master branch (which is the quick-fix commit).

Finally:

$ git checkout release
$ git merge master~2

to merge the quick-fix commit to the release branch (this assumes that my release procedure started from the state where release branch fully contained the tip of origin, which should be the case normally).  That would result in a history of this shape:
       o----o----o----o release branch
      /              /
     /     .--------'
----o----o origin
          \
           \
            o---o master
And we are done!



Tags:

(5 comments | Leave a comment)

Comments:


[User Picture]
From:duncanmak
Date:January 14th, 2009 04:38 pm (UTC)

Why merge and not rebase again?

(Link)
I was following along and thought that you'd end by rebasing master onto the release branch.

Why merge at this point and not rebase (like you did with your master branch)?
[User Picture]
From:gitster
Date:January 14th, 2009 08:04 pm (UTC)

Re: Why merge and not rebase again?

(Link)
I may not have been clear in the description, but the release branch in this case is of "never to be merged back" kind, so it won't make sense to either merge it to my master nor rebase my master onto it. It will contaminate the history of my master branch.
From:deskin.pip.verisignlabs.com
Date:February 3rd, 2009 03:47 am (UTC)

s/~3/~2/ ?

(Link)
Based on the diagrams, it looks like you have two commits on master ahead of your quick fix, and thus would want

$ git push origin master~2:master

and similarly

$ git checkout release
$ git merge master~2

--
Deskin Miller
[User Picture]
From:gitster
Date:February 3rd, 2009 09:10 am (UTC)

Re: s/~3/~2/ ?

(Link)
Yup, you are right. I cannot count.
From:(Anonymous)
Date:April 13th, 2011 07:04 pm (UTC)

Can't wait to get involved

(Link)
Hey - I am really happy to find this. Good job!
gitster's journal - Committing to a different branch

> Recent Entries
> Archive
> Friends
> Profile

Links
Pages at the k.org
Gifts
貢ぎ物
The latest blog by Gitster

> Go to Top
LiveJournal.com