home | codereading | contact | github | math | misc | notes | patches | tech | README

SVN notes

SVN client howto


When doing operations on the repository with the svn command, it is necessary to specify the full repository path. For example, supposing that the server is serving svn using ssh. To checkout a directory of a project, do (like described here):

$ svn checkout svn+ssh://hostname/path/to/repository/project/trunk

It will make login like logging in a machine through ssh.

Accessing the repository through ssh

This requires a Unix account on the SVN server.

After setting up a SVN repository as told in SVN Server Setup, it will be necessary to create individual directories for the projects:

$ svn mkdir svn+ssh://hostname/path/to/repository/project

As told here, it is convention for subversion users to create some directories below the project root:

trunk/              - main flow of development
branches/           - any branches of development
tags/               - snapshots of the repository


$ svn mkdir svn+ssh://hostname/path/to/repository/project/trunk
$ svn mkdir svn+ssh://hostname/path/to/repository/project/branches
$ svn mkdir svn+ssh://hostname/path/to/repository/project/tags

After that, just checkout the project:

$ svn checkout svn+ssh://hostname/path/to/repository/project

You can also, easily, checkout the whole repository and run mkdir command on it:

$ svn checkout svn+ssh://hostname/path/to/repository
$ svn mkdir project
$ svn mkdir project/trunk
$ svn mkdir project/branches
$ svn mkdir project/tags
$ svn commit

And it is ready to get work done on the trunk/ directory.

Accessing the repository without ssh

The commands are the same, but instead of specify the svn+ssh:// protocol, just specify svn://. Also, if the port is not default, specify it in the command line, as shown in the example below (which uses the port 21 to run svnserve):

$ svn checkout svn://hostname:21/path/to/repository/project/tags

Remember that it is not required to have a Unix account on the SVN server, but you need to have access to the repository by creating a user in the repository configuration (conf/<configuration files>). Ask for the SVN administrator to create a user there for you.

If everything is ok, you will be prompted out for a password. Just insert it and everything is working!

SVN server setup

Creating the repository

In NetBSD, subversion-base package is enough for a basic installation. Once you have it installed, create the repository as the user that will own it:

$ su - svn
$ svnadmin create <your repository path>

Once you have been set up the repository, there are several ways to make it available remotelly. Using WebDAV is the most common way, but classical SSH access looks easier and secure, but according to the svnbook, it is not useful when used for many developers. I recommend using ssh only if it is a single user.

Using SSH method to access the repository

So, to enable SSH access to the repository, call the svnserve command, as described here:

$ svnserve -t -r <your repository path>

Append the -d option to make it behave like a daemon, which means that it backgrounds itself. Useful for starting it at the system boot time.

Using svnserve without ssh

This page recommends using svnserve without ssh when there are many developers wishing to access the same repository. It is simple to set up, effective and not really unsecure (although code surfs raw through the cable, the password never goes raw, as told in the svnbook).

So, to set it up, following svnbook, put it in /etc/inetd.conf or in /etc/xinetd.d/svnserve. See this xinetd serve example:

# default: on
# Subversion server

service svn
    socket_type     = stream
    protocol        = tcp
    user            = svn
    wait            = no
    disable         = no
    server          = /usr/bin/svnserve
    server_args     = -i
    port            = 3690

You can also run it like a standalone daemon, with the -d option.

Authentication and access control

This page of the svnbook explains very well authentication and access control. About authentication, if we use svnserve + ssh method, we need to create a Unix account on the machine, for each user that wants to access the repository. If we use svnserve without ssh, there are several ways to make authentication (LDAP and others), but simplest way is to set up the conf/users.cfg file in the repository. Access control is made in conf/authz.cfg file (those names are flexible and configured in the conf/svnserve.conf, in the repository).

The conf/svnserve.conf file is the main configuration file, which points to the others (conf/users.cfg or authz.cfg in the examples given above).

An example of the conf/svnserve.conf file is given below:


# Global access settings.
anon-access = none
auth-access = write

# Users and their passwords
password-db = users.cfg

# Path-specific constraints
authz-db = authz.cfg

realm = My repository name

Importing CVS modules to a SVN repository

If you used to use CVS and is migrating to subversion, you can use cvs2svn [6] program. This cvs2svn FAQ entry teaches a way of importing one module at a time, instead of convert the whole CVS repository to a SVN repository.

Basically, the process consists in copying the cvs2svn-example.option file, modify it and run with the following command:

$ cvs2svn --options=<your modified option file>

If your repository already exists (which means that you don't want to create a new one), specify it in the ExistingRepositoryOutputOption() function instead of the NewRepositoryOutputOption(). (cvs2svn version 2.1.1).

Working with branches and tags

You create a branch with svn copy:

$ svn copy trunk branches/version-2-0

Subversion use the same command for both branches and tags. Therefore, the difference between them is just the use you make for it. If you never do any commit in a directory created by svn copy, it is then a tag.

To merge changes from another branch, use svn merge. You will always have to checkout at least the branch you want to merge to:

$ svn checkout svn+ssh://hostname/path/to/repository/project/trunk
$ cd trunk
$ svn merge svn+ssh://hostname/path/to/repository/project/branches/mybranch

There can be things like conflicts on files. They normally appear if different changes were made in the same file for different branches. Resolving conflicts in subversion can be frightening. This page seems to have good tips for resolving conflicts:

svn merge changes your working tree. If you do not want to do that, but only want to be sure that the merge succeds without conflicts, use the --dry-run option:

$ svn merge --dry-run svn+ssh://hostname/path/to/repository/project/branches/mybranch

To rollback a commit, or a list of commits, you should also use svn merge:

$ svn merge -r HEAD:140 .

This command applies a revert diff at the top of your working directory, so it changes everything to make it equal to the 140th revision of your repository (I saw this here).

There are other commands that may come to help when doing merges. The command svn mergeinfo show important stuff like the common ancestor for two branches and when the last merge ocurred:

$ svn mergeinfo svn+ssh://hostname/path/to/repository/project/trunk

    youngest common ancestor
    |         last full merge
    |         |        tip of branch
    |         |        |         repository path

    1                  276
    |                  |
    -----| |------------         trunk
     \          /
      \        /
       --| |------------         branches/ufrn
              |        |
              73       WC

To view merge information of a branch, use the following command:

$ svn propget -R svn:mergeinfo svn+ssh://hostname/path/to/repository/branch

(Thanks to this page for this tip).

Mirroring the repository

I sometimes want to make tests on the repository but don't want to mess with the repository history. In this situation, I create a temporary and local mirror and work there.

For this, use svnsync. There is a nice and easy howto on how to use that here.


Your repo location changed, and your working copy points to the old location

In this case, just use the svn switch command, with the --relocate flag:

svn switch --relocate svn://old/svn/location svn://new/svn/location

Check the svn switch manual for more information.

Cannot delete file or directory with an at sign (@) in the name

If you (deliberately or by mistake) has a file with an at sign, you will realise that you cannot delete it or even make another change using svn. This is because @ is used as a special character to separate filenames from revisions.

If you want to force it to be handled as a normal @ character, just add another @ at the end (the last one, therefore, will be handled as a special one).

More information in this section of the svnbook.

svn commands say: svn: generic failure

Subversion commands can give you the following error:

svn: generic failure

Lots of different reasons can produce this problem. this and this say that this could be a problem with one of subversion dependencies, but in my case the problem was that my machine hostname was different of the name for the address in /etc/hosts. I changed /etc/hosts to match my hostname and it started to work, as indicated by this page.