Migrating from CVS to Subversion

Installation | Conversion | Miscellaneous | Training

Experiences converting Concurrent Versions System (CVS) repositories to Subversion on Mac OS X. A conversion attempt in early 2004 failed due to Berkeley DB wedging. Subversion now supports a new repository format (fsfs) that should avoid such problems. Sites with larger repositories or multiple developers will likely have additional challenges not covered here, such as scheduling the transition, converting existing infrastructure built around CVS, and retraining staff.

Consider also svk, a “decentralized version control system” that “can mirror remote Subversion, Perforce, and CVS repositories to perform offline operations”.


Install both Subversion and the cvs2svn conversion script. Use a ports or package system if possible, to avoid a tedious manual install.

Install Subversion

Obtain Subversion via a ports or package system, such as Fink for Mac OS X.

$ fink install svn-ssl

Manual Install

If compiling Subversion manually, consult the INSTALL under the source directory for complete install notes. For local use only, build Subversion with the --without-apache option. Omit Berkeley DB support and use the default fsfs repository type:

$ ./configure --without-apache

If building Subvesion via Fink, avoid the system-java14-dev error by installing the Java Developer Tools package from Apple.

Install cvs2svn

The cvs2svn script is also available in Fink. If cvs2svn does not install via Fink, python must still be installed, as the version of python that ships with Mac OS X 10.4.2 does not contain a DBM module:

ERROR: your installation of Python does not contain a suitable
DBM module. This script cannot continue.
to solve: see http://python.org/doc/current/lib/module-anydbm.html
for details.

To use cvs2svn from the source tarball, install python via Fink, then run cvs2svn under the source directory:

$ fink install python24-nox python24-nox-shlibs
$ tar xzf cvs2svn-1.2.1.tar.gz
$ cd cvs2svn-1.2.1
$ /sw/bin/python ./cvs2svn
USAGE: cvs2svn [-v] [-s svn-repos-path] [-p pass] cvs-repos-path

cvs2svn can optionally be installed under a bin directory, though the supporting cvs2svn_rcsparse directory must be placed under a PYTHONPATH path for python.

$ mkdir -p ~/lib/python ~/bin
$ chmod +x cvs2svn
$ cp cvs2svn ~/bin
$ cp -r cvs2svn_rcsparse ~/lib/python
$ export PYTHONPATH=$HOME/lib/python

To ensure the correct version of python is used, edit the first line of cvs2svn to point at Fink’s python.

$ cd ~/bin
$ head -1 cvs2svn


The following are a rough list of steps that need to be done. More will be required if network access and multiple users are involved. Be sure to test the conversion several times before the final switch!


If multiple CVS repositories need conversion, they either can be done incrementally, or first combined into a new CVS repository prior to conversion with cvs2svn.

As Subversion allows directories to be copied and moved, the Subversion repository can be rearranged at will. However, spend some time up front considering any layout changes, and how tags and branches will be managed under Subversion (usually via copies to the tags and branchs directories).


The CVSROOT directory may contain scripts and other data that need to be ported to Subversion. Important files under the CVSROOT directory include the commitinfo and loginfo commit handlers, in addition to the checkoutlist file that lists additional files available under CVSROOT.

The Subversion book documents how commit hooks work under Subversion.

Tags & Branches

Before moving anything, investigate the existing CVS repositories for tags and branches. These the cvs2svn script will automatically place under the tags and branches subdirectories of the Subversion repository, though cvs2svn has --trunk-only and other options to adjust tag and branch handling. The cvs-list-symbols script will help list symbols under a CVS repository:

$ cvs-list-symbols /path/to/cvs/repository

If no tags need conversion, remove them from the CVS repository prior to conversion via the cvs-strip-symbols script. This script empties the symbols section of the Revision Control System (RCS) *,v files CVS uses.


Subversion supports keyword properties similar to the keywords supported by CVS. To locate files under CVS repositories using keywords, use something like the following command.

$ cd /path/to/cvs/repository
$ egrep -rl \
'\$(Author|Date|Header|Name|Locker|Log|RCSfile|Revision|Source|State|Id)' *

Code that relies on the $Revision$ and other keywords may need to be changed to work properly under Subversion!

cvs2svn now converts some keywords by default, unless the --keywords-off is set. To manually set keywords under a Subversion sandbox after the conversion, use something like the following, which may run afoul binary files:

$ egrep -rl '\$Id: ' * | grep -v /.svn/ | xargs svn propset svn:keywords Id
$ svn commit


Read the Subversion book for the exact handling of file ignores. In my case, I have tried the following, but it does not appear to be getting set in subdirectories of the Subversion sandbox. Will have to research this more:

$ cat ~/.cvsignore
$ svn propset svn:ignore -F ~/.cvsignore .
$ svn update
$ svn commit .



To bring new developers up to speed with Subversion, consider: Subversion: The Definitive Guide and the Subversion FAQ. Subversion also contains built in documentation, available via the help option:

$ svn help

$ svnadmin help