tags:

views:

663

answers:

4

I am about to establish a rule at work here that all svn:externals references should come from the one of the other project's tag, never from its trunk or from any of its branches. Is this a reasonable rule or do you see problems / issues with this approach? I am trying to achieve a stable development environment and I wonder if this rule would make development slower or more difficult.

+2  A: 

I think it comes down to how mature your software development practices are. Do you have change-management processes? Automated builds and reporting? Etc. The safest thing to do is to link to a tagged-build of the project (i.e. lib's, dll's, jar's, etc).

If the external project has weekly releases with frequent bug fixes, it could be both helpful and a hinderance. I found that without a good configuration management policy, linking to tags make it easy to miss critical updates. And, by the time you get around to "upgrading" that dependency, there may be a lot of small changes that add up to a lot of work.

On relatively stable projects, this is a good idea. The only problem is that not all IDE's make it clear that a source directory is an external refernce. In that case, it becomes very easy for developers to check-in changes to that tag. From what I recall, Subversion hasn't implemented "read only" yet, though I've been using an older version.

James Schek
You are correct about the "read only" rule for tags - TortoiseSVN gives you a warning about checking in to a tag, but others such as AhnkSVN (integrated with Visual Studio) doesn't. This can really be a problem.
Otávio Décio
+2  A: 

And the decision to actually allow externals? Makes sure you're doing it for the right reasons. It is often better to simply checkout from the original place and or, checkin the dependencies in multiple places. I've been burnt by external references in the past. If you're going to branch they become a real problem unless you "freeze" the external when you do.

But to answer your question, it makes a lot of sense to have a specific location where all externals are placed and referenced. That means that you can control the content of that location and people know that when they put something there then it will be used as an external and thus depended on by a lot of projects.

Michael Wiles
In your view what would be the right reasons for using externals? My main reason here has been for reuse purposes - making reference to common projects. Or should we use published dll's for that?
Otávio Décio
I was burnt so badly with externals that I would never use them (I'm the wrong person to ask).The only contexts that I would consider allowing externals are when I am never going to branch/tag, or when I have tools to automatically freeze the externals when I do branch/tag or, if I have a very large collection of **never** changing library type code that is required by many projects, but even with these conditions I would still need convincing.But let me say, there may be situations that I have not encountered that do merit externals (especially with svn 1.6 supporting file externals)
Michael Wiles
Don't know if this helps, but I've been using the svncopy.pl to branch/tag and it updates the external references with the appropriate repository version number, but it is flaky - you can't have spaces in your path.
Otávio Décio
No spaces in the path is a small price to pay for being able to freeze externals. It's not the first time that spaces in pathnames have been a problem!
Michael Wiles
+4  A: 

Your concern is that a project with "svn:externals" can change without any commits to that project. That's a problem because it's hard to discover the breaking change or to roll back to a good version.

So yes, demanding that svn:external references are stable is a good rule. Only allowing references to tags is one way to achieve that. Another way is to use the -r syntax to pin the external to a fixed revision. Example from the subversion book:

third-party/skins -r148 http://svn.example.com/skinproj

This will also protect you against changes in tags, a bad practice which is more common than I like.

That being said, there still is a trade-off between stability and continuous integration. Often you need the changes and bug-fixes in the external dependencies anyway. In that case you want to be notified by your CI server as quickly as possible that some change in the dependencies broke your project, so that the problem can be fixed ASAP. Most continuous integration servers have support for checking externals.

For this reason I think it's OK to keep the externals in trunk tracking the trunk HEAD of your dependencies (if you have a CI server). Just pin your externals to fixed revisions when tagging and when creating stable maintenance branches.

Wim Coenen
That makes sense - so the trunk would be allowed to make external references to other trunks, and it would be a more unstable environment, which is ok since this is active development anyway and any breaking changes should show up in compilation or unit tests
Otávio Décio
+2  A: 

It depends how stable you consider trunk to be.

  1. If your trunk is something that's always ready for release, then you really don't want your externals pointing to trunk.
  2. If you have release branches that are only changed by merging in revisions from trunk, then you really don't want your externals pointing to trunk.
  3. If for any reason you want a revision in trunk that says "I'm now using this version of this external", thus taking control of all changes to your project code, then you don't want your externals pointing to trunk.

However, it's fine for a developer to switch the working copies of their externals to a trunk. It's also fine to point to trunk within a development branch. It may be ok to point to trunk before the first stable release of a project.

My personal take is to treat trunk very carefully as it has a special meaning to me - it's the complete history of the project. Anything that gets released must go through trunk, by definition. If you can change trunk without having a revision recorded against the change (which is effectively what happens if you point to an external to trunk), you've lost control over when you release that revision, and when you incorporate that revision into your project.

Remembering to change all your references to specific revisions when you branch from trunk can be a trial. Hudson can make things more visible with its tagging support, but little else helps.

Pointing to trunk can also lead to the "untouchable library" problem.

When it comes to CI, there's no reason why you can't do CI on all the components as well as the final integrated projects. By choosing when to merge in the latest library, you choose when you want to do the integration work.

However, it would be nice to have some mechanism which says "Your project is using an out of date library, the latest version is X". This is not possible at the moment.

Also, if you have nested externals, pushing a change from a base library through 5 layers of references until it reaches the main project is a pain.

Jim T
Thanks, this is good advice. Question - if everything that gets released goes throught the trunk, that must include changes made to release tags as well through merging back to the trunk, correct?
Otávio Décio
I'd say conceptually I see the flow going from [optional]dev branches -> trunk -> Release branches. I wouldn't merge from a release branch to trunk coz changes aren't made to release branches directly. Now in practice, sometimes you have to do it the other way around, and fake out the merge history. However, that workflow lets you do this: http://stackoverflow.com/questions/1082699/1082881#1082881
Jim T