Subversion Administration

From Elvanör's Technical Wiki
Jump to navigation Jump to search

This article is a tutorial to Subversion repository administration and general usage.

Design choice: repository setup and serving method

  • You can choose to have one repository per project, or only one single repository containing each project in a separate directory. The single repository setup is easier, but the inconvenient is that the revision number will go up for some projects that did not undergo any changes (if some other projects are updated).
  • Note that if you choose to use the svnserve method rather the Apache one, you won't be able to use name based (DNS) "virtual hosting" if you have several repositories. At least it seems to be MUCH more complicated to set up.
  • You can choose to serve a svn repository over SSH. In this case no svnserve daemon is running, svnserve is only started when needed by ssh. The advantages are increased security (encrypted traffic, no password stored in clear on the server). However note that with the standard svnserve method, no password transits in clear anyway.
  • The disadvantage of SSH for svn is that the administrative tasks can be cumbersome. All svn users must have their SSH key registered on the server, and must be part of the svnusers group, for example.

Repository structure

  • The recommended layout for a given project (within the repository) is to have three directories: trunk, branches and tags. Thus with a project named cool-project:
cool-project/

    branches/
    tags/
    trunk/

The developers should normally checkout from the trunk directory.

Setting up permissions

  • The file authz does not override svnserve.conf for permissions. If all the variables are defined at once, all of the rules must be satisfied before access is allowed.
  • To add a new user to a SVN+SSH setup, do the following:
    • Create the new UNIX account, add it to the svnusers group.
    • Setup the permissions in the authz file for the correct repository.
    • Add a key to authorized_keys, with the following command before the key:
command="/usr/local/bin/svnserve -t -r /var/svn" ssh-dss
    • Alternatively you can use a single subversion user, in that case add only the key to the subversion user .ssh/authorized_keys file and use --tunnel-user:
 command="/usr/bin/svnserve -t --tunnel-user=elvanor -r /var/svn" ssh-dss
  • Note that the svnserve program will set the permissions for the revisions (on a file system repository) to be the same as the one in the parent directories. So if you initially set it as you like when you first run svnadmin create, you don't have to worry later (a call to umask in a wrapper script is unnecessary).

Importing / Exporting repositories

  • This can be done with the svnadmin dump and svnadmin load commands.

Obliteration

  • You cannot with the current version of Subversion (1.4.3) delete an entire revision from the repository easily, if you accidentally committed big binary files.
  • There is however a way to remove permanently some parts of the repository if you need to. For that you will have to use the tools svnadmin, and svndumpfilter.

Importing / exporting projects

  • While doing the initial import, remember that if you specify a path, only its contents will be added, thus, if you want to actually add the directory, remember to do a svn mkdir first.
  • This is not the case when you do an initial checkout of a project.
  • To checkout a repository directory but without the SVN information, use svn export. Very useful when you need to deploy a project to a production environment.

Renaming & Modifying a project hierarchy structure

  • Whatever you do, remember to *NEVER* use non Subversion tools to move versioned files around. If you do that with directories, you will copy the.svn special area within that directory and it will be a pain to get a working copy and repository after that.
  • You can use the SVN command line client or the Subclipse client to move/rename entire directories. Kdesvn does not seem to work.

Switching a local copy to a new repository

  • If a repository changes URL, you can point a local checked out copy to the new URL by running
svn switch --relocate old_url new_url .

Don't forget the last part (the path).

Creating a snapshot (tag) or branch

  • It is extremely easy to create a tag for a particular release. Just issue the command:
svn copy svn+ssh://svn.shoopz.com/com.shoopz/shop-engine/trunk \
          svn+ssh://svn.shoopz.com/com.shoopz/shop-engine/tags/release-1.0 \
     -m "Tagging the 1.0 release of the shop-engine project."

Working with branches

  • Creating a branch is exactly the same as creating a tag.
  • It is possible to delete a branch once you finished working with it, with the standard svn delete command.

Operations

Conflicts

  • When a conflict occurs, SVN creates four files for you. The ancestor revision (the file that existed in the repository before any changes that led to the conflicts were made), the last revision (as commited by somebody else while you were editing the file, so that led to the conflict), you own file with the .mine extension, and finally, a strange file that contains the merge of your changes and the ones on the repository. This last file takes the name of the usual file (no extension) and has merge markers in it.
  • To resolve the conflict you must edit the merged file and remove the markers while fixing the problem.
  • With the Subclipse Eclipse plugin, just choose Team -> Edit Conflict. You will be presented with a diff of the two files which is useful. Be careful that if one file uses different line breaks than the other, the whole file may appear modified!

Reversing changes

  • You can reverse changes made by a particular revision by using the merge command.
  • On Subclipse, this operation is easy: go to the merge dialog, choose HEAD as the start revision and HEAD - 1 as the target one.

Tips & Hints

  • Subversion does password caching by default, so don't be surprised if you are not asked for a password after the first time.
  • There is a list of patterns (for example, *.o files) that are automatically ignored by svn. This is done client-side and can be modified by the client configuration files.
  • Ignore patterns can be specified by running svn propedit svn:ignore directory. Note that this does NOT affect items already put under version control (eg, this makes sense only for items not under version control).
  • Ignore patterns can be set recursively by adding the -R option to the command svn propset, for example. However I don't know if it is possible to add ignore patterns recursively, since propset erases the previous information.
  • The bottom line is that files that need to be ignored on *every* platform (.o files, for example) should be set using the svn:ignore property. What is dependent of the development platform (eg, .directory files that seem to appear with KDE/KDEsvn) should be set by the client.
  • On UNIX, the client configuration file is at ~/.subversion/config. The line to change is global-ignores, set for example to:
global-ignores = *.o *.lo *.la #*# .*.rej *.rej .*~ *~ .#* .DS_Store .directory
  • The fact that a file has the executable bit turned on (on UNIX systems) is controled by the property svn:executable. To set this property:
svn propset svn:executable myprogram

To unset it:

svn propdel svn:executable myplainfile

Note that if you work under Windows some files seem to get this property wrongly set (thus forcing you on UNIX to correct this).

  • To remove all the SVN garbage from a deployment directory, if it was not accidentally copied with the SVN information:
find ./ -L -name .svn | xargs rm -rf

The -L option follows symlinks and may not be necessary.

  • When using svn copy with directories, svn will automatically copy recursively the whole directory. However, only the top directory will be marked for addition, the inner items won't. This can be surprising, as you could expect a behavior of recursively added items. Don't worry though, if you edit later the inner items everything "will just work".

GUI clients

  • kdesvn to get SVN support in Konqueror (very nice). On Gentoo, if it crashes, do a emerge --depclean to get rid of obsolete dependencies and rebuild kdesvn.
  • Subclipse: Subversion support in Eclipse. Absolutely mandatory.

Issues

If you are using the command line SVN client (on Linux for example), there is a bug associated with operations on the root directory of an svn+ssh:// server. For example, svn list svn+ssh://svnusername@svn.elvanor.net will not work as expected. This is due to a bug in the parsing system of svn; it does not happen when dealing with another directory (eg , svn list svn+ssh://svnusername@svn.elvanor.net/doc/ works fine) and it also does not appear when using GUIs (KDEsvn or TortoiseSVN).

A workaround is to not use the user@server syntax, but directly server. So add the following lines to your SSH config (on Linux, ~/.ssh/config):

Host svn.elvanor.net
User svnusername

Then you can use svn like this: svn list svn+ssh://svn.elvanor.net/.

Useful links

Subversion book

Small CVS Reference

  • This would export the release 2.0.6 (assuming that tag exists) of the Spring Framework:
cvs -d:pserver:anonymous@springframework.cvs.sourceforge.net:/cvsroot/springframework login 

cvs -d:pserver:anonymous@springframework.cvs.sourceforge.net:/cvsroot/springframework export -r release-2-0-6 spring
  • The equivalent of svn status is best obtained by
cvs -nq update

Unfortunately, this requires network access.

  • Pruning of old files removed on the repository is not automatic with CVS. At least it should be, but I had problems with it. So the best sometimes is just to delete a whole directory and do a cvs update afterwards, which will regenerate it.
  • When adding a new directory to a CVS repository, commit is automatic. CVS does not give you a chance to wait until you actually commit manually. Also note that if you try to add files in a directory not yet added to the repository CVS will give you an error message saying that no root repository is defined.