On 23 February 2004 CollabNet released Subversion 1.0.0, a centralised version control system meant to replace CVS (Concurrent Versions System) without upending its day-to-day use. The command line stays familiar โ€” svn checkout, svn commit, svn update echo the CVS syntax โ€” and the real difference lies in how the repository records changes.

Context

CVS has been around since the late 1980s and versions files one at a time: each ,v file carries its own revision history, independent of the others, and the revision number advances per file. Three practical consequences follow from this model, all familiar to anyone who has run a shared CVS repository.

First: there is no single identifier for the state of the whole project at a given instant. Reproducing a coherent snapshot needs an explicit tag or a timestamp, and in CVS a tag is a label stuck onto each file separately. Second: the commit is not atomic. If the process breaks halfway through โ€” the network drops, the server is overloaded โ€” some files end up updated and others do not, and the repository lands in a state no single revision describes. Third: CVS does not version directory structure. Renaming a file means removing it and re-adding it, and its historical continuity is lost along the way.

Subversion began in 2000 inside CollabNet (Karl Fogel, Ben Collins-Sussman, C. Michael Pilato, with Brian Behlendorf in the initial group) around one design decision: version the whole tree, not individual files.

Architecture

A Subversion repository is a sequence of trees. Every successful svn commit produces a new complete tree and assigns it an integer revision number that is global and increasing. Revision 42 is not revision 42 of a file: it is the state of the entire repository after the forty-second commit. This single change in representation closes the first two CVS problems in one move. The coherent snapshot becomes a number. And the commit that produces revision 42 is a transaction on the underlying storage: either the new tree is written and becomes visible in full, or it is not written at all.

At the 1.0 release the storage is a Berkeley DB database: the DBMS (database management system) transactions give commit atomicity directly. The choice carries a known, documented operational cost โ€” an abnormal process termination can leave the Berkeley DB environment in a state that has to be recovered with svnadmin recover, and concurrency between reads and writes must be handled with care around locking. It is a stated trade-off, not a detail hidden under the rug.

Since what gets versioned is the tree, directories become first-class objects, with histories of their own. Two operations follow that CVS lacked:

  • copy (svn copy): duplicates a tree node โ€” file or directory โ€” and records the revision and path it comes from. The copy stays internal to the repository and does not physically duplicate the data: it costs as much as a new reference, whatever the size of the subtree. Branches and tags in Subversion are exactly this: a copy of trunk/ under branches/ or tags/, by convention rather than by a dedicated mechanism.
  • rename as a copy plus a delete within the same transaction, with the origin tracked: the fileโ€™s history survives the move.

Every tree node can also carry properties (properties): key/value pairs versioned alongside the content. Subversion reserves a few under the svn: prefix โ€” svn:ignore, svn:executable, svn:mime-type, svn:eol-style โ€” and leaves the rest of the namespace to the user. Line-ending normalisation and the executable flag, which CVS handled through per-file flags or keyword expansion, here become versioned metadata like any other.

The delicate point

The least obvious part of the 1.0 engineering is the network transport. For remote access over HTTP, Subversion does not invent a proprietary protocol: it implements WebDAV (RFC 2518) and its versioning extension, DeltaV (RFC 3253, March 2002). The mod_dav_svn module plugs into mod_dav inside Apache HTTP Server 2, and the repository is exposed as a DeltaV resource.

The practical upshot is that authentication, authorisation, TLS encryption, logging, reverse proxies and load balancers already configured for Apache apply to the repository too, with no second stack to keep running. A browser can walk the repository read-only, because a Subversion repository served by mod_dav_svn is, formally, a WebDAV server. The choice moves complexity out of the Subversion code and into the Apache ecosystem, which by then has been mature for years.

For those who do not want Apache there is an alternative transport: the svnserve daemon with the svn:// scheme, and the svn+ssh:// variant that channels the same protocol inside an SSH session, reusing system authentication.

Implications

Anyone coming from CVS has three mental habits to revise, more than the syntax. The commit should be thought of as an indivisible unit, hence grouped by logical change and not by file touched. The global revision makes per-file tagging pointless: a number is enough to identify the state. And the fact that branches and tags are copies moves the discipline from mechanism to layout convention โ€” trunk, branches, tags โ€” which the system encourages rather than enforces.

On the operational side, with Apache the central repository sits behind HTTPS and the web server handles permissions; and tools such as TortoiseSVN (Windows Explorer integration, under development since 2002) bring the same model to people who do not work from the command line.

Limits

Subversion stays centralised by choice: there is one authoritative repository, and the local working copy is not a replica with a history of its own. Operations like log or diff against arbitrary revisions go through the server. Systems exploring the distributed model do exist โ€” BitKeeper (commercial, used in the Linux kernel), GNU Arch, Monotone, darcs โ€” but today with lower reach and operational maturity; Subversion does not stand on that ground, and does not try to.

The Berkeley DB backend carries the fragility noted above: under high concurrency, or with processes that die badly, repository maintenance is real work, not a hypothesis. Branches are cheap to create, but the merge stays manual: at the 1.0 release there is no automatic record of which revisions have already been merged, and keeping count of that falls to whoever manages the branch. The instant copy is a solid primitive; reconciling branches is still operator work.


Cover image: The classic Subversion logo: the lowercase โ€œsubversionโ€ wordmark โ€” logo by unknown author, public domain โ€” https://commons.wikimedia.org/wiki/File:Subversion_logo.svg