from cvs to subversion

Subversion was written by the maintainers of CVS and is the upcoming alternative to CVS. Over the years CVS has become the de-facto standard of source code management systems.

But CVS has also grown old:

concept

The most visible difference between CVS and Subversion is that while CVS provides tags and branches, Subversion just uses copies as if you were using no source code management system at all:

mkdir branches
mkdir tags
mkdir src
cd src
tar -xzf myproject.tar.gz
cp -r myproject ../branches/EXPERIMENTAL
cp -r myproject ../tags/RELEASE_1_0_0

Contrary to a normal copy operation Subversions copies

Subversion comes with two different database backends: Berkley DB (BDB) and Filesystem Filesystem (FSFS). Berkley DB uses less space than FSFS but had some issues in that past which could corrupt the database because Subversion uses it in some unusual ways.

When using Subversion on a remote server it is recommended to use it along with an Apache so Apaches sophisticated user management can be used. There is a special Subversion module for Apache.

initialize repository

CVS vs. Subversion Comment
Create Repository CVS cvs -d path init repository is a directory path for the svnadmin command, the other command, svn, will use the URL syntax.
Subversion svnadmin create repository
Import Sources CVS cd src
cvs -d repository import module vendortag releasetag
Subversion doesn't know of tags or branches. Instead you use the 'snv copy' command to create a copy of the directory you want to preserve. Subversion takes care that this is efficient.
Because of this its it suggested, that the root of your directory contains three directories:

  • trunk: is where you store the main or HEAD branch
  • tags: is where you copy the 'tags' to
  • branches: is where you copy the 'branches' to
Subversion svn mkdir file://repository/tags
svn mkdir file://repository/branches
svn import src file://repository/trunk


or in case of a remote repository:

svn mkdir https://repository/tags
svn mkdir https://repository/branches
svn import src https://repository/trunk

Checkout CVS cvs -d repository co [-d directory] module Checkout of a file/directory from the repository.
While CVS keeps its information within a CVS/ directory, Subversion uses a .svn/ directory which contains a complete copy of the checked out files. This will be used for comparation during the next commit which makes commits fast over slow network connections.
Subversion svn checkout file://repository/trunk module [directory]

Subversion comes with two different database backends: Berkley DB (BDB) and Filesystem Filesystem (FSFS). Berkley DB uses less space than FSFS but had some issues in that past which could corrupt the database because Subversion uses it in some unusual ways.

In case FSFS is not the default database backend, you can specify it manually:

svnadmin --fs-type fsfs create repository

routine tasks

CVS vs. Subversion Comment
Diff CVS cvs diff -u [-r tag1 -rtag2] [file] Print a unified diff of the changes in the current working directory against the last checkout/update.
Subversion svn diff [-r rev1:rev2] [file]
Commit CVS cvs commit Commit changes to the repository.
Subversion svn commit
Update CVS cvs update Merge changes from the repository.
In case of conflicts the conflicts are marked in the files as done in CVS. Additionally three files are generated:

  • file.mine: your version before the update command
  • file.oldrev: the version you've got from the repository
  • file.newrev: the current HEAD in the repository
Subversion svn update
Resolve conflicts CVS vi file Tell Subversion that an update conflict is solved.
This command removes the 3 additional files being created during the update conflict and allows you to commit the files.
CVS just looks that the file was touched after it found the conflict.
Subversion vi file
svn resolved file
Revert changes CVS rm file
cvs update file
Revert your changes to a file.
Subversion svn revert file
Move/Rename CVS mv old new
cvs remove old
cvs add new
cvs commit old new
Subversion svn move old new
Copy CVS cp old new
cvs add new
cvs commit new
Subversion svn copy old new
Add CVS cvs add file
Subversion svn add file
Remove CVS rm file
cvs remove file
Subversion svn remove file

Version History

CVS vs. Subversion Comment
Current Status CVS cvs status [file] Shows the information about the current status of a file.
Subversion svn info [file]
Commit Log CVS cvs log [file] Shows the history of all commits.
Note: Subversion requires you to run svn update to see the last commit in the log history.
Subversion svn log [file]

working with branches

CVS vs. Subversion Comment
Checkout CVS cvs -d directory co repository
cd directory
Checkout was already mentioned on the initialize repository page, but to simplify the examples below, the subversion command show here checks out the the full repository, so that copying to the tag and branch directories becomes easier.
Subversion svn repository directory
cd directory/trunk
Create Branch CVS cvs tag MYBRANCH_0
cvs tag -b MYBRANCH
The examples shown here do a bit more than just creating a branch because from time to time you may want to merge parts of a branch into another branch and to do so, you need to specify a start- and an endpoint which span the changes you want to merge into another tree.
Because of this it is recommended for CVS to create a tag when a branch is created (MYBRANCH_0 in this example) and a tag (MYBRANCH_1 in the example below) when you do the merge so that successive merges can be done from MYBRANCH_0 to MYBRANCH_1, MYBRANCH_1 to MYBRANCH_2 and so on.
The same can be done with subversion but you may also use Subversion's revision numbers instead of tags and provide the required information in the commit messages instead.
(The names “MYBRANCH” and “MYBRANCH_...” are just an example.)
Subversion cd ..
svn copy trunk tags/MYBRANCH_0
svn copy trunk branches/MYBRANCH
svn commit

or

svn copy trunk branches/MYBRANCH
svn commit -m "created branch MYBRANCH"

List available tags and branches CVS cvs status -v some file In CVS you guess the oldest file in your repository and run 'cvs status' on it. In SVN you list the contents of the tags or branches directory.
Subversion svn ls repository/tags/

or

svn ls repository/branches/

Switch to Branch CVS cvs update -r MYBRANCH Switch to the branch.
With CVS you can convert your current working directory into another branch and “cvs status” can show you in which branch certain file resides. (Yes, as CVS is file based, files in a single directory may belong to different branches but this is unusual.)
With Subversion you just change directories when you checked out all branches or you run “svn checkout” for the branch.
Subversion cd branches/MYBRANCH

or

svn checkout repository/branches/MYBRANCH

Switch to HEAD/trunk CVS cvs update -A Switching back into the HEAD/trunk branch.
Subversion cd ../../trunk

or

svn checkout repository/trunk

Merging from another Branch CVS cvs tag -r MYBRANCH MYBRANCH_1
cvs update -kk -j MYBRANCH_0 -j MYBRANCH_1
cvs commit -m "merged MYBRANCH_0 to MYBRANCH_1"
From time to time one my merge changes from one branch into another. The row Create Branch above also explained why CVS requires the role of tags during a merge and the alternatives in subversion.
The “-kk” option given to CVS tells CVS to ignore its keyword substitution, otherwise the merge may create a bunch of additional useless conflicts.
The merge's commit message should always tell what has been merged so you can see how to avoid overlaps in subsequential merges.
The second Subversion command shown on the left uses revision numbers instead of tags.
Subversion svn copy ../branches/MYBRANCH ../tags/MYBRANCH_1
svn merge ../tags/MYBRANCH_0 ../tags/MYBRANCH_1
svn commit -m "merged MYBRANCH_0 to MYBRANCH_1"

or

svn merge -rfrom:to ../branches/MYBRANCH
svn commit -m "merged from:to of branch MYBRANCH"

remote subversion server

When using Subversion on a remote server it is recommended to use it along with an Apache so Apaches sophisticated user management can be used. There is a special Subversion module for Apache.

In case you are compiling subversion on you own, you will need to pass the --with-apxs and --with-apr options to Subversion's configure script.

The Apache configuration file needs the following entries:

Modules

# authentication by password file
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule authz_host_module modules/mod_authz_host.so
# 'Require user' directive
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule auth_digest_module modules/mod_auth_digest.so

# SSL for encrypted passwords and trustworthy source download
LoadModule ssl_module modules/mod_ssl.so

# SVN and its required DAV support
LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule dav_svn_module  modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so

HTTPS

DocumentRoot /var/https/svn

# assume all sources are UTF-8 encoded (only required when browsing the
# repository with a web browser)
AddDefaultCharset utf-8

# activate HTTPS
Listen 443
SSLCertificateFile    /etc/apache2/certificate.pem 
SSLCertificateKeyFile /etc/apache2/privatekey.pem
SSLEngine             on
# only use TLSv1 for maximum security
SSLProtocol           -all +TLSv1

Repository

# publish /var/svn/foobar as https://foobar/
<Location /foobar>
  DAV svn
  # path to the Subversion repository
  SVNPath /var/svn/foobar
       
  Order allow,deny
  Allow from all  

  # require HTTP Authentication for write access
  AuthType Basic
  AuthName "Foobar Subversion Repository"
  AuthUserFile /var/svn/passwd 

  <LimitExcept GET PROPFIND OPTIONS REPORT>
    Require valid-user
  </LimitExcept>
</Location>

converting cvs to svn

The Python based utility cvs2svn can be used to convert existing CVS repositories to Subversion:

cvs2svn -s svn-repos-path cvs-repos-path