IntroductionSubversion fulfills two different functions :
Software packages that combine these two functions are called version control systems. Compared to other version control systems, Subversion is reputed to be simple, dependable and fast. These qualities has made it a fixture of open-source software development and frequently used in the industry. Why use Subversion? Because it will make you bolder. Facing a large refactoring is scary. What if your changes are worse than the original? What if I can't put things back the way they were? With subversion, do a commit (aka, make a backup), then proceed. The commit will only take 1 second of your time and 1 kb of your disk space (or some other small amounts). Then, if you paint yourself in a corner, reverting will take only 1 second as well. Similarly, Subversion lets you boldly remove dead code and dead prose. If you ever need to remind yourself how you solved a tricky problems in a previous version, Subversion's revision history will be there for you. Subversion was developed with software development in mind. Nevertheless, it is a general tool, suitable for all kinds of projects, such as documentation projects or website development. Although some of its functionality works better on flat text files, and most usage examples on the web pertains to source code, Subversion is not limited to flat files. It will handle files of any format.
Fetching and Navigating VersionsAuthors of open-source programs often distribute their source code through Subversion. For example, the following command copies the source code implementing the experimental programming language FrTime (by the research group PLT Scheme) into your current directory. To follow this tutorial, type on your command lines the lines that begin with a dollar sign (do not type the dollar sign.) $ svn checkout http://svn.plt-scheme.org/plt/trunk/collects/frtime/ FrTime's source code is hosted on a Web server, so the URL that specify where to fetch the source code from begins with http://. For your own Subversion repositories, using a Web server will be optional. You are likely to store them in a local directory, in which case the URL will begin with file:///. You may also encounter source code distributed over Subversion's own protocol, which are reachable using URLs that begin with svn+ssh://. The command checkout operates like a file copy. In the previous command, the source of the copy was a directory called frtime, and the destination was your current directory (by default). Thus, you will find a subdirectory called frtime in your current directory. $ cd frtime/ $ ls animation.ss frp-snip.ss graphics-sig.ss list.ss base-gm.ss frtime-big.ss graphics-unit.ss lowered- [...] This directory is called a working directory, because it remembers its source. You can see this with the info command. $ svn info Path: . URL: http://svn.plt-scheme.org/plt/trunk/collects/frtime Repository Root: http://svn.plt-scheme.org/plt Repository UUID: dd0f82c0-e3f7-0310-82dd-f13d63558e96 Revision: 10393 [...] In Subversion parlance, the source is called a repository. The link between the working directory and the repository is implemented as a hidden subdirectory named .svn. You can see hidden directories with ls -lAd. $ ls -lAd .svn drwxr-xr-x+ 6 Admin None 0 Jun 20 21:20 .svn If you were to delete .svn, the link would be lost and your working directory would revert to being a normal directory. The info command also tells us that FrTime's repository contains 10393 revisions. When you real run the command, there will surely be more. Indeed, FrTime is a part of the large PLT Scheme project, whose developer community is so large they commit more than 10 new backups per day. The update command can time-warp your working directory to any one of these revisions. For example, you can go back to the evening of July 21, 2005, when developer gcooper finished an important refactoring. $ svn update -r 420 D frtime.scrbl D lowered-equivs.ss D lang.ss [...] Updated to revision 420. Each revision remembers (amongst other things) the name of its author, its date, and a short message by the author describing the changes. We can retrieve that information with the log command. $ svn log -r 420 ----------------------------------------------------------------- r420 | gcooper | 2005-07-21 23:36:23 +0530 (Thu, 21 Jul 2005) | 6 lines - new and improved model for conditionals based on "super-lift" - added quasiquote - made structures memory-efficient - removed "non-scheduled" dependencies - split into several modules ----------------------------------------------------------------- If we do not use the -r flag to specify a revision, the log command shows the messages of all revisions. The output might be long, so you will want to pipe to less. $ svn log|less [... lots of text] And, without a revision argument, the update command brings the working directory back to the latest version. $ svn update U info.ss UU frp-snip.ss U graphics.ss U frtime-tool.ss [...] Updated to revision 10393. Working directories are expendable. They are easy make and easy to delete. After all, the source code is safely kept by the repository; we can fetch it again if we need to. Once you're done navigating the history of the FrTime project, you may delete your working directory. As a precaution, before the deletion take a moment to confirm that everything in your working directory is indeed safeguarded in the repository. $ svn status [no output] That's good. If there were some stragglers files, or modifications you needed to save, the status command would have highlighted them, like this: $ echo "Blue stragglers are stars of higher luminosity than the \ turnoff point of normal main sequence stars" > stragglers.txt $ echo ";; this is a Scheme comment added at the bottom of an \ important source file." >> main.ss $ svn status ? stragglers.txt M main.ss The question mark indicates that stragglers.txt is not saved in the repository, and the letter M says that main.ss was modified but not committed. We will be happy to lose both of these ill-advised modifications to the FrTime source code, so we just remove the working directory. $ cd .. $ rm -rf frtime Creating a RepositoryA Subversion repository is a disk-based abstract data type (ADT) which represent a revision as a delta to the previous version. The invariant of the ADT guarantees that, once stored in Subversion, directories can be retrieved without any damage to their files' content, their names, or their permissions. In addition, the data structure has provisions for safe concurrent access. The Subversion project created two different implementations of that ADT. The original implementation used the BerkeleyDB database in an unconventional way, which sometime resulted in corruption and on-disk memory leaks (disc leaks?). Recognizing this, the developers abandoned the BerkeleyDB for their second implementation, and the problems disappeared. (Programmers who are familiar with ADTs will applaud the Subversion team for coding to an interface. If they hadn't, the transition would have been much more difficult.) When you create your repository, make sure you select the second implementation, called (oddly) the file-system file system. Using the svnadmin command, we can create three repositories for three different projects: $ cd ~ $ mkdir svn-repositories; cd svn-repositories $ svnadmin create --fs-type fsfs website-repository $ svnadmin create --fs-type fsfs hello-world-repository $ svnadmin create --fs-type fsfs phd-thesis-repository Note that, since svnadmin cannot access or create repositories remotely, it does not use the URL notation. It is important to create one repository per project, because repositories are monotonic and atomic.
By sticking to one project per repository, you can backup them independently, and delete them as they become obsolete. The representation of repositories is opaque (in the ADT sense). Aside from making wholesale copies (for backups), you should only manipulate them via svn and svnadmin. $ ls website-repository/ README.txt conf dav db format hooks locks $ cat website-repository/README.txt This is a Subversion repository; use the 'svnadmin' tool to examine it. Do not add, delete, or modify files here unless you know how to avoid corrupting the repository.
Starting a New Working DirectoryThere are two ways to start working from your newly-created repository. The first way is when your project hasn't started yet. In this case you simply checkout an empty working directory. $ cd ~ $ svn co file:///home/gm/svn-repositories/website-repository/ website Checked out revision 0. $ cd website $ ls [no output] $ ls -A .svn $ svn info Path: . URL: file:///home/gm/svn-repositories/website-repository [...]
The second way to get your first working directory is useful when you created the repository after the project has started. In this case, you already have a directory containing your project's files, and you need to promote it to a working directories. Do it as follow. Suppose you have been working on a website with a graphic banner, and that your file set happens to have a copy of the server log. $ mkdir existing-website $ cd existing-website/ $ touch index.html banner.jpg server.log $ ls banner.jpg index.html server.log You can turn the directory existing-website into a working directory with the following command: $ svn co file:///home/Admin/svn-repositories/website-repository/ . Checked out revision 0. Note the dot as the destination argument. The dot indicates to Subversion that you want to checkout into the current directory, which effectively upgrades it to a working directory. Adding, Modifying, and Committing FilesEven if a file is in a working directory, Subversion will not safeguard it unless you add it. In the existing-websites example, the three files in the working repository are not tracked, as indicated by the question marks in the output of the status command. We add the relevant files with the add command, leaving behind the server log. $ svn status ? banner.jpg ? index.html ? server.log $ svn add banner.jpg index.html A banner.jpg A index.html If we wanted to maintain backups of all files, including the server log, we would use svn add *. Once the files are added, we create a revision with the commit command. The commit command is the principal way to create new revisions -- use it often. $ svn commit -m 'beginning of the project' Adding banner.jpg Adding index.html Transmitting file data .. Committed revision 1. The -m flag specifies a message that will be attached to the revision (don't forget the quotes). Use empty double quotes to commit with an empty message. Note that adding the files did not create a revision on its own. It merely scheduled the files to be added during the next commit. After the commit, the log shows that the revision is safely saved in the repository, and the status reminds us that the server log was not backed up, which is what we wanted. $ svn log index.html ------------------------------------------------------------------------ r1 | gm | 2008-06-21 02:24:33 +0530 (Sat, 21 Jun 2008) | 1 line beginning of the project ------------------------------------------------------------------------ $ svn status ? server.log
$ echo '<!-- this is the end of index.html -->' >> index.html $ svn status ? server.log M index.html $ svn commit -m 'added a comment to the index' Sending index.html Transmitting file data . Committed revision 2. $ svn log index.html ------------------------------------------------------------------------ r2 | gm | 2008-06-21 03:07:54 +0530 (Sat, 21 Jun 2008) | 1 line added a comment to the index ------------------------------------------------------------------------ r1 | gm | 2008-06-21 02:24:33 +0530 (Sat, 21 Jun 2008) | 1 line beginning of the project ------------------------------------------------------------------------ Reverting, Moving, and Removing FilesWith Subversion, you can roll back to any revision stored in the repository. But most of the time you simply want to throw away the changes in your working directory and rollback to the latest commit. Subversion has a command just for this case. $ echo '<!-- I wonder how IE behaves with a open comment at \ the end of the file?' >> index.html $ svn status ? server.log M index.html $ svn revert index.html Reverted 'index.html' $ svn status ? server.log Equivalently, you can delete the file then ask for an up-to-date version. $ echo '<!-- How does IE behave with a open comment at \ the end of the file?' >> index.html $ rm index.html $ svn update Restored 'index.html' At revision 2. This behavior can be confusing when you are actually trying to remove the file from the project. In order to remove a file in such a way that update does not recover it, you must use Subversion's own rm command. $ svn rm index.html D index.html $ svn commit -m 'index.html is obsolete. It will soon be a cgi' Deleting index.html It goes without saying that removing index.html in such a way does not remove the file from previous revisions. The content of index.html can be recovered by using update to time-warp your working directory to a revision when the file existed. In addition to removing, other file manipulations must also be done via Subversion -- renaming, moving, and copying. If you rename (or move) a file without going through Subversion, update will insist to replace the file under its old name (or its old location). Worse, Subversion will ignore the file under its new name, and it will not be backed up. You can see this in the status: in the example below, big-banner.jpg is not being backed up, and banner.jpg is scheduled to reappear (as indicated by the exclamation-mark). $ mv banner.jpg big-banner.jpg $ svn status ? big-banner.jpg ? server.log ! banner.jpg $ svn up Restored 'banner.jpg' At revision 5. $ ls banner.jpg big-banner.jpg server.log $ svn status ? big-banner.jpg ? server.log $ rm big-banner.jpg (Note that up is short for update.) To affect a real move, you must use the command svn mv. $ svn mv banner.jpg big-banner.jpg A big-banner.jpg D banner.jpg $ svn ci -m 'renamed' Deleting banner.jpg Adding big-banner.jpg Committed revision 4. (Note that ci is short for commit). Subversion also has an equivalent of cp. While copying does not run into problems with updates, copying with svn cp lets Subversion share histories and deltas between the copies within the repository, which is more efficient than duplicating the bytes. $ svn cp banner.jpg big-banner.jpg A big-banner.jpg $ svn ci -m 'copied' Adding big-banner.jpg Committed revision 6. Like adding, the commands for deleting, moving or copying to not create new revisions. Commit does. Collaborating and Resolving ConflictsReferences |