views:

125

answers:

6

OK, I understand the trunk/tags/branches thingy for a repository with a single project.

Now let's say I have a main project and a number of smaller auxiliary modules/ plugins / tools / scripts etc. During the early stages there's a lot of renaming, reorganization, etc., and some of them die an early death because they go nowhere. It doesn't make sense to me to stick a particular module into the trunk until the organization is pretty stable. (at which point copying to the trunk is "cheap" per the svn design)

Where would be the best place to put small a module (say "FooModule") early in its development process?

  • /branches/development/FooModule ?
  • /development/FooModule ?
  • /sandbox/modules/FooModule ?

does anyone have experience organizing subversion repositories in a similar way? what has worked for you?

A: 

I'm not sure if my organization structure fits your needs but I took a very different approach than the trunk/tags/branches model. Take a look at http://www.mattwrock.com/post/2009/10/10/The-Perfect-Build-Pard-2-Version-Control.aspx for details.

Here is our structure:

/prod
/prod/app1/20090903
/prod/app1/20090917
/prod/app2/20090903
/sandbox
/sandbox/users/mwrock
/staging
/staging/app1
/staging/app2
/trunk
/trunk/libraries
/trunk/desktop
/trunk/docs
/trunk/services
/trunk/sql
/trunk/testing
/trunk/thirdparty
/trunk/web

Here we have the following root folders:

  • Trunk: This holds the latest code revisions suitable for integration into the mainline. There is a single trunk shared by all projects and teams. Developers only have to checkout this single folder and they have everything they need.

    Sandbox: These are personal development areas used for branching long running changes that you want to keep separate from the trunk until they are ready to be merged back to the trunk.

    Staging: This is the final QA/UAT area. The trunk is copied here once development is thought to be stable and ready for final testing. This protects the release from development commited to the trunk by other teams. When a release is in this stage, you do not want unknown commits from someone else entering your code base.

    Prod: This contains production releases. Each application has its own folder under prod and each release has a folder named after the date of its release. The staging branch is copied to these release tags upon deployment and they represent a snapshot of the code at the time of release. The prod area is a historical record of exactly what was released and when.

Matt Wrock
Just a small point for consideration: if you intend your project to be public and trackable through Ohloh, you'd better have most of your stuff spawning from /trunk.
jldupont
A: 

The /branches/dev/FooModule would be the most sensible approach if you really don't want to have it in the trunk from the start IMHO. That's what development branches are for (except that normally that is the other way around, code is copied from the trunk there, then goes back to the trunk eventually).

I would definitely avoid uncommon root pathnames like the two other examples you gave. You will find further considerations in Version Control with Subversion.

RedGlyph
A: 

When I've approached this sort of thing myself I tend to use an entirely separate repository to save cluttering the main repository with unnecessary revisions.

the_mandrill
A: 

I'm a fan of having trunk, tags, branches for each app. In such a design, you can kind of do whatever you want for a sandbox.

app1/
    trunk/
    tags/
    branches/
app2/
    trunk/
    tags/
    branches/
sandbox/
    trunk/
    tags/
    sure_you_could_keep_the_parallelism_up_here_but_is_there_really_any_need/

People will bicker back and forth about the pros and cons of doing it this way or the root level trunk, tags, branches way, but one strong advantage of this way is that merges and checkouts are much less painful.

(A lot of people overlook this structure because they see their projects sharing code between applications. We have some success using svn:externals when such code sharing is necessary. What's really nice about that is that even breaking changes to common libraries will be no problem if you use externals to link to tags, which will freeze the common library at a point when it was known to work.)

David Berger
If the users don't forget to update their svn:externals when they branch/tag their code, that's fine.
Vladimir
@Vladimir If the svn external is set on the trunk of a project and the trunk is copied for the branch/tag, there is no need to update the external; it is copied along. The only time the external needs to be updated is if it is important to be linked to the latest version of another project. This is not usually important unless other projects contain critical shared standards, such as serialization/deserialization routines.
David Berger
+1  A: 

That's a very interesting question because starting right has a lot of benefits (modularization, low-coupling...). Anyway, this is how I would start:

1) put everything into the trunk:

http://svn/application/trunk/application

2) if you can, start early to split the code into modules

http://svn/application/trunk/application1
                             module1
                             module2

3) if a module is stable, move it upstream into its own repository:

http://svn/module1/trunk

4) finally, when you have several stable modules and applications, you could end up with

http://svn/application1/trunk
http://svn/application2/trunk
http://svn/module1/trunk
http://svn/module2/trunk

each application/module having their own release cycle.

Alternatively, you can take a look at what the Spring Framework is doing (very nice organization if you ask me)

http://svn/application1/trunk
http://svn/application2/trunk
http://svn/framework/trunk/module1
http://svn/framework/trunk/module2

I would advise against splitting the code into trunk/branches for each module, at least at the beginning of the project: as soon as you start branching (and not working on the trunk), you cannot work with the HEADS of other modules' trunk anymore: you either have to branch all your projects at the same time or work with specific versions (1.0 and not SNAPSHOT). I don't think I'm very clear but let me know if I have to explain it differently.

Vladimir
A: 

I can't edit David's post but I want to mention something with svn:externals: they are quite dangerous from a release point of view (imo). Here's the nightmare scenario:

Let's imagine that you svn:externals some module code inside your application; for the sake of it, let's imagine that the Subversion revision is 1000 for the module. You create a branch, make a release and ship it to the customer.

Time goes by and a couple of months/years later the customer asks you to fix a problem in the application. You check out the branch and start svn updating the project. Unfortunately, the linked module has changed widely and has now the version 23456. And now the application doesn't even compile any more.

Of course, what you have to do it so change the svm:externals to point the exact version (1000) when you branched. And if you have to change the module's code, than you have to point now to the head of the branch created for the module at the revision 1000.

A lot of unnecessary work, that's why I would strongly discourage the usage of externals for any large project.

If you have had good experience with svn:externals I am all ears.

Vladimir