No PhD

I work for Nature Publishing, but I haven't got a PhD

Mercurial sub-repositories for project dependencies

with 4 comments

With a number of our projects now sharing certain assets (primarily CSS files, images and javascript files) I’ve recently been looking in to a new feature of Mercurial; subrepos. These have been introduced in Mercurial 1.3 and are roughly analogous to externals in Subversion. Having just completed a first stab at using subrepos where we have assets shared between a Java Struts app and a Rails app I thought I’d share the steps in getting things up and running on OS X.


You’ll need the most recent version of Mercurial (v1.3.1 is the latest stable build). I use MacPorts to manage most of my apps on OS X. To install Mercurial with macports simply do:

$ sudo port install mercurial

Running the Mercurial command should return the following output:

$ hg --version
Mercurial Distributed SCM (version 1.3.1)

If not, update your ports install and try again.

Setting up

First we need a couple of repos – lets set them up with Mercurial:

$ hg init css-assets
$ hg init app
$ cd css-assets
$ echo "body { margin: 0 }" > main.css
$ hg add
$ hg commit -m "Initial stylesheet commit"

We now have an assets repository with a stylesheet and an empty app repository.


Now we need to link our css assets project to our app. It’s worth bearing in mind that subrepo support is experimental at this point and may change, but at this time the process is:

  1. Clone the subrepo in to your parent repository.
  2. Write an .hgsub file to identify the subrepo
  3. Commit the parent project to link the subrepo.

So, we must do the following steps:

$ cd app
$ hg clone ../css-assets css
updating working directory
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ echo "css = css" > .hgsub
$ hg add
$ hg ci -m "Committing CSS subrepo"

The subrepo is now linked to the app repo. Committing the app repo has one major side-effect; it creates an .hgsubstate file. This identifies the version of the subrepo you link to. No matter which updates are pushed to the CSS repo by other users, our app repo will be fixed to the version in the .hgsubstate file. You can confirm this easily:

$ cd css-assets
$ hg log

The tip changeset ID of the CSS repo will match the version in the app repo .hgsubstate file. To update the app subrepo we must do the following:

$ cd css-assets
$ echo "p { margin: 5px }" >> main.css
$ hg ci -m "Updated main stylesheet"

This has updated the CSS repo. The app repo will not yet be aware of these changes; if you check the .hgsubstate file in your app repo you’ll see the changeset ID will still be the ID of the initial commit to the CSS repo. To update the version of the CSS you must:

$ cd app/css
$ hg pull -u
$ cd ..
$ hg ci -m "Updating CSS subrepo"

Now check the .hgsubstate file. The changeset ID has been updated to point to the CSS repo tip. Anyone cloning your repo will now get the latest versions.

That pretty much covers everything I’ve uncovered so far. An improvement I’d like to see is the ability to set your .hgsub file to point at a remote repo and for it to handle the initial clone for you rather than manually cloning and configuring (and if it can do this, someone please inform me how – the documentation is still a little thin).


Written by spanx

25th August, 2009 at 4:34 pm

Posted in Code

4 Responses

Subscribe to comments with RSS.

  1. Nice tutorial, thanks. will changes to /app/css be automatically pushed to the /css-asset repository when you push /app?


    16th September, 2009 at 8:03 am

    • Hi David,

      Yes, it appears the subrepos are pushed alongside the parent repo. You can still push subrepos separately though.


      29th September, 2009 at 10:42 am

  2. So another interesting behavior is that if you clone the app directory, make a modification to the css repository inside in that cloned instance, and then push your changes, they will propagate back up to both the app directory *and* to the css-asset repo. So:

    $ hg clone app app-instance
    $ cd app-instance/css
    $ echo "code { font-weight: bold; }" >> main.css
    $ hg ci -m "Emphasize code more."
    $ hg push
    $ cd ../app/css
    $ hg log
    tag: tip

    summary: Emphasize code more
    $ cd ../../css-assets
    $ hg log
    tag: tip

    summary: Emphasize code more

    Note the distinct lack of an hg up in either the app or the app/css repositories.

    This is all with hg v1.4


    23rd November, 2009 at 9:38 pm

    • OK, I am accidentally spreading misinformation. The hg up wouldn’t be necessary to see the changes reflected in the hg log. It *is* relevant and good to know that when you push from app-instance to app, the changes to css will propagate all the way back to css-assets, but I should emphasize again that it *will not auto-update or anything weird like that*.


      23rd November, 2009 at 11:27 pm

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: