Set the revision of your svn:externals (or else!)

Posted on Tuesday 21 October 2008

There is a very cool Subversion feature called svn:externals (or External Definitions), which is a very powerful feature that allows several projects to reuse common code.  However, this can be a very dangerous feature, if you’re not careful… but we’ll get to that.

The svn:externals feature allows you to create a working copy consisting of multiple working copies from several repositories (or several locations within the same repository).  Basically, it allows you to create something like a “symbolic link” (or “shortcut” in Windows).  The end result is that a sub-folder in your working copy is actually in a different repository (or repository location) than it’s parent folder — you’ve effectively “mounted” a different repository location as the sub-folder in your working copy.

The way that you do this is to set the “svn:externals” property in the parent folder.  This tells the Subversion client (such as TortoiseSVN) to treat the sub-folder as part of the working copy.

This is a very powerful feature that allows several projects to reuse common code.  That sounds great, but there’s a big problem:

When you create a tag in subversion (such as when you create a release of your product), you’re not tagging the svn:externals repository — you’re tagging your working copy, which references the svn:externals repository.

So, if your svn:externals property does not specify the revision of the svn:externals repository, it will always float to the latest version when you do an update, including when you checkout or do updates on working copies of tags!  In other words:

If you do a checkout of a tag, any svn:external sub-folders (without revision information) will update to the latest revision and not the latest revision at the time you created the tag!  This means that you probably don’t have an exact copy of the code that you tagged.

The solution is to explicitly set the revision of the svn:externals property.  For example, instead of setting the property as the following:

toolkit http://svn.red-bean.com/repos/skin-maker

We should explicitly set the revision, like the following (note the “-r 21″ argument):

toolkit -r 21 http://svn.red-bean.com/repos/skin-maker

Allowing an svn:external to float to the latest revision may be is desirable for working in the trunk (when we’re working towards a release), however this is certainly not desirable in a tag (when we want a permanent record of what we released).  There is really only one correct way to address this issue (that I can think of):

Make sure that your trunk specifies the revision of svn:externals before you create a tag.  You can always unset the svn:externals revision in the trunk, after you create the tag.

Now, you might want to let svn:externals float to the latest revision when you’re doing development on the trunk, but this requires that you are diligent about setting the revision of svn:externals, before you create your tag.  This is manual work (unless you have a script that does it for you) and might not get done by lazy developers (and we’re all a little lazy, aren’t we?).

How do we fix this problem, if we’ve have already created a tag that doesn’t specify svn:externals revisions?  Easy: you can go into the tag and look at the log to determine the svn:externals revision at the time the tag was created.  Then, set the svn:externals revision in the tag.  However, this is considered “cheating”, since you’re not really supposed to commit changes to tags — that’s what branches are for.  However, it’s a necessary fix for a bad tag.

On a side note, I wonder why TortoiseSVN or the command-line svn client don’t have a feature to automatically set the revisions of svn:externals during a tag operation — and, at least they could warn you if you try to create a tag that has svn:externals that don’t have revisions set.

Using Subversion in LabVIEW? The JKI TortoiseSVN Tool for LabVIEW makes it easy by letting you use TortoiseSVN from inside your LabVIEW Projects and VIs.

Subversion and LabVIEW in the Enterprise : If your organization uses LabVIEW and you would like help deploying Subversion in your organization, consider hiring JKI to help get you started. You can contact us via our website.


14 Comments for 'Set the revision of your svn:externals (or else!)'

  1.  
    Leif Suonvieri
    October 28, 2008 | 2:38 am
     

    A common way to handle this is to first create a “release branch” from current trunk state, and in that branch you set all externals to specific revisions, and if that passes all tests you create the tag from the branch.
    This way you dont have to touch the externals in the trunk.

  2.  
    October 28, 2008 | 10:42 am
     

    Hi Leif: Thanks for the pointer. That sounds like a very workable approach.

  3.  
    Gothgod
    January 9, 2009 | 3:36 am
     

    Thanks for the tip! But this should really be handled automatically. What a hassle it is!

  4.  
    nk
    April 24, 2009 | 6:35 am
     

    Yep that is how we do it also at my workplace. It makes tagging a bit tedious but it is definitely worth it.
    Someday I’ll probably grow tired of it and try scripting it… Unless the fine folks at TortoiseSVN handle it somehow ^^

  5.  
    Rick B
    January 14, 2010 | 6:39 pm
     

    Jim, in our case, we constantly have stuff going on in the re-use trunk(s), so when a project developer (non reuse area) starts a new proj, they get the latest sanctioned externals def from the sample project area. This will have explicit versions for those portions of the reuse that are under development, and floating (HEAD) for those areas deemed working. Then they just use that def in their project.

    But on a more troubling note, I did notice doing an update to a folder in the working copy that has a designated revision on the externals def WILL UPDATE TO THE HEAD REVISION if not updated globally from the root.

  6.  
    January 14, 2010 | 7:40 pm
     

    Hi Rick, that bug sounds like a real pain, especially since users can’t really tell whether they are looking at a folder in Windows that is an SVN external of the parent folder. Do you put some file in that parent folder that says something like “DO NOT SVN UPDATE CHILD FOLDERS”?

  7.  
    Pedro Pereira
    February 24, 2010 | 7:27 am
     

    is this “fixed” already? is there any new features on subversion that tags the externals?

  8.  
    February 24, 2010 | 10:48 am
     

    Pedro, I have no idea if this is “fixed”, yet.

  9.  
    Vlad
    March 1, 2010 | 4:19 am
     

    >Make sure that your trunk specifies the revision of svn:externals
    >before you create a tag. You >can always unset the
    >svn:externals revision in the trunk, after you create the tag.

    I can propose the following solution:

    1. Check out branch or trunk which should be tagged.
    2. Freeze revisions of all externals in the working copy by editing svn:externals property on the working copy.
    3. Use `svn copy` to copy the working copy to a new tag location in the repository.

    This way the tag will contain the exact copy of the code with freezed externals revisions.
    On the other hand, you don’t have to set and unset properties in the repository, which may be highly undesirable epsecially if we consider trunk with many developers working on it.

  10.  
    July 18, 2010 | 10:37 pm
     

    We’re facing exact problem, we have like 10-14 external repositories linked per project and its a pain in a** to tag each and every repo manually.

    I am starting to write a Phing (ANT of PHP) task to do this automatically if anyone has not done this before?

  11.  
    Byron
    November 19, 2010 | 8:04 am
     

    Ugh…just ran into this myself with over 300 revs that have unset external revs. Its enough to make me want to look for alternatives to SVN. Anyone using GIT and successfully implementing a parallel to externals?

  12.  
    John Gauthier
    January 24, 2011 | 1:01 pm
     

    We have the same problem with externals. It seems like a common problem that someone would have solved already. A custom TAG command or option on the existing TAG command would be ideal to automatically add or replace a revision number on the external statement.

    If anyone has one of these, I’d be interested in it.

  13.  
    Uwe Frenz
    February 9, 2011 | 4:40 am
     

    Jim,

    I had asked a related Q on stackoverflow and got an answer to use symbolic links to shared code. So to include /user.lib/ into /myproject/, one could create a symbolic link ‘mounting’ user.lib into myproject. This should solve the issue AFAIU (…understood). See here:
    http://stackoverflow.com/questions/4897957/svn-library-folders-outside-project-tree-can-this-be-handled-with-externals

  14.  
    olivier
    February 9, 2011 | 2:37 pm
     

    Hi,
    I am trying to find a solution to this issue.
    I found this thread : http://subversion.tigris.org/issues/show_bug.cgi?id=1258 which seems to answer !

Leave a comment

(required)

(required)


Information for comment users
Line and paragraph breaks are implemented automatically. Your e-mail address is never displayed. Please consider what you're posting.

Use the buttons below to customise your comment.


RSS feed for comments on this post |

 

Bad Behavior has blocked 1787 access attempts in the last 7 days.