Using Subversion

Contents

  1. Installing SVN
  2. Server-side commands
  3. Client-side commands
  4. Further reading...

Subversion (SVN) is arguably the most popular version control software. Originally created by Tigris, it is now part of the Apache Software Foundation (and thus distributed under the Apache License).

Version control softwares (also known as revision control softwares or source control softwares) are collaborative tools that aim to resolve problems commonly faced by a team of developers working on the same project. How can everyone on the team work in the same file(s) without overwriting each other? How to keep track of changes, while being able to go back to a previous version if needed? How to maintain multiple versions of the same product, while, at the same time, avoiding a painfully maintainable amount of somewhat similar copies?

Probably the best-known revision system to the general public is the one that is integrated in Microsoft Office since Office 2007. It is the mechanism that provides, among other things, the ability to comment a document in Word and then to go from "bubble to bubble" to revise the document.

Version controllers are also useful when a project is the work of a single person. It provides easy (often off-computer) backup capabilities, with added bonus functionalities like progress logs or the possibility to revert to an earlier version.

For those interested in that sort of thing, source controllers are often used to make statistics about a project: number of lines, growth rate, ...

Every field comes with its bunch of words that describe common concepts in that field. There are quite a few, but here are the essential ones.

A (Subversion) server is the (most often network-enabled) computer on which the Subversion server process runs. It keeps a central version of a project called the repository. That repository can be updated by contributors to the project. Contributors are users of the repository.

Users (most often) use a different computer from the server. Their computer are the clients. They run the Subversion client software to talk to the server. Every user is able to get the project (from scratch, the checkout) or to update their working copy. The working copy is the local copy of the project on a user's computer. It reflects a certain version of the project (not necessarily the latest). Files in the working copy can be edited. It is the user's job to periodically update their working copy to the latest available version on the server. When the version on the server matches the version of the user's working copy, the user can commit the changes into the server. A new version will then be available on the server with the latest changes.

The update process is a totally desynchronized one. Users update on their own will. They do not need to update every time there is a new version, but once they update, their working copy will always reflect the latest changes made to the project.

Subversion is primarily targeted at developers. So it mainly deals with text files. That doesn't mean it can't handle binaries (e.g. icons of a program), just that it can't track changes in them. In text files, on the other hand, it is able to detect (and sometimes automatically correct) conflicts. Conflicts occur when multiple users work in the same file at the same time. (Note that, since the update process is desynchronized, "at the same time" really means "between two successive updates of a working copy".)

The model used by Subversion is the server/client one. There is a single server and every user connects to it to make or get changes. Other version controllers (e.g. Mercurial) use a distributed model in which multiple servers are available and punctually synchronize with each other. A user can then select one of these servers (usually the closest to them) to work with. Like always, advantages may come out of that distributed infrastructure: if a server fails, the others will still work; any of the server is able to completely recreate another server's repository; ...

This article will focus on the use of Subversion. I will not talk about branching (the "how to have multiple similar projects" part). Originally, I intended to do a simple aide-mémoire for myself with the common commands that I use. Then I decided to cover the possible authentication methods for Subversion, since I couldn't find anything that suited me when I installed Subversion. So the page gradually grew to become this. Hopefully, it will be useful to someone :)

Installing SVN

Server

Unix / Linux

The subversion server is most likely available in your package repository. In Archlinux, the package name is subversion.

Once installed, you may want to configure your system to run the subversion server as a service by adding svnserve in your rc.conf file (or inetd.conf, or what have you).

Usually, only limited rights are given to svnserve. Hence, it is usually not run as user System. Most often, a specific user (say user svn) will be created to run the daemon.

Systems using rc.d can edit the script located at /etc/rc.d/svnserve and add

SVNSERVE_USER = "svn"

Arguments to the daemon can be given by modifying the SVNSERVE_ARGS variable. As such,

SVNSERVE_ARGS = "--root /home/svn/repositories"

sets the repository root path to /home/svn/repositories. Other popular locations are /srv/svn or /var/svn. Don't forget that if you're running the server as user svn, user svn has to have read and write privileges to that base path.

Sysems using inetd.d can edit file /etc/inetd.conf and add the following line to it:

svn stream tcp nowait svn /usr/bin/svnserve svnserve -i --root /home/svn/repositories

where the first svn is the service name for Subversion, as defined in /etc/services while the second one is the username to run the daemon as. /usr/bin/svnserve is the full path to svnserve. Finally, the -i option tells svnserve that it is being run through inetd.d.

If your distribution uses another initialization program, you probably know better than me how to achieve that configuration on it. If not, consult your distribution's documentation.

To manually launch the SVN server, run svnserve in a terminal.

Windows

A pre-packaged version with a graphical installer is available at CollabNet. (You must be registered with CollabNet to be able to download, but the registration is free.)

Once installed, you may want to configure your system to run the subversion server as a service. In order to do so, you can (graphically) add an entry in services.msc. Alternatively, you can enter the following command in a command prompt:

sc create svnserve binpath="\"C:\Program Files\CollabNet\Subversion\" --service --root C:\svn_repositories" displayname="Subversion" depend=tcpip start=auto

Obviously, C:\Program Files\CollabNet\Subversion is the path you have decided to install SVN in. C:\svn_repositories is the base path for every repository (i.e. that means every repository is located in C:\svn_repositories). The whole --root C:\svn_repositories is an optional argument to svnserve, but it is good practice to specify it. Please note that if there is any space in the root repository path, the correct way of specifying it would be (for example) --root \"C:\My Documents\svn_repositories\" (i.e. with the escaped quotes \").

If Windows asks you choose an account to run the service as, select the local service account (NT AUTHORITY\LocalService on systems in English). You can also specify it by appending obj="NT AUTHORITY\LocalService" to the previous command.

To manually launch the SVN server, run svnserve in a command prompt.

Change the listening port

The default port for SVN is 3690. If, for some reason, you want to change it to something else (say 3691), you only need to append

--listen-port=3691

to the arguments passed to svnserve.

Authentication methods

Multiple methods for authenticating the client can be used.

The basic authentication is the default mode that "works out of the box". It authenticates a user with a (classical) username/password combination. However, all exchanged data (authentication or not) is not encrypted. It is the most popular method for authenticating users with SVN (probably out of laziness). No further configuration is requested to use the basic authentication. To setup username/password entries associated with a repository, see section Create a repository.

Authentication can also be carried out under SSL. Obviously, the exchanged informations are then protected via SSL. The SSL part is carried out by a third-party software.

The most common third-party is the Apache web server. (Don't forget that the Subversion project is now handled by the Apache Software Foundation.) Apache will then use the HTTP header-based authentication to provide access.

For those who don't have (or don't want to use) Apache, the Cyrus SASL library can be used to provide secured data exchange.

Finally, SVN authentication can be done through SSH. In that case, the client first signs in with SSH (which means every contributor to the repository must also be a system user), and then plain-text SVN informations are exchanged within encrypted SSH packets.

Authentication over SSL with HTTPS (and Apache)

Make sure that modules mod_dav, mod_dav_fs, dav_svn_module, and authz_svn_module are correctly installed, loaded and enabled.

Then, edit file /etc/apache2/mods-enabled/dav_svn.conf and add

<Location /svn>
    DAV svn
    SVNParentPath /home/svn/repositories
    AuthzSVNAccessFile /home/svn/.svn-policy
    AuthName "Subversion Repositories"
    AuthType Basic
    AuthUserFile home/svn/.svn-auth
    Satisfy Any
    Require valid-user
</Location>

/home/svn/repositories is, like above, the root path for the repositories. Please note that, now, user svn is not the only one who should be able to access it. User www-data (or whatever Apache runs as on your system) also has to.

Modifying dav_svn.conf results in making each of your virtual hosts svn URLs handled by subversion (i.e. http://virualhost1.tld/svn and http://virualhostN.tld/svn will both be handled by SVN). If you want to restrict SVN handling to a particular domain, instead of adding the previous code to dav_svn.conf, put it directly in /etc/apache2/sites-available/virtualhost under the <VirtualHost> tag. To make it only available under SSL (i.e. only with HTTPS), add it to the virtual host entry that handles HTTPS traffic (usually the <VirtualHost IP:443> one). (Obviously, this authentication method works just as well without SSL, but why would you go through all this trouble if you're not going to gain on privacy? If you don't want to have encrypted data streams, you might just stick to the basic authentication.)

Obviously, the above configuration relies on two other files: /home/svn/.svn-policy and /home/svn/.svn-auth. The first one defines policies by user for a repository. The second one stores the user/password associations.

Please note that because the authentication file is global (i.e. the .svn-auth is unaware of the different repositories), a single user will not be able have different passwords for different repositories.

I cannot stress hard enough that if you're going to use this method of authentication, it is

  1. ridiculously complicated if you're not going to take advantage of SSL encryption,
  2. necessary that Apache (i.e. user www-data) can access all the requested locations; that includes the repositories, and the policy and authentication files.

Normally, this whole configuration should work just as well on Windows, provided that you change the paths to the Windows equivalent ones. (I've always found it cumbersome to work with Apache modules on Windows).

Authentication over SSL with Cyrus SASL

The Cyrus Simple Authentication and Security Layer is a software library developed by folks at Carnegie Mellon University. It enables authentication and encryption capabilities for any network protocol. Since version 1.5, Subversion has been able to use that library.

Once SASL is installed, you have to create a configuration file for svnserve, let's call it svn.conf. Windows users will find it convenient to put it in the installation directory of the svnserve executable. For Unix / Linux users, that executable is most likely located in /usr/bin and you will certainly not want a configuration file there. Put it wherever you like (hint: /home/svn/svn.conf), and append

--config-file /home/svn/svn.conf

when you call svnserve.

Fill that file with the following informations:

pwcheck_method: auxprop
auxprop_plugin: sasldb
mech_list: DIGEST-MD5
sasldb_path: /home/svn/.sasldb

The sasldb database contains username/password associations. Please note that the service has to be able to access that file. So, if you specify the --root argument when you run svnserve (if not, you really should!), the database has to be somewhere in there. So it will certainly be located in a common parent directory to all the repositories.

Finally, the SVN server has to be aware of the location of the SASL library. In Unix / Linux, that means svnserve must be compiled with SASL support enabled. In Windows, if you've installed the CollabNet version, everything has already been taken care of. If not, you should add two string keys in HKEY_LOCAL_MACHINE\SOFTWARE\Carnegie Mellon\Project Cyrus\SASL Library:

  1. SearchPath with the directory containing the sasl*.dll files,
  2. ConfFile with the directory containing the svn.conf file.

I cannot seem to understand how to provide read-only access to authenticated users with this method so maybe it is not (currently) possible. If read-only encrypted access is important to you, you may want to check another authentication method.

Authentication with SSH

When tunneling SVN into SSH, it is unnecessary to run the Subversion server as a daemon. Indeed, whenever a user logs in svnserve can be run (with that user's rights), and terminated when the user logs out.

File rights management is trickier when using this method, since it is the real end-user that accesses the repository (not some fictional user svn). Some administrators like to create a group per project and assign the rights to the repositories by groups. Others just manage each repository directly with usernames. It is your task to decide whether you prefer having a lot of groups (if so, please, use some sort of prefix to the group names to know what is SVN and what is not), or if you'd rather manage everything user by user, and eventually have an "imperfect" user management). Just remember that each user is granted the rights they have on a repository's directory.

It may seem that this is the "shortest way to privacy". However, beware that a bad management of SSH access to your server may have catastrophic consequences. Common sense applies: if you don't know what you're doing, don't do it... (or rather learn how to do it :).

Client

Unix / Linux

The subversion server is most likely available in your package repository. In Archlinux, the package name is subversion.

Windows

A pre-packaged version with a graphical installer is available at CollabNet. (You must be registered with CollabNet to be able to download, but the registration is free.)

Server-side commands

Create a repository

To create a new repository, open a console/command prompt and go to the root directory for your repositories. Then type

svnadmin create myRepository

where myRepository is the name of the repository to create. Alternatively, you can use the full path to the repository:

svnadmin create /home/svn/repositories/myRepository

Once the command is executed, a new directory should be located in the root repository folder. It should contain (at least) a conf directory.

Add users to the repository

The method to add users to a repository depends on the authentication method you have selected. (Please note that it is possible to select different authentication methods for different repositories. You can also imagine authenticating some users via SSH, while others use an SSL-based authentication, etc.)

Basic authentication

To add a user to the basic authentication, first edit the file myRepository/conf/svnserve.conf. In the [general] section of the file, you can find

anon-access = read
auth-access = write

Quite self-explanatory, but in case you didn't get it, anonymous access is granted a read-only right, while authenticated users have read-write capabilities. The values can be any of the three following values : none, read, write. Edit the entries to match your goal.

A bit further down, still in the [general] section, make sure that the line

password-db = passwd

is not commented (i.e. it doesn't start with a sharp character (#)).

You can also specify the realm by editing the line

realm = My repository

(and make sure it is uncommented). The realm is a sort of "authentication domain" for SVN. Beware that two realms mustn't be identical on a server.

Save that file, close it, and open passwd located in the same folder.

In the section [users] of passwd, you can add users with the following format (one entry per line):

username = password

Yes, the password is stored in plain-text.

Once you're done, save the file and restart svnserve (I'm not sure it is necessary on every system).

The repository is now available at

svn://domain.tld/myRepository

Authentication over SSL with Cyrus SASL

Just like in Basic authentication, start by editing myRepository/conf/svnserve.conf. You can comment (i.e. add sharp characters (#)) the whole [general] section, since it will be disregarded when using SASL, except for the realm line

realm = My repository

Make sure it is uncommented, as you will need the realm value further down. The realm is a sort of "authentication domain" for SVN. Beware that two realm mustn't be identical on a server.

In the [sasl] section uncomment the lines (i.e. remove the sharp character (#))

use-sasl = true
min-encryption = 0
max-encryption = 256

Obviously, you can set whichever value you fancy for the minimal/maximal encryption value. I recommend you leave the maximum set to 256 (bits), but increase the minimum to 128 (bits).

When you're done, save the file and close it.

In a console/command prompt type

saslpasswd2 -c -f /home/svn/repositories/.sasldb -u "My repository" username

saslpasswd2 is an utility from the SASL library that sets a password for a user. -c indicates that it will create an entry if it doesn't already exist. -f is the (full) path to the sasldb (see subsection Authentication over SSL with Cyrus SASL in the Installing SVN section). -u is the domain. In our case, it is the realm of the repository. Finally username is the username of the user you want to add to the repository. saslpasswd2 will then prompt you to enter the user's password.

Please note that if you have any space in any of the arguments of the previous command (and that include the full sasldb file path), you should use quotes (") around them (just like in the example with My repository.

If you want to remove a user from a domain, you can call saslpasswd2 with the -d argument (which deletes a user) in the following fashion:

saslpasswd2 -d -f /home/svn/repositories/.sasldb -u "My repository" username

Once you're done, save the file and restart svnserve (I'm not sure it is necessary on every system).

The repository is now available at

svn://domain.tld/myRepository

Authentication over SSL with HTTPS (and Apache)

Let's now define the policy (/home/svn/.svn-policy) and user/password association (/home/svn/.svn-auth) files we talked about earlier.

The policy file should look something like this:

[/]
*=r

[myRepository:/]
user=rw

The asterisk (*) is the anonymous access. user is a user for repository myRepository. Obviously, anonymous users have a read-only right, while user user has read-write rights over the myRepository repository. Please note that rights for myRepository are inherited from global rights (in section [/]) so that myRepository also allows read-only access for anonymous users. If you don't want to have anonymous reading rights, you can always overwrite the access with *= in the [myRepository:/] section which grants no right for anonymous users.

The user/password file is something similar to the usual .htpasswd mechanics used in Apache. To add a user, type, in a console,

htpasswd -s /home/svn/.svn-auth username

You will then be prompted to enter the password. The -s option enables the use of the SHA-1 hash algorithm (instead of the default MD5). The first time you add a user, you may also want to use the -c option which creates the file.

The repository is now available at

https://domain.tld/myRepository

Alternatively, if you decided not to use SSL (and HTTPS), the address becomes

http://domain.tld/myRepository

Authentication with SSH

Make sure the user already has an SSH access to your server.

Create the script /usr/local/bin/svn containing

#!/bin/sh

umask 002
/usr/local/subversion/bin/svn "$@"

which is a wrapper for svnserve. The umask value 002 is a umask that prevents access by other users.

Then, give read-write permissions for the group (or for the user) to the repository directory.

The repository is now available at

svn+ssh://domain.tld/home/svn/repositories/myRepository

Please note that, in this case, both, the repository name (myRepository) and the full path to the repository directory (/home/svn/repositories) are part of the address. The repository path is needed for SSH.

Backup a repository

A backup file of a repository can easily be created. It can be used as a real backup or as means to transfer a repository to another SVN server.

The dump command creates a dump of the repository. Generally speaking, a dump is a raw copy of an object. In this case, the object is the repository. So, you are making a raw copy (i.e. in exactly the same format) of a repository.

To create a dump file of the repository, type the following command (as usual, in a console/command prompt):

svnadmin dump /home/svn/repositories/myRepository > ~/myRepository.svndmp

/home/svn/repositories/myRepository is the full path to repository myRepository. ~/myRepository.svndump is the full path to the repository dump file (which will be created).

The file myRepository.svndmp contains the whole repository (that includes the different files in the repository, the commits history and logs, ...).

You can store that file or move it as any other file on your system. To add it to another SVN server, use the load command.

Please note that if you're not using the basic authentication, you will have to reconfigure users' accesses if you lose your SVN server. If you use Apache's BasicAuth to authenticate users, backup the .svn-policy and .svn-auth files. If you're using Cyrus SASL, backup the sasldb. Although all of these files contain more than user configurations for myRepository, they certainly do contain it too. You can always manually merge (or recreate) the files on your new server. For the SSH authentication, well... it's all tied to your system: backup your system! (But then why wouldn't you backup the whole /home/svn/repositories/ with it?)

Reload a backup

The load command loads an SVN dump file into an existing repository.

The first thing you have to do is to create a new repository. You do not, however, need to worry about user configuration now.

To load an SVN dump into that new repository (which we'll call newRepo), use the following command :

svnadmin load /home/svn/repositories/newRepo < ~/myRepository.svndmp

Obviously, you don't need to give the full path to newRepo if you execute the command from the /home/svn/repositories/ location. ~/myRepository.svndmp is the full path to the repository dump file.

If your original repository was configured to use basic authentication, you're all set.

If you use any of the other authentication methods, you will need to properly reconfigure users' accesses, as indicated in the Create a repository section.

If you're wondering why you have to reconfigure users, just remember that, when using another authentication than the basic one, it is a third-party software (i.e. an entity outside of svnserve's control) that manages accesses to your repository. So, the SVN server can't be aware of those settings since it doesn't "contain" them.

Client-side commands

Checkout

A checkout is the initial import of the project on your computer: it creates the working copy. You only need to do it the first time you connect to the SVN server.

To checkout a repository, use the following command :

svn checkout svn://domain.tld/myRepository project --username user

where svn://domain.tld/myRepository is the address of the repository and project is the local location to put the files in. (Obviously, if you want to put it in the current location, just use a point (.) as the location.) If you do not specify the location to checkout in, the SVN client will create a folder named like the repository in the current location. user represents the username to log in as. (You will be prompted for your password afterwards.)

After you've been prompted for your password, SVN will ask you if you want your password to be memorized. You have to know that the Subversion client stores passwords locally as plain-text. If it is important to you that your password is not stored in that way, just answer no. You will then be prompted for your password on every svn command you call.

A shortcut for checkout is co so that the shortened command becomes

svn co svn://domain.tld/myRepository project

Checkout can be a long process. It all depends on the size of the project and the speed of your network connection.

Once the working copy is created, you can modify any of the files in it; add (and remove) files to (from) it. However, don't edit (or remove) any of the .svn directories (or whatever is in it). They are part of the SVN mechanism. Should you delete/edit them, you will end up compromising your working copy and you won't be able to do anything with it (except delete it and perform a new checkout).

Update the working copy

The update command updates your working copy by reflecting the changes that have been made in the repository into your local files.

An update is significantly shorter (in time) than a checkout. Performing one regularly ensures that your working copy is up to date (which, in turn, might save you from having to deal with conflicting versions).

To perform an update, type the command

svn update

A shortcut to update is up so that the shortened command is

svn up

update produces an output very similar to status. Don't forget to check the file states to check it for possible version conflicts.

If you want to "go back in time" and update your working copy to an older version of the project, you can specify the revision number with the -r option. The following version upgrades (although it should really be "downgrades") to version 4:

svn up -r4

(you never really lose anything with SVN).

Add (and remove) files to (from) revision control

When you create a new file (or directory) in your working directory, that file isn't automatically added to version control (i.e. Subversion doesn't "take care" of it until you've told it to).

To add your file to revision control, execute the following command in a location that's already version controlled:

svn add filename

filename is the name of the file (or directory) to add to control version. If filename is a directory, it will be processed recursively. If you don't want it that way, you can specify the argument --non-recursive, and the command becomes

svn add --non-recursive directory

A shortcut for --non-recursive is -N, so that the shortened version is

svn add -N directory

To remove a file from revision control, you can just delete it from the working copy. Alternatively, you can use the command

svn delete filename

where filename is the name of the file to remove from version control. filename can also be a directory. In that case, the directory (and therefore everything that's inside it) will be removed from version control.

Shortcuts for delete exist. They include

svn rm filename

just line Unix's rm command. One other alternative is

svn del filename

just like the del DOS command.

If you want to remove control version from a file that's been locally modified, you will have to force the removal. Hence, the command becomes

svn rm --force filename

These commands all remove the file both from the local copy and from the repository. In order to remove a file from revision control, but still keep it locally (e.g. a file that was committed, but that should have been ignored), you can use the --keep-local argument, as follows:

svn rm --keep-local filename

Ignore files

You may have files in your working copy that you never want to be "managed" by SVN. You shouldn't normally have build files in your SVN, so that's a good examples of files to be ignored.

Subversion has a bunch of properties. One of them is svn:ignore. It is the property that is going to be modified to ignore certain files.

Let's imagine you have a build directory in your repository. Everything under it should be ignored by version control. (Arguably, you could also ignore the directory itself, but if you want it to appear in the structure of the project, only its contents will have to be ignored.) In order to do so, from inside build, type

svn propedit svn:ignore .

The final point (.) indicates that we want to edit the properties (hence the name propedit) for the current location (i.e. location .).

A text editor should open (e.g. nano, vim, notepad, ...). Add masks for files to ignore (one mask per line). In this case, you want to ignore everything, so we will just add an asterisk (*) in the file. (If you only wanted to ignore HTML files, the mask would be *.html (and maybe *.htm).) Save the file in your editor, and close the editor. Filenames that match your mask(s) will then be ignored by SVN.

To change the editor in which the svn:ignore properties are opened, change the SVN_EDITOR environment variable (this is out of the scope of this article, but it is a widely available information).

To make sure everything went according to plan, you can type

svn propget svn:ignore .

(the syntax is similar to propedit), and you will have the list of everything that's ignored in the target location.

Status

You can view the current status of your working copy at any time. Status includes informations about which file was modified, which file was added, which file was modified, ...

To view the status, type

svn status

in a location that is under revision control. By default, status doesn't display the ignored files. To display them, use the option --no-ignore:

svn status --no-ignore

The shortcut command for status is st:

svn st

Here's a typical status answer:

?      temp
D      README
I      doc/report/tex/CuteSNMP.dvi
I      doc/report/tex/CuteSNMP.ps
I      doc/report/tex/CuteSNMP.pdf
M      doc/report/tex/CuteSNMP.tex
A      doc/report/tex/new

Statuses are indicated in the left column. ? means that the file is not currently under revision control. I means that the file is ignored. M means that the file has been modified since the last commit or update (i.e. the file has local changes). A means that the file is new and has been added to revision control (it is not considered as a "regular" file until it has been committed). Finally, D means that the file has been removed from revision control.

If you type status at the root of your working copy, every directory will be recursively processed (like in the example above). To "filter", just change the location in which you type the command. For example, if I had typed the above command in doc/report/tex, only the files in that location would have been displayed, leaving the files located at the root (i.e. temp and README) out of the result.

Three more statuses exist. They represent file conflicts. They are status U (update), G (merGe), and C (conflict). For more details about these status, refer to section Conflicting versions.

Commit changes

Committing your working copy pushes the changes you've made to the project onto the Subversion server. It is the "inverse" operation of update.

To commit your changes, type the following command:

svn commit --message "Commit message"

The commit message is used as a log entry in the commit logs. It is mandatory to put one, although it can be an empty string (i.e. "").

Alternatively, you can use a file as the commit message, with the following command:

svn commit --file commit_message_file

where commit_message_file is the file in which the commit message is. It can be advantageous to use a file instead of an in-line message since it is easier to fill-in (in terms of formatting, etc) and can be written while the changes are made to the project (so that the log is completely accurate).

As usual, there are shortcuts for this command too. commit can be replaced by ci (not co which is the shortcut for checkout). The short for --message is -m and the one for --file is -F. The shortcut commands for the previous ones are

svn ci -m "Commit message"
svn ci -F commit_message_file

Please note that if Subversion tells you that you can't commit because your working copy is not up to date, you have to do an update first. At this point, you should be very careful for version conflicts. If you have unresolved conflicts you will not be able to commit.

Conflicting versions

Typically, there are multiple contributors to a single project. These contributors may even work in the same file (at the same time). The initial goal of revision control is to avoid problems when that happens. There is no use in updating your work on the server if, when you're doing it, someone else's work is deleted.

The previous scenario leads to conflicting versions: while you were working on a file, someone else was working on it too, and the working copy you have done your work in is not up to date anymore. You can't just send it to the server, you have to merge the two different versions of the file. In other words, you have to resolve the conflict.

As noted in the status section, there are three types of conflicts:

  1. The version of the file in the repository has been updated to a new version and your local copy has not changed. (Status U)
  2. The version of the file in the repository has been updated, and so has your local copy. The changes, however, do not overlap. (Status G)
  3. The version of the file in the repository has been updated, and so has your local copy. In this case, the changes do overlap. (Status C)

In the first two cases, Subversion handles the conflicts all by itself:

  1. Replace local copy with repository version.
  2. Merge the two version in a single file (easily done algorithmically since changes don't overlap), and mark that file as changed and ready for the next commit.

Unfortunately, the last case can't be handled automatically. SVN will mark the file as conflicting (meaning that you can't commit it until you've marked the conflict as resolved). To help you do the merge manually Subversion creates three new files:

Please note that conflictingFile is a representation of the filename, not its actual name. If the conflicting file is foo.cpp, the old revision number is 31, and the new one is 36, the you will have the four following files in your directory: foo.cpp, foo.cpp.mine, foo.cpp.r31, and foo.cpp.r36.

To understand how they work, here's a little example (taken from the SVN book). Open conflictingFile (i.e. the (new) content of the file that is in conflict). It will look something like this (the example is a grocery list):

Mayonnaise
Lettuce
Tomato
Provolone
<<<<<<< .mine
Salami
Mortadella
Prosciutto
=======
Sauerkraut
Grilled Chicken
>>>>>>> .r2
Creole Mustard

The lines filed with <<<<<<< .mine, =======, and >>>>>>> .r2 are conflict markers. They are not part of the original data in any way. Whatever you do, make sure you don't leave them in the final (resolved) file. (Also, please note that none of the three files conflictingFile.mine, conflictingFile.rOLD, and conflictingFile.rNEW have any sort of marker in them.)

The part between <<<<<<< .mine and the equal signs (=======) are the changes you made to the file. The changes made by the other contributor are between those equal signs and the >>>>>>> .r2 separator.

Your job is to make that section of the file (i.e. the one between <<<<<<< .mine and >>>>>>> .r2) coherent (and to remove the conflict markers).

Once you're done, the conflict can be marked as resolved. In order to do so, type

svn resolved conflictingFile

You can also delete the three conflict files conflictingFile.mine, conflictingFile.rOLD, and conflictingFile.rNEW.

Please note that there can be more than one conflict in a single file (and more than one conflicting file). Make sure you sort them all out!

You can resolve the conflict in other ways if you like. If you just want to replace the file with the latest version, delete conflictingFile and rename conflictingFile.rNEW in conflictingFile, then mark the conflict as resolved. In the same fashion, you can put your file as the new version. You can also revert to an older file version. (If you choose to revert, Subversion will automatically mark the conflict as resolved, so you won't need to do it.)

You are now ready to commit.

Revert to an older version

If for some reason you are not satisfied with the changes you've made to the project, you always have the option to revert to the previous version. In other words, you will erase any local change you made and get the files you had the last time you performed an update.

To revert the changes made to myFile, just type

svn revert myFile

You can also revert the changes made to a directory (say myDir):

svn revert myDir

If you want SVN to recursively process the subdirectories of myDir, you can specify the --recursive option:

svn revert --recursive myDir

A shortcut for --recursive is -R, so that the last command becomes

svn revert -R myDir

Please note that specifying no target location for the revert will have no effect (to prevent you from losing every changes you made by accident).

If you want to go further down than the latest update revision number, you can make use of the update command. Although not specified in the corresponding section, you can specify a target file for update (so that it only updates that single file). To revert back file myFile back in time to revision 82, you can use the following command:

svn update -r82 myFile

View commit logs

The messages you entered while committing can be viewed with the log command.

Calling

svn log

from inside a working copy displays the whole commit log. Here's a typical output of that command

------------------------------------------------------------------------
r83 | q | 2010-05-22 18:29:30 +0200 (sam., 22 mai 2010) | 4 lines

Corrected bugs:
    - Program assertion failing when changing current user name
    - Removed displayed MIB when failing to process a walk on a new agent

------------------------------------------------------------------------
r82 | q | 2010-05-22 07:58:40 +0200 (sam., 22 mai 2010) | 1 line

Bug correction
------------------------------------------------------------------------
r81 | murmex | 2010-05-22 06:05:05 +0200 (sam., 22 mai 2010) | 1 line

correct debug messages
------------------------------------------------------------------------
r80 | murmex | 2010-05-22 05:58:34 +0200 (sam., 22 mai 2010) | 1 line

removing unused files

Let's see in details what the header means. The number number following r (e.g. r83) is the revision number (e.g. it was the 83rd commit). The second column is the user that committed (here: q). It is followed by the commit date and by the number of lines in the commit message (here: 4). The header is followed by an empty line which, in turn, is followed by the whole commit message.

You can search for the commit logs that modified a file. The command is then

svn log filename

and the result will be the commit logs of the commits that modified filename.

You can also restrict the commit logs to certain revision numbers. For example, to get the commit log of revision number 6, type

svn log -r6

To get the commit lots of every revision between revision 23 and 32, use the following command:

svn log -r23:32

Notice now the colon (:) separates the bounds of the revision numbers to show.

Please note that you need to be able to access your SVN server to use the log command, as the logs are not stored locally on the client side.

A few more tips

It can be overwhelming to have all those log outputs in your console/command prompt. Here are a few basic tips (this is more dedicated to Windows users, since it is pretty common knowledge in the *nix world):

svn log | more

which will "send" the output in the utility more that will display the text on a single screen height. You can then press the enter key to "scroll" down. (Yes, I know, it is more convenient to use less but more works on Windows too!). You can also redirect the output to a file:

svn log >> svn_log.txt

and the file svn_log.txt will be created in the current directory with the contents of svn log. If svn_log.txt already existed before, the new content will be appended to the file.

These stream redirection mechanism not only work with svn log commands, or svn commands: any console/command prompt application that outputs on the standard stream (it is most often the case if there is no user interface) can have its (standard stream) redirected that way.

Relocate

Sometimes, funny business happens: a server changes its hostname, the repository is moved to another server, ... As checking out a project can be quite costly, it would be interesting to only locally change the address of the repository so that the local working copy keeps on going.

The switch command allows you to do that. Here's how to use it:

svn switch --relocate svn://old-address.tld/oldRepository svn://new-address.tld/repository

where svn://old-address.tld/oldRepository is the old address of the repository and svn://new-address.tld/repository is the new address of the repository.

Please note that it will only work if the repositories on both addresses have the same UUID. In other words, it will only work if the SVN server administrator correctly did its work of moving the repository around with the dump command.

To check if relocating succeeded, you can use

svn info

and check if the value given in URL is the new one.

Further reading...

For more in-depth informations about Subversion (including functionalities not discussed in this article), consult Version Control with Subversion by Ben Collins-Sussman, Brian W. Fitzpatrick, and C. Michael Pilato.

Revisions

Last modified: Wednesday, October 10, 2012, 13:17:25 (Europe/Brussels).