Getting Started
***************

How to get started with Subversion.

Introduction
============

A Revision Control System
-------------------------

Subversion is a free/open-source revision control system.

That is, Subversion manages files over time.  The files are placed into a central repository.  The repository is much like an ordinary file server, except that it remembers every change ever made to your files.  This allows you to recover older versions of your files, or browse the history of how your files changed.  Many people think of revision-control as a sort of "time machine".

Some revision control systems are also software configuration management (SCM) systems.  These systems are specifically tailored to manage trees of source code, and have many features that are specific to software development (such as natively understanding programming languages.)  Subversion, however, is not one of these systems; it a general system that can be used to manage any sort of collection of files.  (And is still darn good at managing source code.)

History
-------

Subversion aims to be the successor to CVS (http://www.cvshome.org).

At the time of writing, CVS is the standard Free revision control system used by the open-source community.  It has a hard-earned, well deserved reputation as stable and useful software, and has a design that makes it perfect for open-source development.  However, it also has a number of problems that are difficult to fix.

Subversion's original designers settled on a few simple goals: it was decided that Subversion should be a functional replacement for CVS. It should do everything that CVS does -- preserving the same development model while fixing the the most obvious flaws.  Existing CVS users are the first target audience: any CVS user should be able to start using Subversion with little effort.

Collabnet (http://www.collab.net) provided the initial funding in 2000 to begin development work, and the effort has now blossomed into a large, open-source project backed by a community of Free software developers.

Features
--------

What sort of things does Subversion do better than CVS?  Here's a short list to whet your appetite:

  * Directory versioning The Subversion repository doesn't use RCS files like CVS; instead, it implements a 'virtual' versioned filesystem that tracks tree-structures over time.  Files and directories are versioned.  At last, there are real client-side `mv' and `cp' commands.

  * Atomic commits A commit either goes into the repository completely, or not all.

  * Advanced network layer The Subversion network server is Apache, and client and server speak WebDAV protocol to one another.  (see Design)

  * Faster network access A binary diffing algorithm is used to store and transmit deltas in both directions, regardless of whether a file is of text or binary type.

  * Meta-data Each file or directory has an invisible hashtable attached.  You can invent and store any arbitrary key/value pairs you wish: owner, perms, icons, app-creator, mime-type, personal notes, etc.  This is a general-purpose feature for users.  Properties are versioned over time, just like file contents.

  * Hackability Subversion has no historical baggage; it is primarily a collection of shared C libraries with well-defined APIs.  This makes Subversion extremely maintainable and usable by other applications and languages.

Design
======

Subversion has a modular design; it's implemented as a collection of C libraries.  Each layer has a well-defined purpose and interface.

If you aren't interested in how Subversion works under the hood, feel free to skip this section and move on to Installation and Basics.

Here's a helpful diagram of Subversion's layers.  Program flow begins at the top of the diagram (initiated by the user) and flows "downward".

                         +--------------------+
                         | commandline or GUI |
                         |    client app      |
              +----------+--------------------+----------+ <=== Client interface
              |              Client Library              |
              |                                          |
              |        +----+                            |
              |        |    |                            |
      +-------+--------+    +--------------+--+----------+ <=== Network interface
      | Working Copy   |    |    Remote    |  | Local    |
      | Management lib |    | Repos Access |  | Repos    |
      +----------------+    +--------------+  | Access   |
                            |     neon     |  |          |
                            +--------------+  |          |
                               ^              |          |
                              /               |          |
                        DAV  /                |          |
                            /                 |          |
                           v                  |          |
                   +---------+                |          |
                   |         |                |          |
                   | Apache  |                |          |
                   |         |                |          |
                   +---------+                |          |
                   | mod_DAV |                |          |
                 +-------------+              |          |
                 | mod_DAV_SVN |              |          |
      +----------+-------------+--------------+----------+ <=== Filesystem interface
      |                                                  |
      |               Subversion Filesystem              |
      |                                                  |
      +--------------------------------------------------+

Filesystem
----------

The Subversion Filesystem is not a kernel-level filesystem that one would install in an operating system (like the Linux ext2 fs.)  Instead, it refers to the design of Subversion's repository.  The repository is built on top of a database -- currently Berkeley DB -- and thus is a collection of .db files.  However, a library accesses these files and exports a C API that simulates a filesystem -- specifically, a "versioned" filesystem.

This means that writing a program to access the repository is like writing against other filesystem APIs: you can open files and directories for reading and writing as usual.  The main difference is that this particular filesystem never loses data when written to; old versions of files and directories are always saved as historical artifacts.

Using a database backend also provides other nice features that Subversion needs: data integrity, atomic writes, recoverability, and hot backups.

Network Layer
-------------

Subversion has the mark of Apache all over it.  At its very core, the client uses the Apache Portable Runtime (APR) library.  (This means that Subversion client compiles and run anywhere Apache httpd does -- right now, this list includes all flavors of Unix, Win32, BeOS, OS/2, Mac OS X, and possibly Netware.)

However, Subversion depends on more than just APR -- the Subversion "server" is Apache httpd itself.  Apache httpd is a time-tested, extensible open-source server process that ready for serious use.  It can sustain a high network load, runs on many platforms, and can operate through firewalls.  It can use a number of different authentication protocols and do network pipelining and caching.  By using Apache as a server, Subversion gets all these features for free.

Subversion uses WebDAV as its network protocol.  DAV (Distributed Authoring and Versioning) is a whole discussion in itself (see www.webdav.org) -- but in short, it's an extension to HTTP that allows reads/writes and "versioning" of files over the web.  The Subversion project is hoping to ride a slowly rising tide of support for this protocol: all of the latest file-browsers for Win32, MacOS, and GNOME speak this protocol already.  Interoperability will (hopefully) become more and more of a boon over time.

For users who simply wish to access Subversion repositories on local disk, the client can do this too; no network is required.  The "Repository Access" layer (RA) is an abstract API implemented by both the DAV and local-access RA libraries.  This is a specific benefit of writing a "librarized" revision control system: feel like writing a new network protocol for Subversion?  Just write a new library that implements the RA API.

Client Libraries
----------------

On the client side, the Subversion "working copy" library maintains administrative information within special .svn subdirectories, similar in purpose to the CVS administrative directories found in CVS working copies.

A glance inside the typical .svn directory turns up a bit more than usual, however.  The `entries' file contains XML which describes the current state of the working copy directory (and which basically serves the purposes of CVS's Entries, Root, and Repository files combined).  But other items present (and not found in CVS) include storage locations for the versioned "properties" (the metadata mentioned in 'Subversion Features' above) and private caches of pristine versions of each file.  This latter feature provides the ability to report local modifications -- and do reversions -- without network access.  Authentication data is also stored within .svn/, rather than in a single .cvspass-like file.

The Subversion "client" library has the broadest responsibility; its job is to mingle the functionality of the working-copy library with that of the repository-access library, and then to provide a highest-level API to any application that wishes to perform general revision control actions. (For example: the C routine `svn_client_checkout()' takes a URL as an argument.  It passes this URL to the repository-access library and opens an authenticated session with a particular repository. It then asks the repository for a certain tree, and sends this tree into the working-copy library, which then writes a full working copy to disk (.svn directories and all.))

The client library is designed to be used by any application.  While the Subversion source code includes a standard command-line client, it should be very easy to write any number of GUI clients on top of the client library.

Installation
============

### Somebody please write this.  It should describe how to fetch various binary packages of Subversion for different platforms.

### Place a cross-ref here to the appendix that describes how to build from source code.

Basics
======

If you're an existing CVS user, then the first section, The Subversion Development Model, should already be familiar.  You may just want to skim it quickly, noting the special definition of "Revision" in the second subsection.  At some point, you should probably also read the appendix which describes fundamental differences between CVS and SVN.

The Subversion Development Model
--------------------------------

Working Directories and Repositories
....................................

Suppose you are using Subversion to manage a software project.  There are two things you will interact with: your working directory, and the repository.

Your working directory is an ordinary directory tree, on your local system, containing your project's sources.  You can edit these files and compile your program from them in the usual way.  Your working directory is your own private work area: Subversion never changes the files in your working directory, or publishes the changes you make there, until you explicitly tell it to do so.

After you've made some changes to the files in your working directory, and verified that they work properly, Subversion provides commands to publish your changes to the other people working with you on your project.  If they publish their own changes, Subversion provides commands to incorporate those changes into your working directory.

A working directory contains some extra files, created and maintained by Subversion, to help it carry out these commands.  In particular, these files help Subversion recognize which files contain unpublished changes, and which files are out-of-date with respect to others' work.

While your working directory is for your use alone, the repository is the common public record you share with everyone else working on the project.  To publish your changes, you use Subversion to put them in the repository.  (What this means, exactly, we explain below.)  Once your changes are in the repository, others can tell Subversion to incorporate your changes into their working directories.  In a collaborative environment like this, each user will typically have their own working directory (or perhaps more than one), and all the working directories will be backed by a single repository, shared amongst all the users.

A Subversion repository holds a single directory tree, and records the history of changes to that tree.  The repository retains enough information to recreate any prior state of the tree, compute the differences between any two prior trees, and report the relations between files in the tree --- which files are derived from which other files.

A Subversion repository can hold the source code for several projects; usually, each project is a subdirectory in the tree.  In this arrangement, a working directory will usually correspond to a particular subtree of the repository.

For example, suppose you have a repository laid out like this:

     /trunk/paint/Makefile
                  canvas.c
                  brush.c
            write/Makefile
                  document.c
                  search.c

In other words, the repository's root directory has a single subdirectory named trunk, which itself contains two subdirectories: paint and write.

To get a working directory, you must check out some subtree of the repository.  If you check out /trunk/write, you will get a working directory like this:

     write/Makefile
           document.c
           search.c
           .svn/

This working directory is a copy of the repository's /trunk/write directory, with one additional entry --- .svn --- which holds the extra information needed by Subversion, as mentioned above.

Suppose you make changes to search.c.  Since the .svn directory remembers the file's modification date and original contents, Subversion can tell that you've changed the file.  However, Subversion does not make your changes public until you explicitly tell it to.

To publish your changes, you can use Subversion's commit command:

     $ pwd
     /home/jimb/write
     $ ls -a
     .svn/    Makefile   document.c    search.c
     $ svn commit search.c
     $

Now your changes to search.c have been committed to the repository; if another user checks out a working copy of /trunk/write, they will see your text.

Suppose you have a collaborator, Felix, who checked out a working directory of /trunk/write at the same time you did.  When you commit your change to search.c, Felix's working copy is left unchanged; Subversion only modifies working directories at the user's request.

To bring his working directory up to date, Felix can use the Subversion update command.  This will incorporate your changes into his working directory, as well as any others that have been committed since he checked it out.

     $ pwd
     /home/felix/write
     $ ls -a
     .svn/    Makefile    document.c    search.c
     $ svn update
     U search.c
     $

The output from the svn update command indicates that Subversion updated the contents of search.c.  Note that Felix didn't need to specify which files to update; Subversion uses the information in the .svn directory, and further information in the repository, to decide which files need to be brought up to date.

We explain below what happens when both you and Felix make changes to the same file.

Transactions and Revision Numbers
.................................

A Subversion commit operation can publish changes to any number of files and directories as a single atomic transaction.  In your working directory, you can change files' contents, create, delete, rename and copy files and directories, and then commit the completed set of changes as a unit.

In the repository, each commit is treated as an atomic transaction: either all the commit's changes take place, or none of them take place. Subversion tries to retain this atomicity in the face of program crashes, system crashes, network problems, and other users' actions.  We may call a commit a transaction when we want to emphasize its indivisible nature.

Each time the repository accepts a transaction, this creates a new state of the tree, called a revision.  Each revision is assigned a unique natural number, one greater than the number of the previous revision. The initial revision of a freshly created repository is numbered zero, and consists of an empty root directory.

Unlike those of many other systems, Subversion's revision numbers apply to an entire tree, not individual files.  Each revision number selects an entire tree.

It's important to note that working directories do not always correspond to any single revision in the repository; they may contain files from several different revisions.  For example, suppose you check out a working directory from a repository whose most recent revision is 4:

     write/Makefile:4
           document.c:4
           search.c:4

At the moment, this working directory corresponds exactly to revision 4 in the repository.  However, suppose you make a change to search.c, and commit that change.  Assuming no other commits have taken place, your commit will create revision 5 of the repository, and your working directory will look like this:

     write/Makefile:4
           document.c:4
           search.c:5

Suppose that, at this point, Felix commits a change to document.c, creating revision 6.  If you use svn update to bring your working directory up to date, then it will look like this:

     write/Makefile:6
           document.c:6
           search.c:6

Felix's changes to document.c will appear in your working copy of that file, and your change will still be present in search.c.  In this example, the text of Makefile is identical in revisions 4, 5, and 6, but Subversion will mark your working copy with revision 6 to indicate that it is still current.  So, after you do a clean update at the root of your working directory, your working directory will generally correspond exactly to some revision in the repository.

How Working Directories Track the Repository
............................................

For each file in a working directory, Subversion records two essential pieces of information:

  * what revision of what repository file your working copy is based on (this is called the file's base revision), and

  * a timestamp recording when the local copy was last updated.

Given this information, by talking to the repository, Subversion can tell which of the following four states a file is in:

  * Unchanged, and current.  The file is unchanged in the working directory, and no changes to that file have been committed to the repository since its base revision.

  * Locally changed, and current.  The file has been changed in the working directory, and no changes to that file have been committed to the repository since its base revision.  There are local changes that have not been committed to the repository.

  * Unchanged, and out-of-date.  The file has not been changed in the working directory, but it has been changed in the repository.  The file should eventually be updated, to make it current with the public revision.

  * Locally changed, and out-of-date.  The file has been changed both in the working directory, and in the repository.  The file should be updated; Subversion will attempt to merge the public changes with the local changes.  If it can't complete the merge in a plausible way automatically, Subversion leaves it to the user to resolve the conflict.

The subversion "status" command will show you the state of any item in your working copy.

Subversion Does Not Lock Files
..............................

Subversion does not prevent two users from making changes to the same file at the same time.  For example, if both you and Felix have checked out working directories of /trunk/write, Subversion will allow both of you to change write/search.c in your working directories. Then, the following sequence of events will occur:

  * Suppose Felix tries to commit his changes to search.c first.  His commit will succeed, and his text will appear in the latest revision in the repository.

  * When you attempt to commit your changes to search.c, Subversion will reject your commit, and tell you that you must update search.c before you can commit it.

  * When you update search.c, Subversion will try to merge Felix's changes from the repository with your local changes.  By default, Subversion merges as if it were applying a patch: if your local changes do not overlap textually with Felix's, then all is well; otherwise, Subversion leaves it to you to resolve the overlapping changes.  In either case, Subversion carefully preserves a copy of the original pre-merge text.

  * Once you have verified that Felix's changes and your changes have been merged correctly, you can commit the new revision of search.c, which now contains everyone's changes.

Some revision control systems provide ``locks'', which prevent others from changing a file once one person has begun working on it.  In our experience, merging is preferable to locks, because:

  * changes usually do not conflict, so Subversion's behavior does the right thing by default, while locking can interfere with legitimate work;

  * locking can prevent conflicts within a file, but not conflicts between files (say, between a C header file and another file that includes it), so it doesn't really solve the problem; and finally,

  * people often forget that they are holding locks, resulting in unnecessary delays and friction.

Of course, the merge process needs to be under the users' control. Patch is not appropriate for files with rigid formats, like images or executables.  Subversion attempts to notice when a file is in a binary format, or is of any mime-type other than text/*.  For these rigid-format files, Subversion simply presents you with the two original texts to choose from.

Quick Walkthrough
-----------------

The previous section gave an abstract overview of the Subversion development model.  Here's an opportunity to play with Subversion in some hands-on examples.  The Subversion commands demoed here are just small examples of what Subversion can do;  see Chapter 2 for full explanations of each.

Make a repository
.................

The Subversion client has an abstract interface for accessing a repository.  Two "Repository Access" (RA) implementations currently exist as libraries.  You can see which methods are available to your svn client like so:

     $ svn --version
     Subversion Client, version N
     compiled Jan 26 2002, 16:43:58

     Copyright (C) 2000-2002 CollabNet.
     Subversion is open source software, see http://subversion.tigris.org/

     The following repository access (RA) modules are available:

     * ra_dav : Module for accessing a repository via WebDAV (DeltaV) protocol.
          - handles 'http' schema
     * ra_local : Module for accessing a repository on local disk.
          - handles 'file' schema

If you don't see ra_local, it probably means that Berkeley DB (or relevant database back-end) wasn't found when compiling your client binary.  To continue with these examples, you'll need to have ra_local available.

Start by creating a new, empty repository using the svnadmin tool:

     $ svnadmin create myrepos

Let's assume you have a directory someproject which contains files that you wish to place under version control:

     someproject/foo
                 bar
                 baz/
                 baz/gloo
                 baz/bloo

After the repository exists, you can initially import your data into it, using the ra_local access method (invoked by using a 'file' URL):

     $ svn import file:///absolute/path/to/myrepos someproject myproj
     [...]
     Committed revision 1.

The example above creates a new directory myproj in the root of the repository's filesystem, and copies all the data from someproject into it.

Make some Working copies
........................

Now check out a fresh "working copy" of your project.  To do this, we specify a URL to the exact directory within the repository that we want. The '-d' option allows us to name the working copy we check out.

     $ svn co file:///usr/local/svn/repos1 -d wc
     A  wc/foo
     A  wc/bar
     A  wc/baz
     A  wc/baz/gloo
     A  wc/baz/bloo

Now we have a working copy in a local directory called wc, which represents the location /myproj in the repository.

For the sake of example, let's duplicate the working copy, and pretend it belongs to someone else:

     $ cp -R wc wc2

From here, let's make some changes within our original working copy:

     $ cd wc
     $ echo "new text" >> bar       # change bar's text
     $ svn propset color green foo  # add a metadata property to foo
     $ svn rm baz                   # schedule baz directory for deletion
     $ touch newfile
     $ svn add newfile              # schedule newfile for addition

That's a lot of changes!  If we were to leave and come back tomorrow, how could we remember what changes we'd made?  Easy.  The 'status' command will show us all of the "local modifications" in our working copy:

     $ svn status                   # See what's locally modified
     M   ./bar
     _M  ./foo
     A   ./newfile
     D   ./baz
     D   ./baz/gloo
     D   ./baz/bloo

According to this output, three items are scheduled to be (D)eleted from the repository, one item is scheduled to be (A)dded to the repository, and two items have had their contents (M)odified in some way.  For more details, be sure to see the svn status section in Chapter 2.

Now we decide to commit our changes, creating Revision 2 in the repository:

     $ svn commit -m "fixed bug #233"
     Sending    bar
     Sending    foo
     Adding     newfile
     Deleting   baz
     Transmitting data...
     Committed revision 2.

The -m argument is a way of specifying a log message: that is, a specific description of your change-set sent to the repository.  The log message is now attached to Revision 2.  A future user might peruse repository log messages, and now will know what your Revision 2 changes were for.

Finally, pretend that you are now Felix, or some other collaborator.  If you go wc2 (that other working copy you made), it will need the svn update command to receive the Revision 2 changes:

        $ cd ../wc2                # change to the back-up working copy

        $ svn update               # get changes from repository
        U   ./bar
        _U  ./foo
        A   ./newfile
        D   ./baz

The output of the update command tells Felix that baz was (D)eleted from his working copy, newfile was (A)dded to his working copy, and that bar and foo had their contents (U)pdated.

If for some reason bar contained some local changes made by Felix, then the server changes would be merged into bar: that is, bar would now contain both sets of changes.  Whenever server changes are merged into a locally-modified file, two possible things can happen:

  * The merge can go smoothly.  That is, the two sets of changes do not overlap.  In this case, svn update prints a G (``mer(G)ed'').

  * The sets of changes overlap, and a C for (C)onflict is printed.  See section ??? for information about how conflict resolution works.