This is an old revision of the document!
Note: The first part of this page aims to explain the conventions behind Subversion repository organisation, and use various simplified repository structures to explain this. The recommended repository layout can be found at the end of this page.
In CVS, branches and tags are first class entities – CVS contains several commands for manipulating these. Subversion does not. Instead, Subversion's support for cheap file/directory copies within the repository is used to support the notions of tagging and branching.
A number of conventions have developed to support this. These conventions are not enforced by any of the base Subversion tools, but they can be enforced by pre-commit hooks in the repository (if it is felt that these decisions need to be programmatically enforced).
$REPO and commits
Subversion repositories are referred to with URLs. In the examples that follow, $REPO is assumed to refer to the root URL for the given repository.
Any Subversion command that specifies the full URL operates against the repository, which often means a simultaneous commit. Commands that just specify local files or directories in the working copy change the working copy, but they must be explicitly committed.
For example, this example copies one file to another in the repository – the data in the file does not need to travel to the client, so the operation is quite quick, as it happens entirely on the repository host.
% svn copy $REPO/file1 $REPO/file2
The user is then prompted for the commit message for this commit (or it can be specified with a -m option on the command line) and the commit completes.
Alternatively, the user could do this:
% svn checkout $REPO/file1
% svn copy file1 file2
% svn commit file2}}}
As you can see, that process takes more commands, and involves transferring the file data to the client.
== trunk/, tags/, and branches/ ==
This is the most pervasive convention. Code that corresponds to CVS HEAD is placed in the {{{trunk/}}} directory. So in the ordinary course of operation, if a user
When a tag needs to be made a copy is made of {{{trunk/}}} to an appropriately named directory under {{{tags/}}}.
{{{ % svn copy $REPO/trunk $REPO/tags/name-of-tag}}}
There is nothing in Subversion that directly prevents someone from checking out the {{{tags/name-of-tag/}}} directory, and then committing changes. This would appear to violate the spirit of tags, in that they should be immutable. However, CVS supports this operation too (c.f., "sliding a tag"), and an appropriately written {{{pre-commit-hook}}} script that interrogate the commit, and refuse to allow it if the commit includes a directory under {{{tags/}}}, perhaps with some additional checks (e.g., members of the Release Engineering group would be allowed to create/change files under {{{tags/}}}, but no one else).
It follows, therefore, that a branch is just a tag to which people are allowed to commit. And that is exactly how Subversion operates. To create a branch the command is:
{{{ % svn copy $REPO/trunk $REPO/branches/name-of-branch}}}
The user can then check files out from the {{{branches/name-of-branch/}}} directory, and commit as normal.
Since these are just directories in the repository there is nothing inherent that prevents someone from, for example, creating a branch from a tag. For example,
{{{ % svn copy $REPO/tags/name-of-tag $REPO/branches/name-of-branch}}}
== Multi-project repositories ==
There is nothing that enforces the idea that a repository can contain a single project. In fact, it's commonplace not to. A typical multi-project repository layout might look like this:
{{{
$REPO/project1/trunk/...
$REPO/project1/tags/...
$REPO/project1/branches/...
$REPO/project2/trunk/...
$REPO/project2/tags/...
$REPO/project2/branches/...
$REPO/project3/trunk/...
$REPO/project3/tags/...
$REPO/project3/branches/...}}}
That layout is common if branching and tagging operations are normally applied to one project at a time, or if the projects are somewhat independent. For an example of this see the Apache Subversion repository -- http://svn.apache.org/viewvc/. This contains multiple independent projects that branch and tag at different times. If you drill down to the individual projects you'll see per-project {{{trunk/}}}, {{{tags/}}}, and {{{branches/}}} directories.
An alternative layout, more appropriate for multiple projects that are tightly coupled and that normally branch and tag at the same time would be:
{{{
$REPO/trunk/project1/...
$REPO/trunk/project2/...
$REPO/trunk/project3/...
$REPO/tags/project1/...
$REPO/tags/project2/...
$REPO/tags/project3/...
$REPO/branches/project1/...
$REPO/branches/project2/...
$REPO/branches/project3/...}}}
This layout is common if the individual projects are tightly coupled, and tend to be tagged or branched at the same time. A good example of this is the KDE Subversion repository at http://websvn.kde.org/. As you can see, there are top level `trunk/`, `tags/`, and `branches/` directories, and every KDE sub-project sits under there. This allows the KDE team to produce a consistent snapshot of the entire project when they plan a new release.
XXX - nik plans to pick this up later