Skip to content. | Skip to navigation

Personal tools

>>> ''.join(word[:3].lower() for word in 'David Isaac Glick'.split())

‘davisagli’

Navigation

You are here: Home / Blog / Backporting a topic branch with git

Backporting a topic branch with git

by David Glick posted Nov 26, 2011 11:16 AM

As a maintainer of Plone and Dexterity, I frequently find myself with the need to merge a pull request not only to the master branch, but also to a maintenance branch used for bugfix releases to older versions of the software.

When the pull request involves a single commit, it's pretty straightforward: I merge the pull request to master through github's UI, or via the command line with git merge. Then I check out the maintenance branch and use "git cherry-pick" to apply the changeset from the commit relative to the older branch.

But this quickly gets annoying if the branch I'm trying to merge involved multiple commits, and I have to cherry-pick each one in turn. So here's a different approach I used yesterday to backport a changeset from zedr (Rigel di Scala) to add an Italian translation to plone.dexterity.

His pull request was against the master branch, so I first merged that using the github UI.

Then I needed to apply the same change to the 1.x branch of plone.dexterity.

In my local copy of the plone.dexterity repository, I added zedr's fork as a remote, and fetched it.

$ git remote add zedr https://github.com/zedr/plone.dexterity.git
$ git fetch zedr
From https://github.com/zedr/plone.dexterity
 * [new branch]      1.x        -> zedr/1.x
 * [new branch]      davisagli-extend-fsschema -> zedr/davisagli-extend-fsschema
 * [new branch]      jbaumann-locking -> zedr/jbaumann-locking
 * [new branch]      jmehring-drafts -> zedr/jmehring-drafts
 * [new branch]      master     -> zedr/master
 * [new branch]      toutpt-unicode -> zedr/toutpt-unicode

Next I created a new branch called "zedr-merge" specifically for carrying out the merge, based on zedr's forked master branch which contained the change. I needed a temporary branch for this in order to carry out the rebase in the next step.

$ git co -b zedr-merge zedr/master
Branch zedr-merge set up to track remote branch master from zedr.
Switched to a new branch 'zedr-merge'

Now for the fun part. I used rebase to modify the zedr-merge branch's history so that it contains the commits from the 1.x branch, followed by only the existing commits from the zedr-merge branch that I wanted.

$ git rebase -i --onto 1.x a36f40743d67da8e6d5c7b0aee81e786a2de9f5e

Let's break this down. The rebase command will first store all commits on zedr-merge from a36f40743d67da8e6d5c7b0aee81e786a2de9f5e to HEAD in a temporary location (I found this hash using git log to identify the last commit prior to the changes I was trying to backport). Next it resets the history and state of the zedr-merge branch to be equivalent to that of the 1.x branch (because of the "--onto 1.x"). Finally it reapplies the changes that were stored in the temporary location. The end result is that we have exactly the history we want—that is, the 1.x history plus the relevant portion of the zedr/master history—but it is on the zedr-merge branch rather than on 1.x where we want it to end up. We'll deal with that in a moment.

Notice one more thing about the rebase command. I used the -i flag, which means interactive rebase. This means that I'll be prompted in an editor with a list of commits, and can choose to "pick" (include), remove, or "squash" (merge into the prior commit) each commit. In my case, since zedr had a number of commits making small changes to his translation file that were really all part of the same change at the macro level (adding the Italian translation file), I squashed them all together so that I ended up with a single commit at the HEAD of the zedr-merge branch which accomplished the same changes as all of the commits zedr had made on his master branch.

pick 8562549 Added Italian translation
squash d035596 Correct timestamps
squash 9fa9904 Removed template header
squash 4a97700 cancel does not really mean that; fixed (thanks gborelli)
squash aef40f1 messags now coherent with the standard Italian translations found elsewhere
squash 621e185 Updated changelog

# Rebase a36f407..621e185 onto 9408d8d
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.

At this point, since I had a single commit that I cared about on zedr-merge, it was a simple matter to use git cherry-pick to apply it to the 1.x branch instead.

$ git co 1.x
$ git cherry-pick 6dec9429d7994f02e332e22f8009a687ee3944c0

And now git log shows the change all together nicely in one commit:

$ git log 1.x
commit 6dec9429d7994f02e332e22f8009a687ee3944c0
Author: zedr <zedr@zedr.com>
Date:   Mon Nov 21 12:29:32 2011 +0100

 Added Italian translation
 
 Correct timestamps
 
 Removed template header
 
 cancel does not really mean that; fixed (thanks gborelli)
 
 messags now coherent with the standard Italian translations found elsewhere
 
 Updated changelog

This is really the story of my first realization of the power of git rebase. But one word of warning: you should not rebase commits if they have been shared (i.e. by pushing to github) and others may have based further work on them. It can lead to duplicate commits in the history if the derivative branch is later merged as well. In my case this is not a concern, though, since the maintenance branch will never be merged back to master.

I really don't know if this is the best method for my use case, but it at least had the end effect I was going for in this case. I'm still not quite sure what the simplest approach would be if I wanted to end up with all the commits from zedr/master separately in the history of the 1.x branch, instead of squashing them. I'd be interested to hear if other people are using different approaches.

garbas says:
Nov 27, 2011 05:42 AM
since git v1.7.2 you can also provide range of commits to cherry-pick.

git cherry-pick bbbbbbb^..aaaaaaaa
Servilio says:
Jul 04, 2012 01:10 PM
The disadvantage of this method is that there is no automated way to tell what commits of the maintenance branch are also in trunk, as all the commits are different.

From my point of view, the ideal situation would be that zedr worked on a separate branch that then you can merge both to master and maintenance. Second best would be to rebase zedr's branch onto a commit that is a common ancestor of both branches, then merge.

In monotone they call this technique daggy-fix, I strongly recommend reading their wiki page if you haven't already:

http://wiki.monotone.ca/DaggyFixes/
Lebtjflo says:
Sep 07, 2013 08:47 AM
Lots of Buttons, a Hong Kong-based startup that claims <a href=http://www.foampositeshoesbox.com/[…]/a> to be the magic’s largest site give up to selling buttons, has been specified a kind dosage of publicity and money after it won the Startup Arena Singapore 2013 contest held at Tech shopping blog In Asia‘s Startup Asia actuality today.
 
The consequence pitted twenty auspicious startups from across Asia head-to-head, with each pitching to a four-man judging panel. Alongside the US$10,000 prize scratch, Lots of Buttons has also won a stagger to a networking event from Japanese VC Globalbrain, and a stall at top Chinese tech drama GMIC.
 
While the button making space is an unconventional industry to present, since it serves a entirely recess audience, the guests says there is heavy claim since most crafters and designers dearth hands down access to stores — markedly if they live in minute cities — and may not comprise leisure to communicate with and physically read buttons. Putting them online makes them easy to reveal, not to bring up that the new zealand sells them at a evaluate that it claims is 50 percent disgrace than its rivals.
 
The B2B service houses more than 15,000 button designs and is aiming to “sooner regard g belittle every solitary button in the era online so that you can settle upon the exact button you’re looking for”. It uses common networks, including Titter, Facebook and Pinterest, to remedy spread book of its products and is generally a splendidly laid discernible website.
 
Basically focused on the US crafts stock exchange, the company told Tech In Asia that its philosophy is <a href=http://www.jordansretrogethome.com/[…]/a> comprehensible: “Sell in English, ocean cheaper than competitors and be musty to <its>manufacturers] China.”
 
In return at once, it is stinging on raising a round of angel investment with a picture to introducing its own Etsy-like marketplace to depute its users to dispose of buttons to others.
 
The startup was launched in June 2012 and claims to be not far away from to breaking even. Its close proximity to suppliers is key <a href=http://www.49ersprosale.com/[…]/a> to its scanty pricing, under Ken Lee says.
 
Younger Apple arise in the battle went to Xunta, a combination of stock gay app Grindr and Chinese flirting help Momo – which has 16 Ipad case million users and raised a late-model $40 million Series B round. Look visualization situation Pudding rounded in the top three spots.
 
You can find more details of the tournament all about at Tech In Asia.
 
Headline image via Apostolos Mastoris / Shutterstock, statue from Startup Arena Singapore 2013 via Tech In Asia
Navigation