26

I am migrating a client's SourceSafe repository (3 projects) to SVN and two of the projects share source files. (These projects are separate products - with different names and release versions, etc)

Has SVN resolved this shortcoming? How do people generally handle this scenario?

Of the options I know about/can think of

  • Use the external or extern or whatever for SVN. I hear this is not a good option for various reasons

  • Create a new project (maybe called shared) that contains the source. The problem with this is that we still have to get that code (it is not a library) and import it into the project somehow. It can be shown to be the same problem as the one above and it introduces the overhead of an additional product/project.

  • Just check in the files in both repositories and cross-update them. This requires developers to know about the sharing and to remember to check in. I suppose I could write a script that checks all known shared files and updates them when needed.

  • Have one repository for the two projects that share. This leaves me with the problem having to create a top level project/repository that contains the two and it is a problem for labeling. I do not really want to label the top pseudo project. (the tags, trunk and branch things are not exactly where I would want them.)

I will probably go with the last option.

Any other comments?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 3
    I'm curious as to what you consider the shortcomings of svn:externals to be. I make heavy use of them without problem. – Gavin M. Roy Sep 25 '08 at 19:20
  • 1
    I've been doing SVN research here on Stackoverflow for several hours. Many bitch about svn:externals, but nobody gives explicit examples or resources of its shortcomings. :-( – Clint Pachl Feb 03 '11 at 00:22
  • 4
    @ClintPachl The biggest issue with externals is that people often leave them "floating" so that they automatically get updates. This poses a problem when you want to tag for a release though. Simply copying `trunk/` to `tags/release-number` isn't enough. You're external is still floating. You have to go back and peg them at releases. Things get worse when the project you're pulling in also has externals, and chooses not to peg them. It makes for a pretty large CM headache as a result. If you're going to use them, peg them (preferably to something stable), and update them periodically. – John Szakmeister Apr 19 '13 at 08:44

8 Answers8

9

I don't know what exactly you heard about svn:externals, but I think that's what you should use here. You can even specify your external to point to a stable branch or release tag of you shared source, or even point to two different tags from the two other projects that use it (you might need this if you fix some bug in the shared code ASAP for project A, but you don't have enough time to test it fully with project B).

The worst thing you could do is your option 3 (cross-updating two versions of the same files).

mitchnull
  • 6,161
  • 2
  • 31
  • 23
  • 2
    i believe `svn:externals` can only reference folders; not files. And the only way to reference that folder is to create a ***third(!!)*** project, that contains just the shared file. – Ian Boyd Aug 15 '12 at 11:12
  • FWIW, Subversion included the ability to have file externals in 1.6. It doesn't even require the server to be at 1.6 or better, only the client. – John Szakmeister Apr 19 '13 at 08:39
  • @jszakmeister File externals doesn't work across repositories, unfortunately. See also comments under question at http://stackoverflow.com/questions/1355956/can-we-set-a-single-file-as-external-in-subversion – Elise van Looij Jan 28 '16 at 13:07
  • @IanBoyd Creating a new project is not the only way for externals to work. Just create a folder within a project and move the relevant files there. If it's not your own code then you'll end up with more files than you need, but you don't need to reference what you don't need. And perhaps the owner is willing to adjust the layout. – Elise van Looij Jan 28 '16 at 13:12
6

The safe way to do it is to have a third project that builds the shared source into a library that is used by the other two. The library project has it's own SVN repository.

You can even do this with shared files that are just headers, simply leave them in the lib project directory and add it to the list of includes.

Having the same file in two projects, even with soruce control is asking for trouble sooner or later!

Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
5

Just in case if someone googled this question and wonder how would you introduce external resources with TortoiseSVN then documentation is here:

Include a common sub-project

External Items

igor
  • 5,351
  • 2
  • 26
  • 22
2

Use one repository, of course. There might be more shared code later on.

What exactly is the problem with tagging? So you have an extra folder in the tag, but it doesn't cost you space. If you really don't want that extra folder, here's an idea for organizing the tree:

  • /
    • trunk
      • prj1
      • prj2
      • shared
    • tags
      • tag1
        • prj1
        • shared

That is, when you want to tag prj1, you create tag1, then copy prj1 and shared into it.

Lev
  • 6,487
  • 6
  • 28
  • 29
1

In my experience it is problematic to have two independent projects referencing the same source files because i may add or change code in the shared file to meet the needs of one project only to break the other build.

It seems that the trick here is to allow each project to advance independently, so however you set up your repositories you want to stabilize the shared code such that it only changes when you want it to.

For example, if the shared code lives in two branches/folders of the same repository or if it is checked seperately into two distinct repositories, or if it lives in a third repository all by itself, you want the step of upgrading that piece of code to be a manual one that does not have side effects, that you can isolate, debug, and bugfix against.

I have factored this code out into a third repository and then i periodically migrate that code into my dependent project repositories as internal release and upgrade steps; My individual projects then have a revision that looks like "Upgraded to v4.3.345 of Shared.App.dll" which includes all changes needed to work against that version.

If the shared code is part of the same repository as the two dependent projects, then have a separate copy of it in each project and use repository merges to propagate your changes.

David Alpert
  • 3,161
  • 1
  • 23
  • 19
1

You don't mention what language or build tool you are using, but for Java projects, Maven may be worth looking into. One of features is that is essentially extends ant to allow you to pull in external dependencies. That relieves one of your concerns about having to create, maintain and label a meta-project. It also allows you to either pull from HEAD of the external project, or pull from a given tag, which relieves one of the concerns by a previous poster about sharing common files between projects and inadvertently causing breakage, because you can control when each project uses a newer version of the shared files independently.

ramanman
  • 863
  • 4
  • 7
0

Using a trigger to update the files sounds like a bad idea. Somehow they are going to get out of sync. Really the solution with shared code is to extract it into a library and use that library in multiple solutions. That sounds to be outside of the scope of your project, though, so the last solution is your best bet.

stimms
  • 42,945
  • 30
  • 96
  • 149
0

Have one repository for the two projects that share. This leaves me with the problem having to create a top level project/repository that contains the two and it is a problem for labeling. I do not really want to label the top pseudo project. (the tags, trunk and branch things are not exactly where I would want them.)

Like others, I would surely do it the last way. What do you feel is wrong with having 'just' one repository? Repository is about admin rights. Other than that, I would see a single repo have any N number of projects in it.

akauppi
  • 17,018
  • 15
  • 95
  • 120
  • 1
    The problem with one repository (the uber repository) is the dependencies among the projects. Before long you would need to update / download the entire repository in order to work on one project. – mcdon Feb 18 '10 at 20:05
  • 1
    @mcdon - this is not true. In SVN, you can check out specific paths in a repository. With a sane repository structure, you can independently checkout each project. – Clint Pachl Feb 03 '11 at 00:30
  • 1
    @Clint - you can do a partial checkout of a tree no problem. The issue is a checkout of the project and it's shared dependencies. Given UberProject/trunk/AppA/, UberProject/trunk/Shared/, UberProject/trunk/AppB/, at which directory do you branch and tag? References from AppA and AppB to Shared/ will likely be relative paths to Shared/ (../Shared/MyClass.cs). You will branch and tag at the trunk to maintain paths to Shared/. Add more shared projects and dependant apps and this sane repository structure quickly becomes insane. – mcdon Feb 03 '11 at 20:53
  • 1
    @mcdon - with your example tree, I think it could be accomplished using sparse directories. I wouldn't hard code paths in code that are dependent on the repository. Instead, I use svn:externals (with reference to specific revision) to place the shared code exactly where I need it within each dependent project. Branching each project brings with it the specific branch of shared code. Then svn:externals in each project is updated after successful compatibility testing. I use relative URLs with a repository tree like: repo/shared, repo/projects/, repo/projects/{a,b}/trunk – Clint Pachl Feb 05 '11 at 08:36