BUY THIS BOOK
Add to Cart

PDF $27.99

Safari Books Online

What is this?

Looking to Reprint or License this content?


Version Control with Subversion
Version Control with Subversion By Ben Collins-Sussman, Brian W. Fitzpatrick, C. Michael Pilato
June 2004
Pages: 319

Cover | Table of Contents | Online Book | Colophon


Table of Contents

Chapter 1: Introduction
Version control is the art of managing changes to information. It has long been a critical tool for programmers, who typically spend their time making small changes to software and then undoing those changes the next day. But the usefulness of version control software extends far beyond the bounds of the software development world. Anywhere you can find people using computers to manage information that changes often, there is room for version control. And that's where Subversion comes into play.
This chapter contains a high-level introduction to Subversion: what it is; what it does; how to get it.
Subversion is a free/open-source version control system. That is, Subversion manages files and directories over time. A tree of files is placed into a central repository. The repository is much like an ordinary file server, except that it remembers every change ever made to the files and directories. This lets you recover older versions of data, or examine the history of how your data changed. In this regard, many people think of a version control system as a sort of time machine.
Subversion can access its repository across networks, which allows it to be used by people on different computers. At some level, the ability for various people to modify and manage the same set of data from their respective locations fosters collaboration. Progress can occur more quickly without a single conduit through which all modifications must occur. And because the work is versioned, you need not fear that quality is the trade-off for losing that conduit—if some incorrect change is made to the data, just undo that change.
Some version 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, or supplying tools for building software. Subversion, however, is not one of these systems. It is a general system that can be used to manage
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
What Is Subversion?
Subversion is a free/open-source version control system. That is, Subversion manages files and directories over time. A tree of files is placed into a central repository. The repository is much like an ordinary file server, except that it remembers every change ever made to the files and directories. This lets you recover older versions of data, or examine the history of how your data changed. In this regard, many people think of a version control system as a sort of time machine.
Subversion can access its repository across networks, which allows it to be used by people on different computers. At some level, the ability for various people to modify and manage the same set of data from their respective locations fosters collaboration. Progress can occur more quickly without a single conduit through which all modifications must occur. And because the work is versioned, you need not fear that quality is the trade-off for losing that conduit—if some incorrect change is made to the data, just undo that change.
Some version 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, or supplying tools for building software. Subversion, however, is not one of these systems. It is a general system that can be used to manage any collection of files. For you, those files might be source code—for others, anything from grocery shopping lists to digital video mixdowns and beyond.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Subversion's History
In early 2000, CollabNet, Inc. (http://www.collab.net) began seeking developers to write a replacement for CVS. CollabNet offers a collaboration software suite called SourceCast, of which one component is version control. Although SourceCast used CVS as its initial version control system, CVS's limitations were obvious from the beginning, and CollabNet knew it would eventually have to find something better. Unfortunately, CVS had become the de facto standard in the open source world largely because there wasn't anything better, at least not under a free license. So CollabNet determined to write a new version control system from scratch, retaining the basic ideas of CVS, but without the bugs and misfeatures.
In February 2000, they contacted Karl Fogel, the author of Open Source Development with CVS (Coriolis, 1999), and asked if he'd like to work on this new project. Coincidentally, at the time Karl was already discussing a design for a new version control system with his friend Jim Blandy. In 1995, the two had started Cyclic Software, a company providing CVS support contracts, and although they later sold the business, they still used CVS every day at their jobs. Their frustration with CVS had led Jim to think carefully about better ways to manage versioned data, and he'd already come up with not only the name Subversion, but also with the basic design of the Subversion repository. When CollabNet called, Karl immediately agreed to work on the project, and Jim got his employer, RedHat Software, to essentially donate him to the project for an indefinite period of time. CollabNet hired Karl and Ben Collins-Sussman, and detailed design work began in May. With the help of some well-placed prods from Brian Behlendorf and Jason Robbins of CollabNet, and Greg Stein (at the time an independent developer active in the WebDAV/DeltaV specification process), Subversion quickly attracted a community of active developers. It turned out that many people had had the same frustrating experiences with CVS, and welcomed the chance to finally do something about it.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Subversion's Features
When discussing the features that Subversion brings to the version control table, it is often helpful to speak of them in terms of how they improve upon CVS's design. If you're not familiar with CVS, you may not understand all of these features. And if you're not familiar with version control at all, your eyes may glaze over unless you first read Chapter 2, in which we provide a gentle introduction to version control in general.
Subversion provides:
Directory versioning
CVS only tracks the history of individual files, but Subversion implements a virtual versioned filesystem that tracks changes to whole directory trees over time. Files and directories are versioned.
True version history
Since CVS is limited to file versioning, operations such as copies and renames—which might happen to files, but which are really changes to the contents of some containing directory—aren't supported in CVS. Additionally, in CVS you cannot replace a versioned file with some new thing of the same name without the new item inheriting the history of the old—perhaps completely unrelated— file. With Subversion, you can add, delete, copy, and rename both files and directories. And every newly added file begins a with a fresh clean history all its own.
Atomic commits
A collection of modifications either goes into the repository completely, or not at all. This allows developers to construct and commit changes as logical chunks, and prevents problems that can occur when only a portion of a set of changes is successfully sent to the repository.
Versioned metadata
Each file and directory has a set of properties—keys and their values— associated with it. You can create and store any arbitrary key/value pairs you wish. Properties are versioned over time, just like file contents.
Choice of network layers
Subversion has an abstracted notion of repository access, making it easy for people to implement new network mechanisms. Subversion can plug into the Apache HTTP Server as an extension module. This gives Subversion a big advantage in stability and interoperability, and instant access to existing features provided by that server—authentication, authorization, wire compression, and so on. A more lightweight, standalone Subversion server process is also available. This server speaks a custom protocol which can be easily tunneled over SSH.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Subversion's Architecture
On one end is a Subversion repository that holds all of your versioned data. On the other end is your Subversion client program, which manages local reflections of portions of that versioned data (called working copies). Between these extremes are multiple routes through various Repository Access (RA) layers. Some of these routes go across computer networks and through network servers which then access the repository. Others bypass the network altogether and access the repository directly.
Figure 1-1 illustrates what one might call a mile-high view of Subversion's design.
Figure 1-1: Subversion's architecture
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Installing Subversion
Subversion is built on a portability layer called APR (the Apache Portable Runtime library). This means Subversion should work on any operating system that the Apache httpd server runs on: Windows, Linux, all flavors of BSD, Mac OS X, Netware, and others.
The easiest way to get Subversion is to download a binary package built for your operating system. Subversion's web site (http://subversion.tigris.org) often has these packages available for download, posted by volunteers. The site usually contains graphical installer packages for users of Microsoft operating systems. If you run a Unix-like operating system, you can use your system's native package distribution system (RPMs, DEBs, the ports tree, etc.) to get Subversion.
Alternatively, you can build Subversion directly from source code. From the Subversion website, download the latest source-code release. After unpacking it, follow the instructions in the INSTALL file to build it. Note that a released source package contains everything you need to build a command-line client capable of talking to a remote repository (in particular, the apr, apr-util, and neon libraries). But optional portions of Subversion have many other dependencies, such as Berkeley DB and possibly Apache httpd. If you want to do a complete build, make sure you have all of the packages documented in the INSTALL file. If you plan to work on Subversion itself, you can use your client program to grab the latest, bleeding-edge source code. This is documented in Section 8.6.2.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Subversion's Components
Subversion, once installed, has a number of different pieces. The following is a quick overview of what you get. Don't be alarmed if the brief descriptions leave you scratching your head—there are plenty more pages in this book devoted to alleviating that confusion.
svn
The command-line client program
svnversion
A program for reporting the state (in terms of revisions of the items present) of a working copy
svnlook
A tool for inspecting a Subversion repository
svnadmin
A tool for creating, tweaking or repairing a Subversion repository
svndumpfilter
A program for filtering Subversion repository dumpfile format streams
mod_dav_svn
A plug-in module for the Apache HTTP Server, used to make your repository available to others over a network
svnserve
A custom standalone server program, runnable as a daemon process or invokable by SSH; another way to make your repository available to others over a network
Assuming you have Subversion installed correctly, you should be ready to start. The next two chapters walk you through the use of svn, Subversion's command-line client program.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
A Quick Start
Some people have trouble absorbing a new technology by reading the sort of top-down approach provided by this book. This section is a very short introduction to Subversion, and is designed to give bottom-up learners a fighting chance. If you're one of those folks who prefers to learn by experimentation, the following demonstration will get you up and running. Along the way, we give links to the relevant chapters of this book.
If you're new to the entire concept of version control or to the copy-modify-merge model used by both CVS and Subversion, then you should read Chapter 2 before going any further.
The following example assumes that you have svn, the Subversion commandline client, and svnadmin, the administrative tool, ready to go. It also assumes that your svn client has been compiled against Berkeley DB. To verify this, run svn —version and make sure the ra_local module is available. Without this module, the client cannot access file:// URLs.
Subversion stores all versioned data in a central repository. To begin, create a new repository:
$ svnadmin create /path/to/repos
$ ls /path/to/repos
conf/  dav/  db/  format  hooks/  locks/  README.txt
This command creates a new directory /path/to/repos which contains a Subversion repository. Make sure that this directory lives on a local disk, not a network share. This new directory mainly contains a collection of Berkeley DB database files. You won't see your versioned files if you peek inside. For more information about repository creation and maintenance, see Chapter 5.
Next, create a tree of files and directories to import into the repository. For reasons that will be clear later on (see Chapter 4), your structure should contain three top-level directories named branches, tags, and trunk:
/tmp/project/branches/
/tmp/project/tags/
/tmp/project/trunk/
               foo.c
               bar.c
               Makefile
               ...
Once you have a tree of data ready to go, import the data into the repository with the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: Basic Concepts
This chapter is a short, casual introduction to Subversion. If you're new to version control, this chapter is definitely for you. We begin with a discussion of general version control concepts, work our way into the specific ideas behind Subversion, and show some simple examples of Subversion in use.
Even though the examples in this chapter show people sharing collections of program source code, keep in mind that Subversion can manage any sort of file collection—it's not limited to helping computer programmers.
Subversion is a centralized system for sharing information. At its core is a repository, which is a central store of data. The repository stores information in the form of a filesystem tree—a typical hierarchy of files and directories. Any number of clients connect to the repository, and then read or write to these files. By writing data, a client makes the information available to others; by reading data, the client receives information from others. Figure 2-1 illustrates this. Why is this interesting? So far, this sounds like the definition of a typical file server. And, indeed, the repository is a kind of file server, although it's not your usual breed. What makes the Subversion repository special is that it remembers every change ever written to it: every change to every file, and even changes to the directory tree itself, such as the addition, deletion, and rearrangement of files and directories.
Figure 2-1: A typical client/server system
When a client reads data from the repository, it normally sees only the latest version of the filesystem tree. But the client also has the ability to view previous states of the filesystem. For example, a client can ask historical questions like, What did this directory contain last Wednesday? or Who was the last person to change this file, and what changes did they make? These are the sorts of questions that are at the heart of any version control system
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Repository
Subversion is a centralized system for sharing information. At its core is a repository, which is a central store of data. The repository stores information in the form of a filesystem tree—a typical hierarchy of files and directories. Any number of clients connect to the repository, and then read or write to these files. By writing data, a client makes the information available to others; by reading data, the client receives information from others. Figure 2-1 illustrates this. Why is this interesting? So far, this sounds like the definition of a typical file server. And, indeed, the repository is a kind of file server, although it's not your usual breed. What makes the Subversion repository special is that it remembers every change ever written to it: every change to every file, and even changes to the directory tree itself, such as the addition, deletion, and rearrangement of files and directories.
Figure 2-1: A typical client/server system
When a client reads data from the repository, it normally sees only the latest version of the filesystem tree. But the client also has the ability to view previous states of the filesystem. For example, a client can ask historical questions like, What did this directory contain last Wednesday? or Who was the last person to change this file, and what changes did they make? These are the sorts of questions that are at the heart of any version control system: systems that are designed to record and track changes to data over time.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Versioning Models
The core mission of a version control system is to enable collaborative editing and sharing of data. However, different systems use different strategies to achieve this.
All version control systems have to solve the same fundamental problem: how will the system allow users to share information, but prevent them from accidentally stepping on each other's feet? It's all too easy for users to accidentally overwrite each other's changes in the repository.
Consider the scenario shown in Figure 2-2. Suppose we have two co-workers, Harry and Sally. They each decide to edit the same repository file at the same time. If Harry saves his changes to the repository first, then it's possible that (a few moments later) Sally could accidentally overwrite them with her own new version of the file. While Harry's version of the file won't be lost forever (because the system remembers every change), any changes Harry made won't be present in Sally's newer version of the file, because she never saw Harry's changes to begin with. Harry's work is still effectively lost—or at least missing from the latest version of the file—and probably by accident. This is definitely a situation we want to avoid!
Figure 2-2: The problem to avoid
Many version control systems use a lock-modify-unlock model to address this problem. In such a system, the repository allows only one person to change a file at a time. First Harry must lock the file before he can begin making changes to it. Locking a file is a lot like borrowing a book from the library; if Harry has locked a file, then Sally cannot make any changes to it. If she tries to lock the file, the repository will deny the request. All she can do is read the file, and wait for Harry to finish his changes and release his lock. After Harry unlocks the file, his turn is over, and now Sally can take her turn by locking and editing. Figure 2-3 demonstrates this simple solution.
Figure 2-3: The lock-modify-unlock solution
The problem with the lock-modify-unlock model is that it's a bit restrictive, and often becomes a roadblock for users:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Subversion in Action
It's time to move from the abstract to the concrete. In this section, we'll show real examples of Subversion being used.
You've already read about working copies; now we'll demonstrate how the Subversion client creates and uses them.
A Subversion working copy is an ordinary directory tree on your local system, containing a collection of files. You can edit these files however you wish, and if they're source code files, you can compile your program from them in the usual way. Your working copy is your own private work area: Subversion will never incorporate other people's changes, nor make your own changes available to others, until you explicitly tell it to do so.
After you've made some changes to the files in your working copy and verified that they work properly, Subversion provides you with commands to publish your changes to the other people working with you on your project (by writing to the repository). If other people publish their own changes, Subversion provides you with commands to merge those changes into your working directory (by reading from the repository).
A working copy also contains some extra files, created and maintained by Subversion, to help it carry out these commands. In particular, each directory in your working copy contains a subdirectory named .svn, also known as the working copy administrative directory. The files in each administrative directory help Subversion recognize which files contain unpublished changes, and which files are out-of-date with respect to others' work.
A typical Subversion repository often holds the files (or source code) for several projects; usually, each project is a subdirectory in the repository's filesystem tree. In this arrangement, a user's working copy will usually correspond to a particular subtree of the repository.
For example, suppose you have a repository that contains two software projects, paint and
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Summary
We covered a number of fundamental Subversion concepts in this chapter:
  • We introduced the notions of the central repository, the client working copy, and the array of repository revision trees.
  • We gave some simple examples of how two collaborators can use Subversion to publish and receive changes from one another, using the copy-modify-merge model.
  • We talked a bit about the way Subversion tracks and manages information in a working copy.
At this point, you should have a good idea of how Subversion works in the most general sense. Armed with this knowledge, you should now be ready to jump into the next chapter, which is a detailed tour of Subversion's commands and features.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 3: Guided Tour
Now we go into the details of using Subversion. By the time you reach the end of this chapter, you will be able to perform almost all the tasks you need to use Subversion in a normal day's work. You'll start with an initial checkout of your code, and walk through making changes and examining those changes. You'll also see how to bring changes made by others into your working copy, examine them, and work through any conflicts that might arise.
Note that this chapter is not meant to be an exhaustive list of all Subversion's commands—rather, it's a conversational introduction to the most common Subversion tasks you'll encounter. This chapter assumes that you've read and understood Chapter 2 and are familiar with the general model of Subversion. For a complete reference of all commands, see Chapter 9.
Before reading on, here is the most important command you'll need when using Subversion: svn help. The Subversion command-line client is self-documenting—at any time, a quick svn help <subcommand> will describe the syntax, switches, and behavior of the subcommand.
You use svn import to import a new project into a Subversion repository. While this is most likely the very first thing you will do when you set up your Subversion server, it's not something that happens very often. For a detailed description of import, see Section 3.7.2 later in this chapter.
Before we continue, you should know a bit about how to identify a particular revision in your repository. As you learned in Section 2.3.2, a revision is a snapshot of the repository at a particular moment in time. As you continue to commit and grow your repository, you need a mechanism for identifying these snapshots.
You specify these revisions by using the --revision (-r) switch plus the revision you want (svn —revision REV), or you can specify a range by separating two revisions with a colon (svn —revision REV1:REV2). Subversion lets you refer to these revisions by number, keyword, or date.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Help!
Before reading on, here is the most important command you'll need when using Subversion: svn help. The Subversion command-line client is self-documenting—at any time, a quick svn help <subcommand> will describe the syntax, switches, and behavior of the subcommand.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Import
You use svn import to import a new project into a Subversion repository. While this is most likely the very first thing you will do when you set up your Subversion server, it's not something that happens very often. For a detailed description of import, see Section 3.7.2 later in this chapter.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Revisions: Numbers, Keywords, and Dates, Oh My!
Before we continue, you should know a bit about how to identify a particular revision in your repository. As you learned in Section 2.3.2, a revision is a snapshot of the repository at a particular moment in time. As you continue to commit and grow your repository, you need a mechanism for identifying these snapshots.
You specify these revisions by using the --revision (-r) switch plus the revision you want (svn —revision REV), or you can specify a range by separating two revisions with a colon (svn —revision REV1:REV2). Subversion lets you refer to these revisions by number, keyword, or date.
When you create a new Subversion repository, it begins its life at revision zero and each successive commit increases the revision number by one. After your commit completes, the Subversion client informs you of the new revision number:
$ svn commit --message "Corrected number of cheese slices."
Sending        sandwich.txt
Transmitting file data .
Committed revision 3.
If at any point in the future you want to refer to that revision (we'll show how and why you might want to do that later in this chapter), you can refer to it as 3.
The Subversion client understands a number of revision keywords. These keywords can be used instead of integer arguments to the --revision switch, and are resolved into specific revision numbers by Subversion:
Each directory in your working copy contains an administrative subdirectory called .svn. For every file in a directory, Subversion keeps a copy of each file in the administrative area. This copy is an unmodified (no keyword expansion, no end-of-line translation, no nothing) copy of the file as it existed in the last revision (called the BASE revision) that you updated it to in your working copy. We refer to this file as the pristine copy or text-base version of your file, and it's always an exact byte-for-byte copy of the file as it exists in the repository.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Initial Checkout
Most of the time, you start using a Subversion repository by doing a checkout of your project. Checking out a repository creates a copy of it on your local machine. This copy contains the HEAD (latest revision) of the Subversion repository that you specify on the command line:
$ svn checkout http://svn.collab.net/repos/svn/trunk
A  trunk/subversion.dsw
A  trunk/svn_check.dsp
A  trunk/COMMITTERS
A  trunk/configure.in
A  trunk/IDEAS
...
Checked out revision 2499.
Although the previous example checks out the trunk directory, you can just as easily check out any deep subdirectory of a repository by specifying the subdirectory in the checkout URL:
$ svn checkout http://svn.collab.net/repos/svn/trunk/doc/book/tools
A  tools/readme-dblite.html
A  tools/fo-stylesheet.xsl
A  tools/svnbook.el
A  tools/dtd
A  tools/dtd/dblite.dtd
...
Checked out revision 3678.
Since Subversion uses a copy-modify-merge model instead of lock-modify-unlock (see Chapter 2), you're already able to start making changes to the files and directories in your working copy. Your working copy is just like any other collection of files and directories on your system. You can edit and change them, move them around, you can even delete the entire working copy and forget about it.
While your working copy is just like any other collection of files and directories on your system, you need to let Subversion know if you're going to be rearranging anything inside of your working copy. If you want to copy or move an item in a working copy, you should use svn copy or svn move instead of the copy and move commands provided by your operating system. We'll talk more about svn copy and svn move later in this chapter.
Unless you're ready to commit a new file or directory, or changes to existing ones, there's no need to further notify the Subversion server that you've done anything.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Basic Work Cycle
Subversion has numerous features, options, bells, and whistles, but on a day-to-day basis, odds are that you will only use a few of them. In this section we run through the most common things that you might find yourself doing with Subversion in the course of a day's work.
The typical work cycle looks like this:
  • Update your working copy
    • svn update
  • Make changes
    • svn add
    • svn delete
    • svn copy
    • svn move
  • Examine your changes
    • svn status
    • svn diff
    • svn revert
  • Merge others' changes
    • svn merge
    • svn resolved
    • Commit your changes
    • svn commit
When working on a project with a team, you may want to update your working copy to receive any changes made since your last update by other developers on the project. Use svn update to bring your working copy in sync with the latest revision in the repository.
$ svn update
U  foo.c
U  bar.c
Updated to revision 2.
In this case, someone else checked in modifications to both foo.c and bar.c since the last time you updated, and Subversion has updated your working copy to include those changes.
Let's examine the output of svn update a bit more. When the server sends changes to your working copy, a letter code is displayed next to each item to let you know what actions Subversion performed to bring your working copy up-to-date:
U foo
File foo was Updated (received changes from the server).
A foo
File or directory foo was Added to your working copy.
D foo
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Examining History
As we mentioned earlier, the repository is like a time machine. It keeps a record of every change ever committed, and allows you to explore this history by examining previous versions of files and directories, as well as the metadata that accompanies them. With a single Subversion command, you can check out the repository (or restore an existing working copy) exactly as it was at any date or revision number in the past. However, sometimes you just want to "peer into" the past instead of "going into" the past.
There are several commands that can provide you with historical data from the repository:
svn log
Shows you broad information: log messages attached to revisions, and which paths changed in each revision.
svn diff
Shows you the specific details of how a file changed over time.
svn cat
Used to retrieve any file as it existed in a particular revision number and display it on your screen.
svn list
Displays the files in a directory for any given revision.
To find out information about the history of a file or directory, use the svn log command. svn log will provide you with a record of who made changes to a file or directory, at what revision it changed, the time and date of that revision, and, if it was provided, the log message that accompanied the commit.
$ svn log
------------------------------------------------------------------------
r3 | sally | Mon, 15 Jul 2002 18:03:46 -0500 | 1 line

Added include lines and corrected # of cheese slices.
------------------------------------------------------------------------
r2 | harry | Mon, 15 Jul 2002 17:47:57 -0500 | 1 line

Added main( ) methods.
------------------------------------------------------------------------
r1 | sally | Mon, 15 Jul 2002 17:40:08 -0500 | 1 line

Initial import
------------------------------------------------------------------------
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Other Useful Commands
While not as frequently used as the commands previously discussed in this chapter, you occasionally need the following commands.
When Subversion modifies your working copy (or any information within .svn), it tries to do so as safely as possible. Before changing anything, it writes its intentions to a log file, executes the commands in the log file, then removes the log file (this is similar in design to a journaled filesystem). If a Subversion operation is interrupted (if the process is killed, or if the machine crashes, for example), the log files remain on disk. By re-executing the log files, Subversion can complete the previously started operation, and your working copy can get itself back into a consistent state.
And this is exactly what svn cleanup does: it searches your working copy and runs any leftover logs, removing locks in the process. If Subversion ever tells you that some part of your working copy is locked, then this is the command that you should run. Also, svn status will display an L next to locked items:
$ svn status
  L    somedir
M      somedir/foo.c 

$ svn cleanup
$ svn status
M      somedir/foo.c
The svn import command is a quick way to copy an unversioned tree of files into a repository, creating intermediate directories as necessary.
$ svnadmin create /usr/local/svn/newrepos
$ svn import mytree file:///usr/local/svn/newrepos/some/project
Adding         mytree/foo.c
Adding         mytree/bar.c
Adding         mytree/subdir
Adding         mytree/subdir/quux.h

Committed revision 1.
The previous example copied the contents of directory mytree under the directory some/project in the repository:
$ svn ls file:///usr/local/svn/newrepos/some/project
bar.c
foo.c
subdir/
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Summary
At this point, we've covered most of the Subversion client commands. Notable exceptions are those dealing with branching and merging (see Chapter 4) and properties (see Section 7.2). However, you may want to take a moment to skim through Chapter 9 to get an idea of all the many different commands that Subversion has—and how you can use them to make your work easier.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 4: Branching and Merging
Branching, tagging, and merging are concepts common to almost all version control systems. If you're not familiar with these ideas, we provide a good introduction in this chapter. If you are familiar with them, then hopefully you'll find it interesting to see how Subversion implements these ideas.
Branching is a fundamental part of version control. If you're going to allow Subversion to manage your data, this is a feature you'll eventually come to depend on. This chapter assumes that you're already familiar with Subversion's basic concepts (Chapter 2).
Suppose it's your job to maintain a document for a division in your company, a handbook of some sort. One day a different division asks you for the same handbook, but with a few parts "tweaked" for them, since they do things slightly differently.
What do you do in this situation? You do the obvious thing: you make a second copy of your document, and begin maintaining the two copies separately. As each department asks you to make small changes, you incorporate them into one copy or the other.
You often want to make the same change to both copies. For example, if you discover a typo in the first copy, it's very likely that the same typo exists in the second copy. The two documents are almost the same, after all; they only differ in small, specific ways.
This is the basic concept of a branch—namely, a line of development that exists independently of another line, yet still shares a common history if you look far enough back in time. A branch always begins life as a copy of something, and moves on from there, generating its own history (see Figure 4-1).
Figure 4-1: Branches of development
Subversion has commands to help you maintain parallel branches of your files and directories. It allows you to create branches by copying your data, and remembers that the copies are related to one another. It also helps you duplicate changes from one branch to another. Finally, it can make portions of your working copy reflect different branches, so that you can mix and match different lines of development in your daily work.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
What's a Branch?
Suppose it's your job to maintain a document for a division in your company, a handbook of some sort. One day a different division asks you for the same handbook, but with a few parts "tweaked" for them, since they do things slightly differently.
What do you do in this situation? You do the obvious thing: you make a second copy of your document, and begin maintaining the two copies separately. As each department asks you to make small changes, you incorporate them into one copy or the other.
You often want to make the same change to both copies. For example, if you discover a typo in the first copy, it's very likely that the same typo exists in the second copy. The two documents are almost the same, after all; they only differ in small, specific ways.
This is the basic concept of a branch—namely, a line of development that exists independently of another line, yet still shares a common history if you look far enough back in time. A branch always begins life as a copy of something, and moves on from there, generating its own history (see Figure 4-1).
Figure 4-1: Branches of development
Subversion has commands to help you maintain parallel branches of your files and directories. It allows you to create branches by copying your data, and remembers that the copies are related to one another. It also helps you duplicate changes from one branch to another. Finally, it can make portions of your working copy reflect different branches, so that you can mix and match different lines of development in your daily work.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Using Branches
At this point, you should understand how each commit creates an entire new filesystem tree (called a revision) in the repository. If not, go back and read about revisions in Section 2.3.2.
For this chapter, we'll go back to the same example from Chapter 2. Remember that you and your collaborator, Sally, are sharing a repository that contains two projects, paint and calc. Notice, however, that in Figure 4-2 each project directory now contains subdirectories named trunk and branches. The reason for this will soon become clear.
Figure 4-2: Starting repository layout
As before, assume that Sally and you both have working copies of the calc project. Specifically, you each have a working copy of /calc/trunk. All the files for the project are in this subdirectory rather than in /calc itself, because your team has decided that /calc/trunk is where the main line of development is going to take place.
Let's say that you've been given the task of performing a radical reorganization of the project. It will take a long time to write, and will affect all the files in the project. The problem here is that you don't want to interfere with Sally, who is in the process of fixing small bugs here and there. She's depending on the fact that the latest version of the project (in /calc/trunk) is always usable. If you start committing your changes bit by bit, you'll surely break things for Sally.
One strategy is to crawl into a hole: you and Sally can stop sharing information for a week or two. That is, start gutting and reorganizing all the files in your working copy, but don't commit or update until you're completely finished with the task. There are a number of problems with this, though. First, it's not very safe. Most people like to save their work to the repository frequently, should something bad accidentally happen to their working copy. Second, it's not very flexible. If you do your work on different computers (perhaps you have a working copy of /calc/trunk on two different machines), you'll need to manually copy your changes back and forth, or just do all the work on a single computer. By that same token, it's difficult to share your changes in progress with anyone else. A common software development best practice is to allow your peers to review your work as you go. If nobody sees your intermediate commits, you lose potential feedback. Finally, when you're finished with all your changes, you might find it very difficult to remerge your final work with the rest of the company's main body of code. Sally (or others) may have made many other changes in the repository that are difficult to incorporate into your working copy—especially if you run
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Copying Changes Between Branches
Now you and Sally are working on parallel branches of the project: you're working on a private branch, and Sally is working on the trunk, or main line of development.
For projects that have a large number of contributors, it's common for most people to have working copies of the trunk. Whenever someone needs to make a long-running change that is likely to disrupt the trunk, a standard procedure is to create a private branch and commit changes there until all the work is complete.
So, the good news is that you and Sally aren't interfering with each other. The bad news is that it's very easy to drift too far apart. Remember that one of the problems with the crawl-in-a-hole strategy is that by the time you're finished with your branch, it may be near impossible to merge your changes back into the trunk without a huge number of conflicts.
Instead, you and Sally might continue to share changes as you work. It's up to you to decide which changes are worth sharing; Subversion gives you the ability to selectively copy changes between branches. And when you're completely finished with your branch, your entire set of branch changes can be copied back into the trunk.
In the previous section, we mentioned that both you and Sally made changes to integer.c on different branches. If you look at Sally's log message for revision 344, you can see that she fixed some spelling errors. No doubt, your copy of the same file still has the same spelling errors. It's likely that your future changes to this file will be affecting the same areas that have the spelling errors, so you're in for some potential conflicts when you merge your branch someday. It's better, then, to receive Sally's change now, before you start working too heavily in the same places.
It's time to use the svn merge command. This command, it turns out, is a very close cousin to the svn diff command (which you read about in Chapter 3). Both commands are able to compare any two objects in the repository and describe the differences. For example, you can ask
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Common Use-Cases for Merging
There are many different uses for svn merge, and this section describes the most common scenarios.
To complete our running example, we'll move forward in time. Suppose several days have passed, and many changes have happened on both the trunk and your private branch. Suppose that you've finished working on your private branch; the feature or bug fix is finally complete, and now you want to merge all of your branch changes back into the trunk for others to enjoy.
So how do we use svn merge in this scenario? Remember that this command compares two trees, and applies the differences to a working copy. So to receive the changes, you need to have a working copy of the trunk. We'll assume that either you still have your original one lying around (fully updated), or that you recently checked out a fresh working copy of /calc/trunk.
But which two trees should be compared? At first glance, the answer may seem obvious: just compare the latest trunk tree with your latest branch tree. But beware—this assumption is wrong, and has burned many a new user! Since svn merge operates like svn diff, comparing the latest trunk and branch trees will not merely describe the set of changes you made to your branch. Such a comparison shows too many changes: it would not only show the addition of your branch changes, but also the removal of trunk changes that never happened on your branch.
To express only the changes that happened on your branch, you need to compare the initial state of your branch to its final state. Using svn log on your branch, you can see that your branch was created in revision 341. And the final state of your branch is simply a matter of using the HEAD revision. That means you want to compare revisions 341 and HEAD of your branch directory, and apply those differences to a working copy of the trunk.
A nice way of finding the revision in which a branch was created (the "base" of the branch) is to use the -
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Switching a Working Copy
The svn switch command transforms an existing working copy into a different branch. While this command isn't strictly necessary for working with branches, it provides a nice shortcut to users. In an earlier example, after creating your private branch, you checked out a fresh working copy of the new repository directory. Instead, you can simply ask Subversion to change your working copy of /calc/trunk to mirror the new branch location:
$ cd calc

$ svn info | grep URL
URL: http://svn.example.com/repos/calc/trunk

$ svn switch http://svn.example.com/repos/calc/branches/my-calc-branch
U   integer.c
U   button.c
U   Makefile
Updated to revision 341.

$ svn info | grep URL
URL: http://svn.example.com/repos/calc/branches/my-calc-branch
After switching to the branch, your working copy is no different than what you would get from doing a fresh checkout of the directory. And it's usually more efficient to use this command, because often branches only differ by a small degree. The server sends only the minimal set of changes necessary to make your working copy reflect the branch directory.
The svn switch command also takes a --revision (-r) option, so you need not always move your working copy to the tip of the branch.
Of course, most projects are more complicated than our calc example, containing multiple subdirectories. Subversion users often follow a specific algorithm when using branches:
  1. Copy the project's entire trunk to a new branch directory.
  2. Switch only part of the trunk's working copy to mirror the branch.
In other words, if users know that the branch-work only needs to happen on a specific subdirectory, they use svn switch to move only that subdirectory to the branch. (Sometimes users will switch just a single working file to the branch!) That way, they can continue to receive normal trunk updates to most of their working copy, but the switched portions will remain immune (unless someone commits a change to their branch). This feature adds a whole new dimension to the concept of a mixed working copy—not only can working copies contain a mixture of working revisions, but a mixture of repository locations as well.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Tags
Another common version control concept is a tag. A tag is just a snapshot of a project in time. In Subversion, this idea already seems to be everywhere. Each repository revision is exactly that—a snapshot of the filesystem after each commit.
However, people often want to give more human-friendly names to tags, like release-1.0. And they want to make snapshots of smaller subdirectories of the filesystem. After all, it's not so easy to remember that release-1.0 of a piece of software is a particular subdirectory of revision 4822.
Once again, svn copy comes to the rescue. If you want to create a snapshot of /calc/trunk exactly as it looks in the HEAD revision, then make a copy of it:
$ svn copy http://svn.example.com/repos/calc/trunk \
           http://svn.example.com/repos/calc/tags/release-1.0 \
      -m "Tagging the 1.0 release of the 'calc' project."

Committed revision 351.
This example assumes that a