15

The scene: A purchased web application, with regular updates from the vendor. We then, heavily customize the look and sometimes add our own functionality or fix a bug before the vendor gets to it. For version control, we have been using Subversion following their “Vendor Branch” model each time we received a new release. This has the added benefit that we have a, version controlled, vanilla copy of their system.

The problem: We would like to switch to Mercurial and will likely follow the stable/default branching pattern. Mercurial makes perfect sense if we were to only receive a single release from our vendor and start developing it from there. But, for whatever reason, I am having trouble wrapping my mind around how to handle future releases from the vendor.

The plea: Any help with “vendor branching” Mercurial style would be greatly appreciated.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Nathan Hartley
  • 4,005
  • 2
  • 43
  • 46
  • Found a question with a similar scenario, but for Subversion. (http://stackoverflow.com/questions/2447591) – Nathan Hartley Oct 22 '10 at 15:33
  • 5
    Someone is going to suggest Mercurial Queues (mq) -- ignore them. It's a fine technology for an individual to use when preparing patches but not the right fit for something this central to your process. – Ry4an Brase Oct 22 '10 at 15:56

2 Answers2

14

Using named branches as you've described is a fine choice (though not the only choice), but I'd still suggest using a few separate clones at well known locations to facilitate this process. Pretending that http://host/hg/ is a hgweb (formerly hgwebdir) for your install (though ssh:// works great too, whatever), you'd have something like this:

  • http://host/hg/vendor
  • http://host/hg/custom

Two separate repos where data flow from vendor to custom but never the other direction. The named branch default would be the only one in vendor and in custom you'd have both default and stable.

When you got a new code drop from the vendor you'd unpack it into the working directory of the vendor repo, and then run:

hg addremove
hg commit -m 'new drop from vendor, version number x.x.x'

Your history in that vendor repo will be linear, and it will never have anything you wrote.

Now in your local clone of the custom repo you'd do:

hg update default     # update to the latest head in your default branch
hg pull http://host/hg/vendor   # bring in the new changes from vendor as a new head
hg merge tip          # merge _your_ most recent default cset with their new drop

And then you do the work of merging your local chances on default with their new code drop. When you're happy with the merge (tests pass, etc.) you push from your local clone back to http://host/hg/custom.

That process can be repeated as necessary, provides good separation between your history and theirs', and lets everyone on your team not responsible for accepting new code drops from vendors, to concern themselves only with a normal default/stable setup in a single repo, http://host/hg/custom.

Ry4an Brase
  • 78,112
  • 7
  • 148
  • 169
  • 1
    I think this is the clearest answer I have ever seen. Thank you! +1 – eduncan911 Oct 14 '11 at 15:29
  • 2
    I think deleting all the non .hg* files might be required in the vendor folder before the "hg addremove" so addremove can work properly. – Ken Sep 28 '12 at 20:56
  • @Ken that's most definitely _not_ going to work with what I suggested. The vendor is giving you tarballs w/o .hg files and you're untarring them in a repo where they'll become the next commit. You want to keep the .hg stuff there so that you're layering the new version atop the old ones. If what you're getting from your vendor already has `.hg` and friends in in then you can just pull from them and use normal mercurial tools w/o any need for this answer. This is for the case where vendors give you tarballs to which you have to react. – Ry4an Brase Sep 29 '12 at 01:58
  • 1
    @Ry4an -- I'm not saying to get rid of any of the .hg* files (or the .hg folder) -- just everything else. I think if you don't do this, the remove part of "addremove" won't be able to tell what files have been deleted as part of the new vendor drop. – Ken Sep 30 '12 at 22:16
  • Ah, indeed, you said 'non'. In which agree completely. FWIW this is also how I recommend people import complex code bases. You don't need 20,000 changetsets worth of history from back in the CSV/svn days. You need one for each release you released, and the keep your svn/CSV repo around (read-only!) if someone really wants to play archaeologist. – Ry4an Brase Oct 01 '12 at 01:12
  • The vendor has done a complete re-write of their application and, this time, I have tried your answer. Now I am having trouble with one small thing... It used to be simple doing a diff like the following, but haven't figured out how to do it when the vendor branch is in a separate directory, without using a 3rd party diff utility: hg diff -r vendor – Nathan Hartley Oct 24 '12 at 19:02
9

I would use a vendor branch as an additional branch to the default+stable ones. In the end it would look something like this:

V1----V2-------------V3---------V4     Vendor
 \     \              \          \
  D1----D2---D3--D4-D5-D6-D7-D8---D9   default
                  \           \    \
                   S1----------S2---S3 stable
Rudi
  • 19,366
  • 3
  • 55
  • 77
  • Any suggestions as to where to begin? – Nathan Hartley Oct 22 '10 at 15:31
  • 3
    For an existing project I would start by importing the svn history, and arrange the branches afterwards. For a new project, I would import the first vendor version, and create the vendor branch with this commit (V1). Afterwards I would merge V1 to default, creating D1. After some Hacks in default I would create the stable branch with the first stable version(S1). Whenever a new vendor version comes in, a new commit on the vendor branch is created (V2, V3, V4). These commits get merged to default(D2, D6, D9), and after clean up merged to stable(S2, S3). – Rudi Oct 22 '10 at 16:11
  • Thanks. Great solution. I used Branching with Named Branches (described here http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial/#branching-with-named-branches ) to create branches – Greeso May 16 '14 at 19:32