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:
- checking in a symbolic link checks in the symbolic link (not the refered file as in CVS)
- you can easily move files/directories without losing their change history
- you can browse a repository using the command line client
- the repositories can be accessed by multiple methods: locally (
file://
urls), via ssh or rsh, and even WebDav (http://
/https
URLs) - users can browse your repositories with their favorite web browsers - if you permit (and setup WebDav for this)
- and much more
Sure SVN has many highlights - but to be fair we should admit it also has its downside:
- the repository needs twice as much disk space
- in order to be able to use keywords as Id, Author, and Revision, you must explicitely configure their use for each file
- on some other points, people disagree (see the comparisions)
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
- Introduction
- Software installation
- Creating Repositories
- Working with Subversion
- Migrating to a new server
- Useful SVN Resources
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 … |