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:
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.
| 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:
|
| Subversion |
svn mkdir file://repository/tags svn mkdir file://repository/branches svn import src file://repository/trunk svn mkdir https://repository/tags |
||
| 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
| 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:
|
| 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 |
| 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] |
| 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 |
||
| 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 |
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:
# 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
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
# 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>
The Python based utility cvs2svn can be used to convert existing CVS repositories to Subversion:
cvs2svn -s svn-repos-path cvs-repos-path