Journal Articles
Browse in : |
All
> Journals
> CVu
> 172
(12)
All > Topics > Management (95) Any of these categories - All of these categories |
Note: when you create a new publication type, the articles module will automatically use the templates user-display-[publicationtype].xt and user-summary-[publicationtype].xt. If those templates do not exist when you try to preview or display a new article, you'll get this warning :-) Please place your own templates in themes/yourtheme/modules/articles . The templates will get the extension .xt there.
Title: A Subversion Primer
Author: Administrator
Date: 03 April 2005 13:16:11 +01:00 or Sun, 03 April 2005 13:16:11 +01:00
Summary:
This article provides an introduction to Subversion. It lists Subversion's key features and best working practices, provides cookbook recipes for all the common activities in your day-to-day development work, and points the reader to further reading.
Body:
This article provides an introduction to Subversion. It lists Subversion's key features and best working practices, provides cookbook recipes for all the common activities in your day-to-day development work, and points the reader to further reading.
It is intended for software developers and doesn't matter which operating system you use (although it would help to not be scared of the command line). It's useful to have an understanding of CVS, or some other version control system.
Disclaimer: If the information in here diverges from Subversion documentation, clearly I'm wrong and they're right. Terms and conditions apply. Your hair may be at risk if you do not keep up a loan secured on it.
- SCMS
-
Source Code Management System (e.g. CVS, ClearCase, or Subversion)
- CM
-
Configuration Management (development practices using SCMS)
- CVS
-
Concurrent Versions System, the de facto open source SCMS
Subversion was designed from the ground up as a modern, high-performance version control system. It is intended to be compelling SCMS replacement for the (now ageing) CVS[1]. It is freely available under an open source licence.
It is gaining popularity, a stable, production-quality system. It's now used in anger by public projects including Mono, Xiph, Apache, Samba, PuTTY, Debian, and Ethereal. I have used it for personal work, and deployed it in commercial development teams. I've found it to be an excellent, streamlined SCMS that is very usable.
Of the new breed of open SCMS tools around, this is really the only mature production worthy system.
Subversion follows the same modify-merge-commit model of CVS, so it should be familiar to most developers.
-
CVS-like interface
-
Directories, renames, and file metadata are versioned
-
Commits are truly atomic, they either totally succeed or totally fail
-
Commits are recorded as a changeset (a revision number applies to the whole file tree, not individual files)
-
Branching and tagging are cheap (constant time) operations
-
Efficient network usage
-
Cross platform: Windows, Linux, MacOS X, with several GUI front-ends
-
Good for offsite work (supports offline diff and revert)
-
Scales far better than CVS
-
Efficient binary file handling
-
Supports Apache and the WebDAV protocol (also has own protocol, which can be tunnelled over ssh)
-
MS Visual Studio integration
The feature sets of different SCMSs vary, although the core concepts (i.e. versioning a set of files) don't tend to differ significantly. There are a number of key facilities that Subversion does not provide that you may be used to:
-
Merge support is not so rich as some tools (it is as good as CVS, though)
-
There are no dynamic views (a ClearCase magic versioned file system)
-
There are no locking checkouts (strangely, they're working on this)
Depending on your SCMS religion, the last two points are actually huge benefits.
Subversion versioning is different from the CVS model. Unlike CVS, changes are atomic. When you check in multiple files you submit an atomic changeset. These file commits will either all succeed or all fail.
All the modifications made in one changeset are held together as a single revision, with a single checkin message.
Important difference: a revision number applies to the whole tree, unlike CVS where version numbers apply to each individual file. When you check in a single file, the whole file tree gets up-versioned (the files in your working copy do not all automatically get up-versioned, though). A revision number identifies how a file tree looked at a position in time.
For example: you check out foo.c from HEAD, and the repository is currently at version 5. You have 'version 5' of the file in your working copy. What you really have is foo.c as it appeared in version 5 of the repository. The file may not have changed since version 3. So consecutive version numbers of a single file may be identical.
The changeset idea is very powerful. Using it there is no need for a manually maintained changelog (updates) file, and it's easy to merge specific changesets from one branch to another.
Committing a single file effectively creates a new copy of the entire file tree in the repository (remember: the whole source tree goes up a version number). To do this Subversion provides very cheap copy operations. Subversion branches and tags (labels) exploit this fact, and so are also very cheap and quick operations. Their implementation is surprising to CVS developers.
Both branches and tags are stored in the repository as copies of a file set. Therefore, they exist at a physical point in the file structure. This is very different from the CVS branching/tagging model. A Subversion tag is not a property applied to a particular revision of a file, although it does still uniquely identify a set of files.
Both tags and branches are created in the same way, and the difference between the two is only what you do with them afterwards. A branch is a copy created with the express purpose of performing additional development work, work that should be kept separate from the trunk. A tag is a copy that will not be worked on (you can still merge changesets into a tag copy, in order to 'move' the tag).
Branches and tags can have finite lifetimes - as versioned objects in the repository you can delete them like any other object. This will not lose the history of their existence, and is a powerful tool that helps to keep your repository neat.
There is no fixed directory structure in a repository, although there are conventions that Subversion users generally follow. A repository may contain a number of projects, each in their own top-level directory. A project directory has three subdirectories:
- trunk
-
contains the main line of code development
- branches
-
contains all branch copies of code development
- tags
-
contains all tag copies of code development
The branches and tags directories both hold Subversion copies of a version of the trunk file set.
-
When you check out a working copy of the repository, Subversion makes a physical copy of the files on your hard disk. Each directory contains a .svn directory (akin to the CVS directory in CVS) where admin files are held. You must not poke around in here.
In that directory is held a pristine copy of the files you have checked out, so network utilisation is very efficient - file diffs are done at the client end, not on the server.
-
Subversion uses URIs to define a location in the repository. There are several different repository access methods, identified by the URI's transport (e.g. file: svn: http: and https:, you only use one of these at once!)
On Windows, URIs still use the Unix-like forward slash.
-
Most operations are applied to the working copy's file tree, in which case the modification is made locally, but no change occurs in repository until you perform a commit. Some operations also accept repository URIs; these work directly on the repository files (the copy command is an example of this). In this case you do not even need to check out a working copy.
Here are some simple Subversion recipes to get you started. This should cover most of your day-to-day work. If you want to step beyond these examples, you can always type svn help for more information, or look at the Further Reading section, below.
These recipes show how to perform each operation using the Subversion command line client (svn). The exercise is similar using one of the available GUI front ends (for example the MS Visual Studio Ankh plug-in); naturally you don't type a command, you click on helpful buttons instead. But despite all the GUI goodness you still have to understand what's going on behind the scenes - these recipes will make this clear. The Other Tools section towards the end of this article describes the various Subversion GUI front ends available.
In the following command line examples, the text you type is emboldened, the svn response is plain text. The repository URI location is represented as REPOSITORY, and I assume that the URI's transport is method svn:. Change this as appropriate.
Subversion commands have both a long form (e.g. checkout) and a shortened form (co). I use the long form for clarity. The shortened versions are listed at the end of the document (see Shortened Commands).
Admittedly you don't do this very often, but it's a quick way to get a baselined project into a Subversion repository[2].
-
You want to import the widgetizer project into the repository.
-
You have made a top-level widgetizer directory structure in the repository (see below for that recipe).
svn import /path/to/widgetizer svn://REPOSITORY/widgetizer/trunk Adding widgetizer/main.c Adding widgetizer/other.c Committed revision 1
These changes are made to the repository immediately. Don't worry if you import to the wrong place, in Subversion it's easy to move things around afterwards (that's a later recipe).
Before you 'check out' files from the repository you can browse to see what you want to play with. (CVS doesn't provide this facility.)
svn list svn://REPOSITORY/widgetizer branches/ tags/ trunk/
Clearly, if there is a ViewCVS system (a web-based repository browse application) set up, you would use that in preference.
-
You've identified the project subdirectory you want to check out, and know whether you want the trunk or a branch.
cd ~/Work svn checkout svn://REPOSITORY/widgetizer/trunk A widgetizer/trunk/main.c A widgetizer/trunk/other.c Checked out revision 1
The A above stands for 'Added'. We'll see more output like this later. You have now created a working copy of the repository.
You can choose to check out a whole project or just a specific file or directory.
You can edit the files immediately; there is no need to issue a Subversion command to 'open' them for editing. Of course, this means that someone else could be editing the same file as you at the same time. More on that later…
-
You've modified some of the files in your working copy.
-
Before you commit the changes to the repository, you want to see what you've changed.
cd widgetizer/trunk svn status M main.c M other.c
The M above stands for 'Modified'. Files with no difference from the repository[3] are not listed. The most common status codes are:
- M
-
The contents of this file have been changed
- ?
-
This file is not in the repository (you may want to svn add it)
- A
-
File is scheduled for addition
- D
-
File is scheduled for deletion
- C
-
File has conflicts which need resolving (see below)
- S
-
File has been switched to a branch (see below)
- !
-
File is managed by Subversion, but it's missing in your working copy
CVS users, note: Subversion doesn't need you to subvert the update command to do this kind of inspection. (CVS users routinely type cvs -nq update to list modifications because the output of cvs status is not at all helpful.)
You can give a specific filename as an argument to svn status to get information on it alone.
-
You know that you've changed a file.
-
You want to look at the complete set of changes to compose a suitable checkin message.
svn diff other.c Index: other.c ======================================= -- other.c (revision 2) +++ other.c (working copy) @@ -1,4 +1,5 @@ int m; int n; -int p; +int o; $
You can compare your working copy to a specific repository revision using the -r switch, and can compare two repository versions by specifying a range. For example, to see the last change made to main.c:
svn diff -r PREV:COMMITTED main.c Index: main.c ...
-
You've edited a file (or files), and want to check it in to the repository.
svn commit --message "Changed the default \ banana count" other.c
... or ...
svn commit --file log-message-file other.c Sending other.txt Transmitting file data . Committed version 3.
If you don't specify a message on the command line, Subversion opens your default editor (as specified by the EDITOR environment variable) to prompt you for it.
Note: You can't perform a checkin if someone else has modified the files and checked them in before you. In this case, Subversion will moan at you:
svn commit -m "Changed the default banana \ count" other.c Sending other.txt svn: Commit failed (details follow): svn: Out of date: 'other.c' in transaction 'k'
You must first update to the HEAD version (recipe below) and then try to check in.
-
You want to add a new file to the widgetizer project.
-
You have created it in your working copy.
svn add new.c A new.c svn commit -m "Added" new.c
Note that the file doesn't get put into the repository until you issue a commit command.
-
You want to modify the layout of files within a directory.
svn move new.c old.c A old.c D new.c svn copy old.c copy.c A copy.c svn commit -m "Changed file structure" ...
-
You made a mistake when altering main.c, and want to back out your changes, restoring the previous revision that you checked out.
svn revert main.c Reverted 'main.c'
Files change in the repository whilst you are working; your working copy will become outdated. Periodically (and usually before you check in) you must update your working copy to the latest repository state-of-the-art.
If a file that you are modifying has been changed by someone else then Subversion, like CVS, will attempt to merge the changes automatically into your working copy. Usually this works fine. Occasionally a conflict occurs, when Subversion doesn't know how to perform a merge because the changes interfere with each other. This is dealt with in the next recipe.
-
You want to see what files have changed in the repository since you last updated
svn status --show-updates
... or ...
svn status -u M * main.c * other.c
The * shows that an update must be taken from the repository. The M shows that you have modified a file locally: Subversion will merge the repository change into your modified copy.
-
You want to bring in the latest version of other.c, but leave main.c in the current working copy
svn update other.c U other.c Updated to revision 4.
Notes:
-
Working copies are not dynamic, so you are in control of when you pull in other people's changes. This is especially useful during builds - no files will change during your build process, so you can be assured of the build's integrity.
-
Your working copy can contain a random collection of file version numbers (you can commit and update files independently).
-
You can use the -r argument to shift to a particular file revision.
-
You performed a svn update, and a file had conflicts (the update output message showed a file with C status).
-
You can't check your version of the file in until you have resolved the conflict.
-
Open the conflicted file in your editor. You will see the conflicts flagged between conflict markers that highlight the problem changes.
-
Subversion has created three extra files in your working copy directory:
-
filename.mime - the copy of filename that was in your working copy directory before you ran svn update.
-
filename.rOLDREV - The file that was the BASE revision before you ran svn update.
-
filename.rNEWREV - The new version that came from the repository.
-
-
Merge the changes manually.
-
Then type the following command to tell Subversion that you have resolved the conflict (note: this is an extra step over CVS operation):
svn resolved other.c Resolved conflicted state of 'other.c'
-
You want to see how the file other.c changed over time.
svn log other.c --------------------------------- r3 | pete | Tue, 16 Dec 2004 12:23:12 +0000 | 1 line Changed the default banana count --------------------------------- r2 | pete | Tue, 16 Dec 2004 12:16:43 +0000 | 1 line Added ---------------------------------
You want to branch the HEAD of your project's trunk into a branch called trout, to perform some parallel development work .
svn copy \ svn://REPOSITORY/widgetizer/trunk \ svn://REPOSITORY/widgetizer/branches/trout \ -m "Created trout branch" Committed revision 128.
Note: we didn't need to have a working copy checked out to perform this operation, since we used URIs into the repository. (You can also do this locally in a working copy, but there's not much point.)
-
Having created a branch, you want to check it out and start working on it.
svn checkout \ svn://REPOSITORY/widgetizer/branches/trout A trout/main.c A trout/other.c Checked out revision 128.
This new branch is a separate physical directory from the trunk. However, it retains all the file revision history (try a svn log on a file).
Alternatively, if you already have a working copy checked out, and you want to switch it to view the branch, use svn switch:
svn info | grep URL URL: svn://REPOSITORY/widgetizer/trunk svn switch svn://REPOSITORY/widgetizer/branches/trout U main.c U other.c Updated to revision 128. svn info | grep URL URL: svn://REPOSITORY/widgetizer/branches/trout
This is more efficient than checking out a whole new tree, and also allows you to switch just a single directory, or even a single file.
You can now use your branch version of the working directory as if it was the trunk. All checkins you make appear only on the branch, without affecting trunk at all.
-
Your work on the trout branch is sufficiently advanced that it should be merged back onto the mainline of development, into trunk.
-
Create a working copy of the trunk, then identify the range of changes that you want, merge them into the trunk, and check in:
cd ~/Work/trout svn update At revision 132. svn log --verbose --stop-on-copy The final revision number listed is the start of the branch, let's say it's 2 cd ~/Work/trunk svn merge -r 2:132 svn://REPOSITORY/widgetizer/branches/trout M main.c M other.c svn commit -m "Merged trout changes r2:r132 \ into the trunk" ...
Like CVS, Subversion doesn't record a merge history, so you have to be careful when you merge a branch into trunk multiple times. Always specify revision numbers in great detail when you write the log message, next time you merge you will want to merge the range 133:HEAD, not 2:HEAD.
-
You release the first version of your software and want to tag the source code that built it.
svn copy \ svn://REPOSITORY/widgetizer/trunk \ svn://REPOSITORY/widgetizer/tags/Release1 \ -m "Created release 1 tag" Committed revision 326.
This is a very simple tag operation (but probably the most common). You can tag more eclectic collections of files. Update your working copy to the set of file versions that you want to tag (using svn update -r). Then:
svn copy \ my-working-copy \ svn://REPOSITORY/widgetizer/tags/TagName \ -m "Created release 1 tag" Committed revision 327.
-
Some idiot (you, probably) checked a blatantly wrong revision into the repository.
-
You want to revert the change.
svn merge -r 10:9 svn://REPOSITORY/widgetizer/trunk/main.c U main.c svn commit -m "Undoing change committed in r10" ...
Subversion commands can be abbreviated to save you some typing. The following table shows the abbreviations for the common commands:
Long form | Short (alternate) form |
---|---|
checkout | co |
checkin | ci |
copy | cp |
delete | rm, del, remove |
help | ?, h |
list | ls |
move | mv |
status | stat, st |
switch | sw |
update | up |
-revision | -r |
-show-updates | -u |
Table 1. Shortened forms of Subversion commands
Subversion has been designed to work as much like CVS as is practical. Most of your CVS knowledge translates directly into Subversion. The following table shows the Subversion equivalents of common CVS commands:
CVS command | Subversion command |
---|---|
cvs co | svn co |
cvs ci | svn ci |
cvs tag | svn copy |
cvs -ng update | svn status |
cvs diff | svn diff |
cvs tag -j | svn copy |
cvs add | svn add |
cvs update | svn update |
cvs merge | svn merge |
Table 2. CVS and Subversion commands compared
There are other tools that sit on top of Subversion. You may find them useful:
- TortoiseSVN
-
a Windows explorer plug-in providing a Subversion RMB submenu. This is an absolutely excellent Subversion front end, and I highly recommend it. It has an excellent history viewer, merge tool, repository browser, and much more. If you use Subversion under Windows you really want to get a hold of this. You can download it from http://tortoisesvn.tigris.org/
- RapidSVN
-
a cross-platform GUI front end for Subversion. In my experience this is an odd beast, and best avoided - the Tortoise front end is far superior.
- Ankh
-
a MS Visual Studio plug-in for the Subversion client. It works quite nicely, and I recommend it. Some Subversion operations are easier to perform through TortoiseSVN, so I tend to use both clients together. Ankh is not quite as polished as TortoiseSVN, but it is an excellent tool for VS developers.
You can download it from http://ankhsvn.tigris.org/
- ViewCVS
-
a web based repository viewer, originally for CVS, but now with Subversion support (at the moment there is no CVSGraph-like facility, sadly).
Subversion's svnadmin and svnlook tools. Mere mortals needn't ever use these; they are administration tools.
There are many other useful Subversion tools - I have seen very pretty Mac OS X clients (SvnX is a neat GUI front end and SCPlugin is a helpful Finder plug-in). Subclipse and Svn4Eclipse are Eclipse plug-ins. Look around for other useful Subversion plug-ins.
Subversion's homepage is http://www.subversion.org/
The free Subversion book is an excellent, thorough overview of the system. It is available from http://svnbook.org/ You can buy a dead tree version of this from O'Reilly, which is recommended. It's called Version Control with Subversion, ISBN: 0596004486.
Another recommended book is Pragmatic Version Control Using Subversion by The Pragmatic Programmers. ISBN: 0974514063.
There is a Latex Subversion quick reference card in the source distribution.
[1] For this reason I often compare a Subversion operation to the CVS counterpart in this document.
[2] Tools exist to help you import CVS projects and retain the version/branch history. See the Subversion website for details.
[3] Or, more accurately: no difference from the repository version that the working copy was checked out from.
Notes:
More fields may be available via dynamicdata ..