October 13, 2006
svn:externals: just say no

When we set up our Subversion repository, we did it wrong. And by we, I mean me. ;-)

Our application is modular - you can buy one bit, or several, depending on what you want. There's a core module, containing anything that all the other modules can't do without - authentication and authorisation, audit logs, that kind of stuff. Then we have a simple contact management module, a technical accounting module, and so on. (Mostly still to be written.)

Each is a separate web application - a separate WAR file. They communicate via SOAP. (I know, SOAP in this day and age. Still, it was what was required...) And each has its own Java package - uk.co.trisystems.morph.core, uk.co.trisystems.morph.cm, uk.co.trisystems.morph.ta, and so on. But they have a fair amount of code in common, which lives in uk.co.trisystems.morph.common. And that's where we (all right, all right, OK, I) went wrong.

It's not all my fault - I blame VSS. We'd been using it for ages, and in VSS, you do things like this using shared folders. This was our first major project to dump VSS in favour of Subversion, and the closest thing we could find to VSS's shared folders was Subversion's externals. Brain damaged by VSS as I was, that's what we used.

In hindsight, a mistake.

Subversion's externals are really intended not for code shared within your own project, but for genuinely external code - stuff you want to pull in from other projects and so on. Subversion treats externals as 2nd class citizens in a way.

Updating your working copy is not a problem - the usual svn up works fine. But checking your changes back in, that's not so easy. If you've made changes to common code, svn commit leaves them behind. Merging, branching, making patches, just the same - externals are ignored. Fair enough, given what externals are intended for.

It's not so bad for me - bash helps out a lot here. To check all my changes in I do a:

svn st | awk '/^\s?[MAD]/ { print $NF } ' | xargs svn commit -m"Blah blah blah"

(Thanks to Andy for the awk lesson!)

Branching is still a bit of a pain - branching both common and the other apps, and munging the svn:externals property is a fiddle, but I can live with it. But for my Windows-victim colleagues, it's much worse. Padawan Dan has taken to cygwin like a duck to water, but for the rest of the team there's Tortoise.

Tortoise is fine for simple stuff, like updating and looking for conflicts. (Though its conflict resolution doohicky is horrid.) But whenever people try to use it for the slightly more complex jobs such as branching... things just go wrong. And we can never work out what happened. I'm not blaming Tortoise as such - I'm sure that it works fine. But GUIs are just not good for this kind of stuff. You need to be able to work from examples, and with a GUI, it's just too easy to leave some checkbox or other unchecked - and you'll never be able to work out what you did wrong after the fact.

So, what should we have done? Well, I think I know, but this is all a bit suppositional. ;-) What I think we should have done is not to have bothered trying to keep one copy of our common code. Instead, we should have had a copy of the common code in each application, and merged any changes to that common code to the other applications.

Sound right?

Of course, for all this merging, you need good merging tools. But that's another post...

Posted to Software development by Simon Brunning at October 13, 2006 01:07 PM
Post a comment

Email Address:



Remember info?