We have a couple of Zend_Framework applications that we'd like to keep in separate subversion repositories. However, these applications share the same database abstraction layer, and several of the same common components.
We'd like to share the common bits between the apps somehow. The current idea we have looks like
svn://foo/itg-common/trunk
svn://foo/itg-common/branches/foo
svn://foo/itg-common/branches/production
svn://foo/itg-app/trunk
svn://foo/itg-app/branches/foo
svn://foo/itg-app/branches/production
Now, we'd like the itg-app repository to have an externals reference to the itg-common repository. The problem is we want e.g. itg-app/trunk/common
to be linked to itg-common/trunk
, itg-app/branches/foo/common
to be linked to itg-common/branches/foo
, etc. That is, the general pattern is itg-app/$BRANCH/common -> itg-common/$BRANCH
.
Now, in principle we could create these externals, but problems arise whenever we would try to merge. E.g. merging from $/trunk
to $/branches/production
would overwrite the svn:externals
property to make $/branches/production/common
to point to itg-common/trunk
.
Does this make sense? If it does, is there some way around this problem? If it does not, why not, and what should we do instead?
As prodigitalson said already, an external in SVN basically is considered a totally different piece of software, with its own release cycles, branches, tags, etc. According to this model, you should not have unpinned externals into some trunk at all, but have them all pinned to either a tag or a revision. That's a pretty restricted model of using code from external sources, but that's what SVN supports. Stray from this, and you are on your own. (See below for my personal war story about that.)
Another thing I would reconsider if I was you is referring to a different repository. IME referring to an external relatively to the current project or repository root is much better than using absolute paths. Just consider the possibility that you might ever change the protocol from
svn:
to, say,https:
. (I have seen this happening to a company, and despite heavily relying on scripting to change all the externals, this transition was a mess everyone involved keeps having nightmares about.) Relative paths to externals simply are more robust, but they are only available within a single repository.The company I am working for has just faced a similar problem. We have a lot of code that is shared between different products. This is done via externals, and those externally referenced projects have externals themselves. At some spots we're down to three layers of recursive externals, and we already know that there will be more in the future. All that code is worked on constantly, and we like to let externals reference the trunk of the projects they refer to, because automatic testing takes the edge off that, and managing releases of all those recursive externals would require efforts we simply cannot afford.
But branching a project in this setting is a real pain in the, erm, neck, because it's not enough to pin a project's externals, when those themselves then refer to unpinned externals. Whenever you need to branch project
foo
tofoo'
, which, via an external, refers to projectX
, which in turn, via an external, refers to projectXX
, you would need anfoo'
branch ofXX
which is an external in anfoo'
branch ofX
, which is an external offoo'
itself. Imagine half a dozen externals infoo
, half of which have their own externals, some recursing three or even more layers, and you reach the point where projectXXX
is littered with branches created for projects it shouldn't even know about.Our solution is to recursively either A) replace all externals with a branch of what they referred to or B) setup a branch of external
X
infoo/branches/externals/foo'/X
that's referenced by<project>/branches/foo'
(withfoo/branches/externals/foo'/X
itself referring tofoo/branches/externals/foo'/XX
). However, setting this up when creatingfoo'
is impossibly complex and offers more than enough chances for making silly mistakes, so we employ scripting to recursively descent the project and its externals and do all that.