Site Logo

IzzySoft


Das inoffizielle Android-HandbuchDas inoffizielle Android-Handbuch
Buy at Amazon for 16,99 €
Das inoffizielle Android-SystemhandbuchDas inoffizielle Android-Systemhandbuch
Buy at Amazon for 6,99 €
Die besten Android-Apps: Android-Systemtools. Fotografie & Freizeit. Büro-Tools, Schule und StudiumDie besten Android-Apps: Android-Systemtools. Fotografie & Freizeit. Büro-Tools, Schule und Studium
Buy at Amazon for 2,35 €
As of 2023-03-28 04:10
prices & availability might be subject to change.
Software List Documentation Demos Articles

Version control with Subversion: Installation, configuration, and usage. Including installation and configuration of Trac.

Introduction

Subversion is a version control system (VCS) similiar to CVS. Why use another VCS if we already have CVS for so many years? It offers some advantages you might feel worth to think about (find a quick comparision here to find out more. Keep in mind that these comparisions may not reflect the latest development/releases). Just to mention some points I felt important:

Sure SVN has many highlights - but to be fair we should admit it also has its downside:

What's this article about

Reading this article completely, you will learn how to setup a subversion server (and client), configure it, setup and use repositories, and work with subversion. You will find examples and even the one or other script you also can easily download and use with or without (simple) modifications. When you are finished reading (and memorized everything), you should be able to use SVN for your daily work, and even to setup a "sophisticated" server.

Installation and configuration as described here is based on an Ubuntu 6.06 "Dapper Drake" Linux machine, but should be easy to adapt for other Linux distributions. Most of these steps should be also adaptable for Mac users. Sorry for those using some MicroSoft OS - you may have to do some more experiments... But finally, the usage sections should apply to all operating systems the subverion client is available for.

What this article is NOT about

This article is neither a complete reference nor a complete guide or manual. For these things you need to refer to the project's website, see other postings of the SVN manual, or google for the topic.

Table of contents

Software installation

The whole process of course starts with the installation of the software. In all cases, you need the subversion server and client. For Ubuntu, both are provided in a single package called "subversion", and installation is as easy as sudo apt-get install subversion.

For our article, we also want to use WebDav to access our repositories using the http:// protocol. Ubuntu users install "libapache2-svn" for this: sudo apt-get install libapache2-svn. Dependencies will be resolved automatically.

Configuring SVN

Once installed, the software is ready - but still we need to do some configuration. Before we really start with this, some explanation about the final goal:

What we want to achieve

In this article, we are going to setup a somehow "sophisticated" configuration. We are going to be a bit paranoid about write access - so we only want to give write permission using secure protocols. As we are not going to use SSL for this (say we are to lazy for that: We don't want to aquire a valid certificate and deal with the special Apache configuration), we do this using SSH (assuming your machine already has an SSH server installed – sudo apt-get install openssh-server). To avoid the need of creating a system user for every developer, all share the account of the SVN user – don't worry, all operations will still be done in a way you always can see which user did what.

Anonymous users will be granted read-only access (for selected projects) – which will be available also via http://. This way users can browse your latest development code using their favorite browsers, or checkout anonymously from your website to retrieve the latest fixes without your need to do anything additional. No need anymore to release each single fix separately – everybody can grep it right away.

Overhead? Maybe. If you don't need the one or other feature, you are free to simply skip that section.

svnserve

First we need to create an account which then owns all the repositories and does all work concerning subversion. For some administrator(s) to be able to work locally on the machine, having their separate accounts, we also add a separate group. So first become the superuser and stay such during the configuration: sudo - su. Now for our account: adduser --group svn. This will add an user and a group, both named "svn". Make sure not to pass the --system option (which would set the Shell for this user to /bin/false) - this user really needs a real Shell for our purposes.

Now we need to create SSH keys for this user: sudo -H -u svn ssh-keygen -q -t dsa -f /home/svn/.ssh/id_dsa -N "".

As we said above, we want to allow our developers working with the repositories via SSH, sharing the svn account. Still we want to be able to see who did what. So that's what we now go to set up, in the ~svn/.ssh/authorized_keys file. As you might know, this file stores the public keys of all users who are allowed to access this account - one key per line. Lines starting with an hash mark (#) are comments. Less people know that each key may be preceeded by a command - and that's what we use here. So take the following block as an example (I cannot post the real keys since I don't know them).

# This user we trust fully, since he's the owner of the machine
command="svnserve -t -r /usr/local/svn --tunnel-user=izzy" <SSH Key>
# This is one of the developers. To be paranoid, we put him in a cage:
command="svnserve -t -r /usr/local/svn --tunnel-user=peter",no-port-forwarding,no-agent-forwarding,no-x11-forwarding,no-pty <SSH Key>

The directory /usr/local/svn is the base directory we go to store the repositories below. As you can see, as soon as one of our users connects, a svn server process is started via a ssh tunnel (-t parameter), the repository base is set to our base directory (-r /usr/local/svn) – which we can change in case the repositories are to be moved to a different path, so this will be transparent to our developers. And the --tunnel-user option tells the SVN server who is going to connect to it – for the log etc.pp..

Now we did something special with Peter. He shall be able to use SVN, since he joined our project. But just to be paranoid, we don't want him to do anything else – and that's what the additional parameters do (details you can guess from their names). Peter doesn't even get a shell (no-pty) if he would try …

<SSH Key> represents the users public SSH key, which follows our commands. Thus the user is identified by his key, and his personal command is executed. The client process then does the interaction with the spawned SVN server process, which is finally ended together with the session. If there's no matching key, SSH may fall back on password authentication (depending on your configuration). But since we didn't provide a password for this user, this will fail (until you apply a password to the svn account). If you don't trust me, simply try.

WebDav

You can skip this section if you don't want to access any of your repositories via WebDav (i.e. via the http:// protocol).

For the WebDav configuration, at least Ubuntu already provides a sample configuration file with everything commented out, so you can adapt it to your needs.

Simple "one-repository-only" definition

If you only want to provide a single repository for access via WebDav, and don't care too much about the "look and feel" when accessed via a web browser, configuration is quite easy. The file where you find the concerning configuration file (at least it in Ubuntu) is /etc/apache2/mods-enabled/dav_svn.conf. Adapt that file to enable the repository globally (i.e. for all virtual servers) – or move this block inside a virtual servers config to simply enable it for that server. So here comes the block – explanation below it:

<Location /repo/>
  DAV svn
  SVNPath /usr/local/svn/public/sample
#  AuthType Basic
#  AuthName "Subversion Repository"
#  AuthUserFile /etc/apache2/svn-user-auth
#  AuthzSVNAccessFile /usr/local/svn/sample/conf/authz
  <LimitExcept GET PROPFIND OPTIONS REPORT>
    Require valid-user
    Require group svn
  </LimitExcept>
</Location>

First line is quite clear: What to type into the browsers URL field to access the repository. Note the trailing slash – not a must, but prevents some errors. In this case (using the SVNPath directive), you could even set the location to / if you define a separate virtual server only for SVN WebDav. Second line is also clear (enable the WebDav for SVN), and the third line is – as you already may have guessed - the path to our repository.

Stylish multi-repository definition

If you have many repositories (i.e. more than one), you may not want to do above configuration for each of them separately. Well, you don't have to. You can define them using a single block, as shown here. But you are likely to run into some trouble with "403 - access forbidden", and/or not-parsable-stylesheet and the like errors, if you don't know and don't stick to some rules (took me quite a while to get around those). So here comes a working example and its pre-conditions, so you get it running faster than me:

First some assumptions for below configuration example. I created a dedicated virtual server for SVN WebDav access – let's call it svn.example.com here. Its document root is set to /var/www/svn and must be in a location outside your SVN repository tree for this to work. The svnindex.xsl and svnindex.css files used in our example have been downloaded from this page (which unfortunately no longer exists) and saved to the document root (i.e. to /var/www/svn. Our Apache configuration now looks like this:

<Location /repo/>
  DAV svn
  SVNParentPath /usr/local/svn/public
  SVNIndexXSLT "/svnindex.xsl"
#  AuthType Basic
#  AuthName "Subversion Repository"
#  AuthUserFile /etc/apache2/svn-user-auth
#  AuthzSVNAccessFile /usr/local/svn/sample/conf/authz
  <LimitExcept GET PROPFIND OPTIONS REPORT>
    Require valid-user
    Require group svn
  </LimitExcept>
</Location>

Looks very similiar to the previous configuration, but I will point you to the important differences: First, this time the location **must*** be something else than simply / – since our repositories, defined by the SVNParentPath, are outside the web tree and, moreover, the / URL hosts the SVNIndexXSLT files. Second, the SVNPath directive has been replaced by SVNParentPath, pointing to the directory holding all the repos. And – last but not least – there is an additional directive now, SVNIndexXSLT, pointing to the template we downloaded and installed. You will note the difference using this template. But there are even "nicer" templates available on the web, look e.g. at this site (if it's gone: here is the archived variant at the time of this writing).

Authentication

Authentication is similiar in both cases. There are 4 lines commented out, all starting with "Auth" – they are only needed if we want some authentication here, and are responsible for that. If you want some users to be able to write access the repository, you will need to enable these 4 lines and adjust them: AuthUserFile is a password file you create with Apaches htpasswd tool (stores username and password), while AuthzSVNAccessFile should point to the conf/authz file of the repository. For our example, we don't want this – and thus leave it commented out.

Logging Enhancements

If you wish, you can make your logfiles better human-readable by defining a different log definition for your virtual server (if you decided to use such). Instead of specifying

CustomLog logs/access_log combined

you could use

CustomLog logs/svn_logfile "%t %u %{SVN-ACTION}e" env=SVN-ACTION

Or, if you want to keep the old style as well, you may combine both:

CustomLog logs/svn_logfile "%t %u %{SVN-ACTION}e" env=SVN-ACTION
TransferLog Log logs/access_log

As for TransferLog you cannot pass the log format to be used, you may have to specify it immediately before the TransferLog entry, using the LogFormat clause. Please refer to the Apache documentations for details on this issue.

Scripts used for the steps described

Create the SVN user

This script creates the SVN user and his SSH keys. You should run it while being root (e.g. by sudo ./svn_create_user.sh):

#!/bin/bash
# Create the SVN user

#===================================================[ The SVN user account ]===
# Here we create a user (and group) "svn". This account will also be used for
# shared access by the developers (so not everybody needs an own OS account),
# so it needs a real shell (i.e. don't use "adduser --system", as this assigns
# "/bin/false", which will result in "svn: Connection closed unexpectedly"
# (svn: Netzwerkverbindung wurde unerwartet geschlossen) when accessing the
# repo with "svn+ssh://svn@server:/repo"
adduser --group svn
sudo -H -u svn ssh-keygen -q -t dsa -f /home/svn/.ssh/id_dsa -N ""

Creating Repositories

Once the server has been setup and configured, we can go to create our repositories and fill them with data. So beside the repository creation, this section will demonstrate two ways to get your code into them: Importing from a source tree, and converting from a CVS repository. In the latter case we will also implement a hook, so all changes done in your subversion repository will also be applied to the former CVS repository - so you can revert back if you feel subversion is not for you. Of course, this is optional.

This first step for each of your projects is not needed if you want to convert from your CVS repository (this conversion will implicitly create the repo for you). All these steps assume that you are still working as the superuser (sudo - su).

Base directories

First, we create two trees below our base directory. This is an optional step: we do this since we want to separate "private" repositories (which should not be accessed by anyone else) from the "public" ones. In our example, we only want to use one private repository for e.g. our server configuration files and the like, which simply will reside in separate directories – but keep place to setup multiple repositories here, one for each project.

sudo -H -u svn mkdir -p /usr/local/svn/private
sudo -H -u svn svnadmin create --fs-type fsfs /usr/local/svn/private
sudo -H -u svn mkdir -p /usr/local/svn/public/sample
sudo -H -u svn svnadmin create --fs-type fsfs /usr/local/svn/public/sample

Permissions

Next, we have to care for the permissions. We already discussed that we want one local user – usually the server administrator – to be able to access the repositories e.g. for maintenance. Of course, you could do that as superuser (root) – and if so, you can skip the first step of this process: Adding the local user to the svn group:

# Add our local admin to the svn group
adduser admin svn
# Provide group access to the repositories
chmod -R g+w /usr/local/svn

Again: If you have no local user who should access the repository locally from the machine itself, you don't need that step. But still you need to configure access to the repositories from remote machines. This is done inside the conf/authz file in the repository tree – i.e. in our examples, /usr/local/svn/private/conf/authz for the private, and /usr/local/svn/public/sample/conf/authz for the public "sample" repository.

Let's start with the private one. Here we only want one user – we call him "john" here – full access. Nobody else should have access to this repository. So the authz file should look like this – if you remove all comment lines:

[/]
john = rw
* =

For our "public" repository, we want a different setup. Here we have our developers requiring read and write access – and everybody else should have read access:

[group]
devel = john,peter

[/]
devel = rw
* = r

Using the group feature, you can easily add (or remove) team members at any time, and don't need to setup the rights for everyone separate. But even if: The only permissions available here are read ("r") and write ("w"), so not to much to fiddle around with.

Get your data into the repository

Fine – now everything is set up, and we can start to work. First we want to have some data in the repository (makes not much sense without). Basically, there are three methods available to get our files in: add each file separately to the repository (very funny, huh? Okay, forget about that here in this context), importing from a source directory, or converting from a CVS repository. As suggested, we skip the first method here – and have a look at the other two.

Importing from a source directory

This variant is suiteable for code that either has not been in any repository before – or you want to start fresh with, leaving the history behind. To continue with our example, we want to use this method to get our configuration files into the private repository:

cd <directory-above-configuration-dir>
sudo -H -u svn svn import <name> file:///usr/local/svn/private/<name> -m "Initial Import"

As the example shows, we first change to the directory one level above the one we wish to import – and then issue the import command. If you did setup a local user for svn above, you don't need to run these steps as root – and thus can skip the "sudo -H -u svn" prefix of the second line. The term <name> stands for the name to use for this directory in the repository – in our example this would be the same as the directory on disk.

That's already all for the import. Now you could change to some other place on your disk, and checkout the code: svn co file:///usr/local/svn/private/<name> will create a directory named <name> at the place where you issue this command.

Converting from a CVS repository

As described above: If we want to convert from a CVS repo, we don't need to create the SVN repository before. So the following steps assume the repository does not yet exist – but we go to create it in our "public" area. You may need to install cvs2svn before (sudo apt-get install cvs2svn).

sudo -H -u svn cvs2svn --trunk-only --encoding=utf8 --username=john --fs-type fsfs -s /usr/local/svn/public/demo /usr/local/cvs/demo

In this example, our CVS repository (not the working copy!) resides in /usr/local/cvs/demo – i.e. our project is called "demo". And we want to keep that name for our SVN repository. --trunk-only means we have no branches to convert (or don't want to convert them). If that's not the case for you, simply skip this parameter. For the log files, we want to use UFT8 encoding, so all characters are kept (German umlauts, French accents, Kyrillic letters …). The repository should not use Berkley DB, but the newer FSFS (which usually is the default – but it doesn't hurt to specify it just to be on the safe side). The -s specifies our SVN repository location – and the final parameter is our good old CVS repository.

Implementing a hook for "fall-back"

This again is an optional step. If you are sure you won't ever use your CVS repository again: Just back it up, store it somehow ("just in case"), and skip this section.

I already said, we can implement some hook to get all the changes from SVN back to our old/original CVS repository. If you want to do so, nobody else should write to the CVS repo anymore – or things get screwed up. First, make a backup of your CVS repository (copy it somewhere else, or create a tarball from it). And finally, advice all your developers to only use the new SVN repository now.

For the hook, we first need the script doing the real work. You can find this together with a description of what it does and how to implement, on this page. Download the script, and store it somewhere accessible by your $PATH variable (or you have to specify the full path in all the hook scripts). That script basically looks like this:

#!/bin/sh
REPOS="$1"
REV="$2"
CVSDIR=/path/to/cvs/repo
svn_maillog "$REPOS" "$REV" "svn@localhost" "sam@localhost"
svn_cvsinject -r "$REV" "$REPOS" "$CVSDIR" -a "1.0/v1_0" -a "2.0/v2_0" &
exit 0

What you have to do here is: Adjusting the CVSDIR variable to point to the CVS repository directory, make the script executable, and store it in the hooks/ subdirectory of your SVN repository. Can't hurt if you chown the script to the svn user (chown svn:svn post-commit), and make it executable for user and group (chmod u+x,g+x post-commit).

Great – you are done! Please, check the scripts web site (where you downloaded the svn_cvsinject script from) for limitations, description, and the like - so you know what to expect.

Scripts used for the steps described

Create/migrate repositories from CVS

This script creates the "private repository" discussed above and as well migrates your existing CVS directories. Check thorougly before really using it – at least you have to adjust some settings in the configuration section. To run it, you should be root (e.g. by sudo ./svn_create_repos.sh):

#!/bin/bash
# With this script you can initially create your repositories. Run it as
# root - e.g. "sudo svn_create_repos.sh" - after you checked it and made
# your changes, where necessary.

#==========================================================[ Configuration ]===
# Sudo command for executing things as svn repo owner
sudo="su - svn"
# Base directory below which all your repos reside
svnbase=/usr/local/svn
# local user with full access to all SVN functions - this is the one and
# only to access the private repository
admin="john"
# users with read+write access to all repositories
admingroup="john,peter" # comma separated list for the conf/authz file
# where is your old cvsroot (for all your projects to be migrated here)
cvsroot=/usr/local/cvsroot
# which projects to migrate 1:1 (space separated list)
conv_projects="demo sample whatever"
# which projects to migrate and rename
conv_oldname="beans frogs"
conv_newname="jbean ifrog"

#--------------------------------------[ authz file for private repository ]---
# This function creates the conf/authz files for the private repository. It
# accepts and requires one parameter: The SVN repository directory
function authz {
  local file=$1/conf/authz
  mv $file ${file}.bak
  cat >$file<<EndAuth
[/]
$admin = rw
* =
EndAuth
}

#-------------------------------------[ authz file for public repositories ]---
# This function creates the conf/authz files for each repository. It accepts
# and requires one parameter: The SVN repository directory. Optional second
# parameter defines whether the original "example outfile" should be removed
# (set it to "del") or not (ommit the parameter).
function authz {
  local file=$1/conf/authz
  mv $file ${file}.bak
  cat >$file<<EndAuth
[group]
admins = $admingroup

[/]
admins = rw
* = r
EndAuth
  [ "$2" = "del" ] && rm ${file}.bak
}

#-------------------------------------------------------[ post-commit hook ]---
# This creates the post-commit hook to feed the old CVS repo. Comment in the
# svn_maillog if you have that script and want to use it
# Parameters: <SVN repository directory> <CVS repository directory>
function cvshook {
  svndir=$1
  cvsdir=$2
  hookfile=$svndir/hooks/post-commit
  cat >$hookfile<<EndHook
#!/bin/sh
REPOS="\$1"
REV="\$2"
#svn_maillog "\$REPOS" "\$REV" "svn@localhost" "sam@localhost"
svn_cvsinject -r "\$REV" "\$REPOS" "$cvsdir" -a "1.0/v1_0" -a "2.0/v2_0" &
exit 0
EndHook
  chown svn:svn $hookfile
  chmod u+x,g+x $hookfile
}

#----------------------------------------------[ Migrate projects from CVS ]---
# This function migrates a group of repositories which reside in the same
# main dir on CVS side, keeping their names as-is.
# Parameters: <List of modules> <CVS root dir> ["del"]
# The SVN base is taken from above configuration. If "del" is specified, the
# example authz file created by svn will be replaced by our own. Otherwise
# it will remain as authz.bak
function migrate_cvs {
  local pnames=$1
  local cvsroot=$2
  for project in $pnames; do
    $sudo "cvs2svn --trunk-only --encoding=utf8 --username=izzy --fs-type fsfs -s $svnbase/public/$project $cvsroot/$project"
    authz $svnbase/public/$project del
    cvshook $svnbase/public/$project $cvsroot/$project
  done
}
# This function migrates a CVS repository and changes its name. Good for
# projects which have been renamed - best time to rename the repository ;)
# Parameters: <CVS module name> <SVN module name> <CVS root directory> ["del"]
# Behaviour as described for the previous function.
function migrate_renamed {
  local oldname=$1
  local newname=$2
  local cvsroot=$3
  $sudo "cvs2svn --trunk-only --encoding=utf8 --username=izzy --fs-type fsfs -s $svnbase/public/$newname $cvsroot/$oldname"
  authz $svnbase/public/$newname del
  cvshook $svnbase/public/$newname $cvsroot/$oldname
}

#===========================================================[ Repositories ]===
# Create base directory for repositories and own it to the svn user - just in
# case this is not yet done
mkdir -p $svnbase
chown svn:svn $svnbase

#--------------------------------------------[ Now create the repositories ]---
# private one for site maintenance:
$sudo "mkdir -p $svnbase/private"
$sudo "svnadmin create --fs-type fsfs $svnbase/private"

# public one for OpenSource projects:
$sudo "mkdir -p $svnbase/public"

# 1:1 migration
migrate_cvs "$conv_projects" "${cvsroot}"
# projects to rename
typeset -i i=0
typeset -i max=`echo $conv_oldname|wc -w`
while [ $i -lt $max ]; do
  let i=$i+1
  oldname=`echo $conv_oldname|cut -d " " -f $i`
  newname=`echo $conv_newname|cut -d " " -f $i`
  migrate_renamed $oldname $newname "$cvsroot"
done

Working with Subversion

Using SVN with the command line is much the same as with CVS. If you worked with CVS up to know, most commands will look familiar to you. However: Since SVN offers additional features, there are also additional commands. For all of them, there is online help available by invoking the command line client as follows: svn help for a list of commands, or svn help <command> for help on a special command.

Basic commands

The following table contains a list of basic commands. Commands from the first block will look similiar to you if you already used CVS. The second block shows commands not available in CVS:

Command Description
Commands similiar to CVS commands
svn add <files> add files to the repository
svn checkout checkout code from a repository
svn commit [-m "message"] commit changes to repository
svn diff <file> show differences between local file and repository version
svn import <directory> import code to the repository
svn update update code from repository
Additional commands
svn copy <source> <target> copy a file
svn mkdir <directory> create a directory
svn move <source> <target> move or rename a file or directory

Initialize a repository

Other than with CVS, some things are not setup by default – e.g. the keywords (Id, Author, Revision etc.). So to initially setup your repository, you may find the following script useful. It should be ran against your SVN working copy, and do it expects two parameters: The SVN repository to checkout the code from, plus the directory to create your working copy in.

#!/bin/bash
# Initialize a SVN repository we just imported from CVS
# (converting .cvsignore and set the keywords to use)
#==========================================================[ Configuration ]===
# Keywords we want to use
keywords="Id Author Rev Revision"
# Parameters passed to the script
REPO="$1"
WORKDIR="$2"

#=================================================[ Process the given Repo ]===
#---------------------------------------[ CheckOut from the SVN repository ]---
svn checkout $REPO $WORKDIR
cd $WORKDIR
#-----------------------------------------------------[ Convert .cvsignore ]---
find -name .cvsignore | while read file; do
  svn propset svn:ignore "`cat "$file"`" "`echo "$file" | sed 's,/[^/]*$,,'`"
done
#--------------------------------------------[ Set the keywords to be used ]---
find . -type f -a '(' -path '*/.*' -prune -o -print ')' | while read file; do
  for keyword in $keywords; do
    if grep -q "\$$keyword:" "$file" && ! svn propget svn:keywords "$file" | grep -q "^$keyword\$";
    then svn propset svn:keywords $keyword "$file"; fi
  done
done
#-----------------------------------------------------[ Commit the changes ]---
svn commit -m "imported svn:ignore and svn:keywords properties"

Migrating to a new server

Some day your SVN repository might need to be migrated to a new server. That's the time you start thinking about how to do that. Or you simply want to have a backup of your repositories handy, just in case. As that's the first half of a migration, it's covered here as well.

While one might think a simple copy of the corresponding directories might do (which is not unlikely to be the case), most sources on the web don't recommend so. Instead, they are speaking of "dumping" the repository, and restoring it from the dump. So did the source I based my migration on, a PDF found at Binary-Zone.com. As I didn't want to do this manually for a bunch of repositories, I've used that information to create a script automatizing the entire process.

Backing up the repositories

The very first step is to dump the repository. This can be accomplished using the command svnadmin dump -q </path/to/repo> <repo-name>.svndump (optionally followed by a packing command like bzip2 -9 <repo-name>.svndump). This dump will hold the entire codebase, including all its revisions, in a way that you can "replay" all its commits. Fine for a backup, as of course you can "replay" it on the original server as well. This command can be run by any user having access to the repository. That could be svn, root, or any other user you've granted access.

But that's only half of it, as the dump just holds the code. If you didn't simply use the svn user as a "proxy" (as described in Setting up the server: svnserve), but had "local users" on the machine accessing it as well – or made some special adjustments to the setup of each repository, you should take care for the repository's conf/ directory as well. Same applies to the commit-hooks in its hooks/ subdirectory. A simple tar cjf <repo-name>-conf.tar.bz2 </path/to/repo>/conf </path/to/repo>/hooks should do.

Transferring data to the new server

There's not that much to say on this: Simply transfer the files as you would normally transfer files, using the tool of your choice – be it scp, rsync, ftp, or whatever is available. Even an USB stick would do.

Restoring from a backup

Now comes the "replay" action – but first there are some preparations required: an empty repository has to be created. This should best be done as user svn, and is described in detail in Creating the repositories. Here the abbreviated variant, assuming you are logged in as user svn:

# Creating an empty repository for "foobar"
svnadmin create "/opt/svn/foobar"
# Unpacking the dump
bzip2 -d --keep "/opt/svndumps/foobar.svndump.bz2"
# Do the "Replay"
svnadmin load --force-uuid "/opt/svndumps/foobar.svndump" "/opt/svn/foobar"
# Remove the unpacked dump
rm -f "/opt/svndumps/foobar.svndump"

That done, you might need to take care for the conf/ and hooks/ directory's contents now. Either restore the necessary files manually (especially when the migration involved a version jump, where things might have changed) – or simply unpack the tarball you've created with the backup.

All that's left now is the svn user's .ssh/ setup, or the WebDAV stuff – whichever you've used. This part you again find with the installation instructions.

Which means: Basically, all done and should be up and working. For your convenience, there the automatized

Script used for the steps described

This script does multiple things. First, it assumes you have several trees of repositories (e.g. for multiple projects). If you don't, you can of course adjust that. After all, the script is just an example (though a working one). It walks those "masters" (project directories), and processes each subdirectory it finds as "slave" (svn repository).

For each "slave" it does the above described backup steps: dumping the revisions, packing it with bzip2. While doing so, it also creates a restore script, which you then simply need to run for the "replay": it will create the repos, unpack the dumps, "replay" them, remove the unpacked dump, and keeps the packed ones. The head of the created restore-script holds a comment with some basic hints, just in case.

At the head of the script you find a little [ Configuration ] section. This is where you adjust the paths to reflect your local setup.

Now: Enjoy! I hope it helped you.

#!/bin/bash
# Dump all SVN repositories
# Idea taken from http://www.binary-zone.com/Projects/howto-svn-migration.pdf
# See also: http://forums.debian.net/viewtopic.php?t=4933 (how to setup svn)
#
# This script will dump all repos, compress them using bzip2, and prepare a
# restore script. Simply mirror the entire BACKUP_DIR to the new machine,
# make the restore script executable, and run it there. Pre-condition is
# the new server uses the same directory structure.
#
# Remember that this way only the repositories are safely "migrated" to the
# new server; you must still take care for the configs, hooks, etc. in
# their respective subdirectories.

#--=[ Configuration ]=--
SVN_BASEDIR=/opt/svn
BACKUP_DIR=/opt/svndumps
RESTORE_SCRIPT="${BACKUP_DIR}/svn_restore.sh"
#--[ /Configuration ]=--

function svn_backup() {
  REPO=$1
  BNAME=$2
  FNAM=$(basename "$REPO")
  # Backup:
  echo "Processing ${REPO}"
  svnadmin dump -q "$REPO" >"${BNAME}/${FNAM}.svndump"
  bzip2 -9 "${BNAME}/${FNAM}.svndump"
  # Preparing restore:
  echo >>"${RESTORE_SCRIPT}"
  echo "# Restoring ${REPO}" >>"${RESTORE_SCRIPT}"
  echo "svnadmin create \"${REPO}\"" >>"${RESTORE_SCRIPT}"
  echo "bzip2 -d --keep \"${BNAME}/${FNAM}.svndump.bz2\"" >>"${RESTORE_SCRIPT}"
  echo "svnadmin load --force-uuid \"${REPO}\" \"${BNAME}/${FNAM}.svndump\"" >>"${RESTORE_SCRIPT}"
  echo "rm -f \"${BNAME}/${FNAM}.svndump\"" >>"${RESTORE_SCRIPT}"
}

echo "#!/bin/bash" > "${RESTORE_SCRIPT}"
echo "# Restore SVN repositories from the scratch" >>"${RESTORE_SCRIPT}"
echo "#" >>"${RESTORE_SCRIPT}"
echo "# Restore should be done using the svn user, so we have to create it first:" >>"${RESTORE_SCRIPT}"
echo "# adduser svn --gid 120 --uid 120 --home /home/svn --shell /bin/bash --system --disabled-password" >>"${RESTORE_SCRIPT}"
echo "# mkdir -f \"${SVN_BASEDIR}\"" >>"${RESTORE_SCRIPT}"
echo "# chown svn:svn \"${SVN_BASEDIR}\"" >>"${RESTORE_SCRIPT}"
echo "# Now remember to run the following as svn user, i.e. 'sudo su - svn' first."
echo "#" >>"${RESTORE_SCRIPT}"
for master in $(ls "$SVN_BASEDIR"); do
  [ ! -d "${BACKUP_DIR}/${master}" ] && mkdir "${BACKUP_DIR}/${master}"
  if [ "$master" = "slw" ]; then
    svn_backup "${SVN_BASEDIR}/${master}" "${BACKUP_DIR}/${master}"
  else
    for slave in $(ls "${SVN_BASEDIR}/${master}"); do
      [ -d "${SVN_BASEDIR}/${master}/${slave}" ] && svn_backup "${SVN_BASEDIR}/${master}/${slave}" "${BACKUP_DIR}/${master}"
    done
  fi
done

Useful SVN Resources

Manuals, tutorials and HowTos

URL Description
Subversion Home Subversion home page – first-hand information and resources: manual, FAQ and more.
HowTo WebDav How To Configure Web Access To Subversion Repositories Using Apache. Includes a post-commit hook to send a mail after each commit.
SVN manual Complete manual for SVN as of version 1.4. For other versions and languages, look here.
CVS2SVN HowTo HOWTO: smooth CVS to SVN migration (and back again)
Subversion HowTo A Subversion HowTo (German)
SVN and Trac This tutorial covers the installation, configuration and administration of a Linux Subversion Server and Trac server.
SVN Tutorial A more detailed tutorial on svn command line client usage - with links to server installation and configuration
Apache and SVN HOWTO Apache2 with subversion SVN and DAV (based on Gentoo Linux)
Wikipedia Wikipedia article describing Subversion and its features

Comparisions

URL Description
SVN vs CVS The pros and cons. May be not that up-to-date, and also not complete.
Misc Versioning tools Comparing miscellaneous versioning tools: CVS, SVN, Aegis, Arch and SVK
Git vs. SVN Git's Major Features Over Subversion

Software

Graphical FrontEnds

URL Description License OS
SmartSVN Java based graphical frontend to SVN Commercial w/ Trial All that support Java
KDESVN As the name suggests: a KDE based graphical client GPL Linux
RapidSVN Fast client written in C++ GPL Linux, Windows
KSVN Plugs into Konqueror as Tortoise does in the Windows explorer GPL Linux
TortoiseSVN Windows shell extension - manage SVN from inside the explorer GPL Windows
SyncroSVN Multiplatform Subversion front-end Commercial w/ Trial Linux, Mac, Windows
GSVN A Gnome frontend to SVN GPL Linux

Other SVN tools

URL Description License OS
SVN2Log automatically generate changelogs from a Subversion repository AFL All Python supported
Commitfilter provide a commit mailing list where users can subscribe GPL All Perl supported
Easy SVN Web FrontEnd to SVN formerly known as WebSVN. Only requires Perl and the svn CLI GPL Linux, Mac, Windows
ViewSVN PHP based web frontend GPL All PHP supported
SVN::Web Perl based SVN Web FrontEnd Perl All Perl supported
Subversive Eclipse PlugIn for SVN Eclipse All Java supported

Miscellaneous

URL Description
ReposStyle.COM Styles for browsing your repositories via WebDav, using an Internet browser
SVN2CVS Just in case you need to revert back …
2018-12-16