All Unkept
Posted in: Python, Software development, Django  —  July 31, 2008 at 09:51 PM

Managing Django patches using Mercurial

by Luke Plant

Update: this is probably superseded by: http://code.djangoproject.com/wiki/MercurialBranches.


For any slightly longlived Django patch, for instance if I want to work on something in stages before committing, or if it might never be committed to trunk, here is the pattern I started using today:

Setup §

Do this once:

In a subversion checkout:

$ hg init
$ cat > .hgignore
\.svn/
\.hgignore$
\.pyc
~$
^D

(^D == Control-D, EOF)

$ hg ci -Am "Initializing from subversion checkout"
$ hg qinit -c

NB: make sure you do 'hg qinit -c'. Your patches live in .hg/patches, and this command makes that directory into a Mercurial repository, so all your changes to the patches are versioned. You have to remember to do hg qcommit after hg qrefresh.

Usage §

Commit all work to mercurial queues, not to mercurial directly.

New patch:

$ hg qnew name_of_patch

(Hack away, using hg diff etc. to see changes)

Commit changes to the current patch:

$ hg qrefresh && hg qcommit

Pull in new subversion changes:

$ hg qpop -a
$ svn update
$ hg addremove -s 75
$ hg commit -m upstream
$ hg qpush -a

(Of course, you could put that lot in a little script)

Once done, commit to subversion, and delete patches:

$ svn commit
$ hg qdel -r qbase:qtip
$ hg qcommit -m "Pushed patches upstream"

(Your patches are still there, of course, in the mercurial repository in .hg/patches, should you need the history)

Evaluation §

I'm not yet sure if this is the best way to do this (see the other methods on the Mercurial Working with Subversion page), but it is a lot better than Subversion on its own, and it isn't too complicated.

One advantage of the system is that it is very easy to ignore it or use it as required. Most of my Django work I will just hack directly and commit. If I realise part way through that it is going to take I while, or that I'm doing two sets of changes that I want to split up, hg qrecord is just the ticket -- interactively record changes to a new patch. If I then need to work on something else, I can just do hg qnew, doing hg qpop first if necessary/desired.

It is quite nice that the patches are just simple files in .hg/patches -- you can just go and look at them with normal tools etc. If your patch has got messy (i.e. accidental whitespace changes), you can just hg qpop it, fix it up manually, hg qcommit and hg qpush it again.

One of the downsides is that patches are managed as a stack -- if you want to add a new patch, you have to put in somewhere in the series of patches (not necessarily at the 'top' i.e. most recent end, but you do need to think about where to insert it). I imagine things can get tricky if you put it in the wrong order initially, though you could always just delete it and put it somewhere else. As long as you have versioned everything, you can get at it easily.

On the other hand, given that your patches directory is a full hg repository, I imagine you can actually do very powerful things -- you can branch your patches etc. very easily. I've discovered recently that Mercurial branching is actually very powerful -- you don't have to create clones, you can do everything inside one working directory.

Anyway, hope that is useful to someone else.

Comments §

blog comments powered by Disqus