开发者

SVN and code shared between several projects

I have multiple projects in SVN. Each of these project sits in it's own trunk and branched for releases.

And there is a shared code which is used in each project. The question is what is the best way to handle the code.

Let me give couple of scenarios and the issues related to them

a) Put the shared code in separate trunk (or repository) and use svn:external.

In the case if we branched some of projects, there will be two problems:

  • Any modification of shared code which are made in trunk will be propagated to branch, because svn:external will pick up the changes
  • In the case if we will need at some moment go back and build exactly the code which was build for release, it will be hard for us to get exact code, because snv:external will again pick up latest copy of shared code, instead of code at the moment when project was brached.

As I understand there is one work around. As soon as we branch, we can modify svn:external to pick up exact revision of shared code. However, there are again two pitfalls:

  • You need remember to do this each time when you branch. (I hate such things, which is easy to forget).
  • You can't modify shared code, if you need to do a hotfix for the branched/released project.

b) Another solution is to branch shared code when the project is branched and change external to point to bracnhed copy of shared code.

  • Again, one of the problem is manual step, which is easy to forget
  • Another problem is merge problems. SVN will skip externals when you will try to merge changes in the project to the trunk. So, again, developer needs to remember to merge shared code manually.开发者_StackOverflow社区

Am I missing anything? Is there any reasonable way to handle this?


Personally i keep a separate repository then use the [http://svnbook.red-bean.com/en/1.0/ch07s03.html svn:externals] attribute.

SVN Externals allow for you to link to other repositories (even ones you dont run e.g. the smarty subversion repo) when you run an svn update both your project and the external repo will be updated.

with SVN externals you can also link to specific revisions using somethign like http://path-to-project.com/svn/thing -r1234 for releases and other things that you need to keep static

Best practice IMHO is to always specify a revision then update the revision number as you make changes to the shared library so that you can keep track of WHY you updated this data. also keeps everything sane when you tag or branch the main project.


You have two correct answers, with two sets of drawbacks.
Here's what I would recommend

Put your shared code into another repository, tag the code with the release version Create an svn externals in your trunk directory that points to your tag.

When you change your library, retag it, and update your trunk application. When you take a branch, your branch will still point to the correct tagged version of your library.

Alternatively try building a separate release of your library, and reference the library as a jar or lib/so.


We use a system similar to CWT's: Shared code tend to be separate projects in their own right, and as such exist separately in the repository (or a separate repository). Within the project that uses the external projects (the upstream project), we include the compiled/packaged binaries for the shared/downstream project.

This way the upstream project won't be sniped by unexpected changes in downstream projects.

We've written some scripts to automatically update the major upstream projects with newer versions of these binaries when necessary (otherwise it's a manual process to copy the package into the appropriate projects, but that's not that big of a deal anyway).

The drawback we've see so far in this madnes^W method is that downstream projects undergoing very active development (say, in the early stages of a new library) require what may seem like an excessive number of updates to the upstream project. Testing the upstream project can require updating the shared lib, compiling, copying that binary upstream, and the compiling/deploying/whatever the upstream project. However, once an initial frenzy of development on a library slows and the lib becomes somewhat stable, this "problem" evaporates.

As with CWT, the upstream project can't modify the shared code in any meaningful way. Changes downstream must be made within that project explicitly, and propagated upstream where necessary.


We use a single repository structure like this:

/trunk/project1
/trunk/classlibrary (shared code)
/trunk/project2

In C# (which may not be your language of choice), project1 and project2 include a reference to classlibrary. When we build (here's a great advantage of the compiled .NET model), any inconsistencies between the project being built and class_library are found. These inconsistencies are resolved before committing changes. Using a server-based build tool (we use CruiseControl.NET) we can build all of the projects simultaneously which will tell us of any problems.

Unless your project1 and project2 need to reference a specific version of classlibrary (which we avoid, trying to make project1 and project2 always use the latest rev of class_library), this works incredibly smoothly.

I tend to avoid making separate repositories for related applications. Since the class_library in the above example ties all of these things together, there is little advantage or logic in maintaining it in separate versions since the real reason that it is separated at the project level is that it is shared code. Production apps that share code do so for a reason - they should be using the same version of the shared code, which implies that they should be part of the same source control branch.


My recommendation for handling shared code (particularly with Java and .NET or a C/C++ library) is to use two sets of repositories: one for source code, and another for versioning released images. When you make changes to the 'common' project, you commit your source changes to the source tree, then build it and then publish the binaries by committing them as a new revision on the release tree. The projects that use the 'common' project then use the svn:externals property to bring in the released binaries. There's no temptation to modify the local images of the shared code. If someone wants to modify the 'common' code, then they do that through the normal development practices for that project.

For more details, see this answer to a similar question.


The answer that's missing from your list is:

c) Always point externals to a specific version of the shared code.

This works remarkably well:

  1. You can always pull down a specific version of your project and guarantee the build.
  2. Branching and tagging is an operation on the project path alone.
  3. Updates to the shared code can be made for 1 project, but the second project won't pick them up until it's ready to.
  4. When the second project does pick up the changes, you get an event recorded in your trunk saying that it was picked up and why.
  5. You get the opportunity for releasing a specific version of the library with specific features for a project. This can get you out of holes if a project isn't ready for an API change but needs certain bug-fixes, etc.

If required, libraries can be checked out in a separate working copy and modified alongside your main project. If the project is temporarily changed to pick up code from the working copy on disk, you can then still work on libraries and projects in parallel, if needed.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜