OpenCores
SVN  -  SVN How To

Important information

OpenCores changed the revision control system from CVS to SVN in March 2009.
All projects were then transferred over to SVN (with all historical information included).

Subversion - a better CVS

Introduction

Subversion [1] is a free source code manager and version control system intended to replace CVS. Most open source developers have, at some stage, come across CVS. It is the de facto standard SCM on free software projects. As such, it has a huge user base, and has earned a reputation as a good piece of software.

The primary goal of the Subversion project is "to build a compelling replacement for CVS in the open source community". In other words, it is designed to implement all of the functionality of CVS, with a familiar interface, while fixing its design flaws, and offering much improved functionality.

Unusually for an open source project, Subversion has had a number of full-time developers employed to work on it since the project's inception. CollabNet is paying the salaries of several developers, and holds the copyright on code in the project. The code is release under a BSD/Apache style licence.

A better CVS

For those who have used CVS for years with no problems, you might be asking yourselves what I meant by design flaws in the last section. CVS has a number of problems, primarily caused by its dependency on the RCS file format for versioning files. The issues addressed by Subversion include the following.

  1. Atomic commits
    If you are making a change to a source code repository, and you commit that change, one of the fundamental principles of both database and version control systems is that either your entire change is accepted or your entire change is rejected. This behaviour is called atomicity (this is the A in ACID).

    In CVS, this is not guaranteed. Atomicity is only guaranteed on a file-by-file basis. This means that if you are committing changes to 10 files, and someone else starts a commit at roughly the same time as you which changes the 8th file in your list, the changes for the first 7 files in your change get accepted, and the rest gets rejected. After this happens, it is very likely that the repository will be in an inconsistent state until you resolve the conflict you've just found and commit the rest of your change.

    In addition, because CVS has no way of grouping changes to a number of files together, it isn't even possible to revert your partial commit while ensuring that the successful commit which happened at the same time doesn't get reverted as well.

    An illustration might help explain the problem. Tom and Dick are working on the same source code tree which has 3 files in it - a.c, b.c and c.c.

    By coincidence, Tom and Dick try to commit changes at the same time. They both check that they are up to date with the repository, and then at the same time they try to commit their changes.

    While Tom is writing his changes to a.c, Dick starts writing to b.c. Before Dick has finished, Tom starts writing to c.c. Dick's commit finds that Tom has locked c.c, and informs him that his c.c is no longer up to date. Dick does an update to get Tom's changes, and finds that there's a conflict in c.c which he has to resolve (perhaps in conference with Tom).

    Meanwhile, Harry checks out the sources and has Tom's changes to a.c and c.c, and Dick's change to b.c, but not Dick's change to c.c. He tries to build the project, ad finds that he can't.

    In brief, until Tom and Dick resolve Dick's conflict, no Tom, Dick or Harry has a working copy of the source code.

    Subversion implements atomic commits. When you commit to a Subversion repository, you start a transaction with the repository, and if any part of the commit fails, the transaction is rolled back and the entire commit is rejected.

  2. Renaming files and versioning directories
    CVS has no way to rename files and keep versioning history. Renaming file1 to file2 in CVS means doing the following:

    $ mv file1 file2
    $ cvs remove file1
    $ cvs add file2
    $ cvs commit

    But this creates a new file file2 with no record of a common history with the old file1 (which is now stored in the Attic).

    In Subversion, the above operation is performed by

    $ svn move file1 file2
    $ svn commit

    and the common history of file1 and file2 is conserved.

    In addition, Subversion has dramatically increased the things that can be versioned. Directories and file metadata, as well as renamed or copied files, all have their own versioning. This means that not only can you move and copy files, you can move and copy directories too.

    These copies are very cheap, because they're lazy copies - the first copy is similar to a hard-link to a particular version of the directory. And as you change files on the branch, only those files you change get copied onto the branch. This means that making and maintaining branches is a cheap operation, both in terms of space in the repository and in terms of time.

  3. Branching and tagging
    When we tag a repository in CVS, every file in the directory tree we're tagging is "stamped" with the tag. Likewise, when we're branching, the branch tag is created in each file affected. This means that branching and tagging are expensive operations for big repositories and directory trees, which has a cost proportional to the number of files being branched or tagged.

    Subversion has made both branching and tagging constant time operations. In fact, Subversion makes no distinction between a tag and a branch. Both of these are implemented simply by copying the directory you are tagging, and have a cost the same as any other copy.

    Logically there is no difference between branching and tagging - a tag is a copy of a group of files at a certain point of time, and a branch is a copy of a group of files at a certain point in time which can be changes independently of the rest of the tree. In brief, a tag is a branch that we don't change. And in Subversion, this is the case. If you change a file in a tagged tree and commit, the tag suddenly becomes a branch.

    In addition, requesting a file off a branch in CVS requires time proportional to the number of revisions since the branch point with the HEAD branch, plus the number of revisions made in HEAD since the branch point. RCS files store the latest revision in HEAD as fulltext, and any time you request the text of another version, it has to be constructed. This means, for a file on a branch, reverting all changes from HEAD to the branch point, and then applying all the changes made on the branch to arrive at the complete file as we see it.

    Because of this, diffs, branch switches and check-outs are all roughly proportional to the number of revisions on a file in CVS when those operations are on a branch. All branch & tag operations in Subversion are constant time.

  4. Binary diffs
    Storing binary files in CVS is something of a nightmare. Because the RCS file format is essentially text based, any changes to a binary file resulted in the replacement of the old file. If the file is a 100K image that gets changed for every release, like the GIMP splash screen, then that one file ends up taking up many megabytes of space in the repository.

    Subversion uses a diffing algorithm called Vdelta to provide efficient binary diffing, meaning that storing postscript or pdf documents which change frequently doesn't pose the same problems as it does for CVS. The diffing algorithm is also extremely efficient on text only files.

  5. Client-server communication
    When we change a file locally when using CVS, and we want to know the difference between our changed copy and the repository version, the entire file is sent to the server, the diff is done there, and the result is sent back to the client. Similar operations are performed for all operations involving locally modified files, such as updates, commits and merges. This means that the cost of these operations is proportional to the size of the locally modified files, rather than the size of the change.

    The philosophy of Subversion is different. The reasoning is that disk space has become a more plentiful resource than bandwidth in recent years, and therefore we should minimise use of the latter, even if there is a cost in the former. When we update a Subversion repository, a copy of the latest repository revision is made locally, as well as being patched into our local copy.

    Because of this, diffs are sent in both directions by Subversion. That is, if we modify a local file and commit, only the differences between our local file and the most recent revision we have locally are sent to the server, meaning a lot less use of bandwidth.

    In addition, because we have a pristine copy of the repository locally, there is a clear distinction between server operations and local operations - for example, finding out which local files have been modified, and the changes we have made to those files, are operations which can be performed without any access to the server.

    In fact, the cost of subversion operations in general is proportional to the size of the change, rather than the size of the repository or the size of the files being changed.

Getting started with Subversion

The easiest way to see the benefits of Subversion is to use it. Getting started is a little tricky for the moment, but as the technologies used become more commonly used, this will certainly get easier.

  1. Installing a Subversion client
    To get started, you will need a subversion client, and the ability to create your first repository. The database which Subversion uses to store your files in the repository is Berkeley DB version 4[6].

    For Debian users, Subversion is included in unstable. For RedHat and Mandrake (and other RPM based distributions), there are RPMs, available off the project download page. For everyone else, you can build from sources. The latest release source tarballs are available on the Subversion site [7].

    To build from sources, look at section II of the install guide [8]. The basic procedure is the usual ./configure, make, make install.

    If you want to build from the latest sources, the requirements are a little more complicated - see the install guide for details.

  2. Learn Subversion in 3 minutes
    Here's a short list of the most common subversion commands along with a description of what they do. A slightly more detailed list is available in the Subversion Quick Guide [11], and a comprehensive description of all commands available in Subversion is available in the Subversion book [3].

    co/checkout Check out a copy of the source code to a working copy.
    ci/commit Commit your local changes to the repository
    up/update Update your working copy to reflect changes to the repository since your last update
    status New in Subversion - summarise your local changes, without talking to the repository, or summarise resources that are out of date without updating.
    add, remove/rm Add or remove files to/from version control.
    copy/cp, move/mv New in Subversion - copy/move a file or directory to another file, keeping old version history.
    merge Equivalent to cvs update -j - merge changes from another location into the working copy.
    switch Change your working copy to use another branch
    diff Get differences between your working copy and the last updated sources (new to Subversion), or the current repository
    log Show log entries for resource
    propadd, proplist, propdel, propviewi New to Subversion - manipulate metadata on a file. You can associate arbitrary data to any file or directory. A certain number of metadata keys have a special meaning (for example, svn:mime-type).

How to use Subversion with OpenCores

OpenCores changed the revision control system from CVS to SVN in March 2009. All projects were then transferred over to SVN (with all historical information included).

When creating a new project a subversion repository is automatically created with the trees tags, branches and trunk. Only maintainer(s) has the possibility to do commit

We will now try to explain how to use the subversion repository with a few examples of different use case below. For all examples we will use the Ethernet SMII IP core as an example. The name given to this repository is smii.

  1. Get a tar file with the latest release
    This can be done from your web browser on the projects page. For each project there is a link to a tar file containing the latest revision of the content in trunk. Download the file, extract the files and you have a local copy.

    $ tar xvzf smii_latest.tar.gz

  2. Check out a copy of the source code to a working copy

    $ svn co http://opencores.org/ocsvn/smii/smii/trunk

    You can optionally include username and password

    $ svn co --username user --password passwd http://opencores.org/ocsvn/smii/smii/trunk

    To include possible updates you do the following

    $ cd trunk
    $ svn update

  3. Commit changes
    If you have changed local files and are a maintainer of the project you can commit your changes to the repositry
    To check for local changes

    $ svn status
    M Makefile

    The local file Makefile have been changed. To see changes use svn diff

    $ svn diff Makefile
    Index: Makefile
    ===================================================================
    --- Makefile (revision 3)
    +++ Makefile (working copy)
    @@ -19,6 +19,7 @@
    vppp --simple +define+SMII+8 tmp.v > smii_module_inst_8.v

    smii:
    - vppp --simple +define+ACTEL generic_buffers.v smii_sync.v smii_txrx.v | cat copyright.v - > smii.v
    + vppp --simple +define+ACTEL generic_buffers.v smii_sync.v smii_txrx.v | cat copyright.v - > smii_ACTEL.v
    + vppp --simple generic_buffers.v smii_sync.v smii_txrx.v | cat copyright.v - > smii.v

    all: comp1 comp2 comp3 comp4 comp8 smii

    The Makefile have a new line. The make script now generate a new file, smii_ACTEL.v. To place this new file under revision control:

    $ svn add smii_ACTEL.v
    A smii_ACTEL.v

    The file is now scheduled for revision, it will be included on next commit. After rebuilding the project with make all we can see current status

    $ svn status
    ? tmp.v
    M smii.v
    M Makefile
    A smii_ACTEL.v

    Two files modified and one file added. Note that the file tmp.v is not under revision control. We can now commit the changes to the repository.

    $ svn -m "added ACTEL version with BUFG" commit
    Sending verilog/Makefile
    Sending verilog/smii.v
    Adding verilog/smii_ACTEL.v
    Transmitting file data ...
    Committed revision 4.

  4. Creating tags Tagging or releasing an IP core should be done either to reflect that the status of the project has reach a defined point or that we want to specify a certain state of the repository to be used in testing or actual products. Tagging makes it easy for the end user to use a defined version of the IP.
    In subversion tagging is done with svn copy to the tag tree. First we should create a new directory in the tag tree to reflect the tag to be made. Secondly you copy the source files from trunk to tag.
    In this example we want to make a prerelease to be used for testing of the IP

    $ svn mkdir -m "Prerelease to be used for testing" http://opencores.org/ocsvn/smii/smii/tags/P0

    Committed revision 5.

    $ svn copy -m "P0" http://opencores.org/ocsvn/smii/smii/rtl http://opencores.org/ocsvn/smii/smii/tags/P0

    Committed revision 6.

All of the above examples can be done from a GUI client. A GUI can make a lot of functions easier. This is especially true if in windows the Tortoise clinet is used. In Tortoise there is a repo-browser. When opened the user can do server side copy. This makes tagging and branching a lot easier.

Conclusion

Subversion is a natural successor to CVS.
It has an impressive feature set, and is very well tested at this stage.
As of writing the stable release is 1.5.6

References:

[1] Subversion home page http://subversion.tigris.org
[2] CVS home page http://www.cvshome.org/
[3] Subversion book http://svnbook.red-bean.com/book.html
[4] Subversion sources http://svn.collab.net/repos/svn/
[5] Inconveniences page http://subversion.tigris.org/inconveniences.html
[6] Berkeley DB home pagehttp://www.sleepycat.com/
[7] Subversion downloads http://subversion.tigris.org/servlets/ProjectDocumentList
[8] INSTALL http://svn.collab.net/repos/svn/trunk/INSTALL
[9] README http://svn.collab.net/repos/svn/trunk/README
[10] Apache2 home page http://httpd.apache.org/
[11] Neon home page http://www.webdav.org/neon/
[12] Quick Reference http://subversion.tigris.org/files/documents/15/177/foo.ps

Copyright David Neary, 2003
Material reworked to suit OpenCores use case, 2009
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License.

© copyright 1999-2014 OpenCores.org, equivalent to ORSoC AB, all rights reserved. OpenCores®, registered trademark.