MacDevCenter    
 Published on MacDevCenter (http://www.macdevcenter.com/)
 See this if you're having trouble printing code examples


Making the Jump to Subversion

by Adam Swift
08/10/2004

If you haven't checked out Subversion, you should. It's a free, open source, powerful revision control system that was built to be a better CVS. It was created with clear design goals and built on top of robust, time-tested technologies. If you've been waiting for a better CVS and are ready to roll up your sleeves, skip directly to the Installing Subversion section of this article.

However, instead, you may be saying, "But c'mon, I'm a busy programmer, this sounds like extra work to me. Besides, CVS only punishes me on Tuesdays and Thursdays, and my team is already comfortable with it and its shortcomings."

After using CVS for years, I realized that it was influencing my software development decision-making just to avoid CVS's shortcomings! (For example: renaming or moving files and removing/renaming directories.) Though I consider this to be one of CVS's greatest crimes, it is only one of many good reasons to make the switch to Subversion.

In short, you should consider jumping to Subversion because:

  1. It's more of a skip than a jump.
  2. It's FREE.
  3. It not only fixes the main issues with CVS that will burn you, but it presents one of the best approaches to revision control available at any price. You can spend a good deal of money and still fall short of the ease-of-use and functional strengths of Subversion.

Also, thanks to the hard work of the Subversion open source community, installation is quick, easy, and uses the standard Mac OS X package installation tools. Alternatively, you can use Fink to install Subversion or download the source and build it by hand. Subversion is also available as downloadable, pre-built packages for a variety of platforms (Mac OS X, Linux, FreeBSD, Win32, etc.). See the official Subversion web site for a current listing.

Installing Subversion

Subversion can run stand-alone or on a network as a repository server with multiple clients. The preferred client/server configuration uses Apache and WebDAV for network communication. I strongly recommend using this style of networked repository server access. It provides the best combination of features, flexibility, and security. If for some reason this type of client/server configuration won't work in your environment, there are other supported configurations available.

You will need to designate one computer as the Subversion server. Subversion clients will connect to this server to access and manage source code and project resources. Secure access to the server can be configured via HTTPS or HTTP through SSH port tunneling. Put simply: HTTPS makes it easy to provide public, read-only access to the repository, and SSH tunneling has the advantage that only users with SSH access through the firewall can connect to the repository.

Because setting up HTTPS can be somewhat involved, this article will focus on HTTP access through SSH port tunneling. The same instructions used to configure HTTP access can be applied to an HTTPS-based connection. For more information about configuring HTTPS see the references listed at the end of this article.

Client-side Installation

Most users will only need to install the Subversion client-side tools. Download the statically linked package from Martin Ott's site or D. J. Hagberg's web page. Download the latest version of the Subversion client (currently Subversion-1.0.6.pkg.zip). Alternatively, see the server-side installation notes below for instructions on how to install the individual packages (the client installation only requires these packages: APR, APR-util, BerkeleyDB, Expat, Subversion).

After downloading, mount the disk image (or open the zip file) and use Apple's Installer application to install the Subversion client package. (Martin Ott's package will install into /opt/subversion with links from /usr/local/bin/; D. J. Hagberg's will install directly into /usr/local/bin/). For convenience, add the path to your executable search path. For the bash login shell, add the following lines to your ~/.bash_profile file:


PATH="/usr/local/bin:/usr/local/subversion/bin:$PATH" 
export PATH

To verify your installation, enter 'svn' into a terminal window. The command should respond with the message, "Type 'svn help' for usage.".

Server-side Installation

To set up a network accessible repository, you'll need to install a few packages on the computer you choose to use as the repository server. Once the packages are installed, then the actual repository must be created and configured for access from client users over the network.

Download and install these individual packages. The packages are available for download as disk images from Fred Sanchez's public iDisk at idisk.mac.com/wsanchez/Public/Software/packages/. Use the Finder to Connect to Server and enter the URL as the server address.


BerkeleyDB
Expat
Libxml2
Neon
SWIG
APR
APR-util
Apache2
Subversion

Mount the disk images and install all of the packages. If you are remotely connected to the server, you can use hdiutil to mount each disk image and use Installer to install the package from each volume mounted by the disk images.


% hdiutil attach <disk_image_file>
% installer -pkg <package_file> -target <target_volume>
In this example note that the installer command and all arguments must be entered on the same line; the \ is used to indicate line continuation:

% hdiutil attach ~/Desktop/Subversion_1.0.5.dmg
% installer -pkg /Volumes/Subversion_1.0.5/Subversion_1.0.5.pkg \
-target /

Each package will be installed into /usr/local/<package_name>.

Now you have all of the necessary packages installed on the server. The only remaining steps are to create the repository and set up client access.

Because you are using Apache to provide access to the repository, you'll need to create HTTP/Apache user accounts to determine repository access restrictions and ownership of file revisions in the repository. These are accounts used within the repository and are completely independent of the Unix/login accounts configured on the server. These accounts are set up as HTTP/Apache users.

Outside of the repository, you need an account that owns the repository database and supporting files. Apache2 will need to have read/write access to files owned by this account.

In reality, this is easy to deal with. Make the Mac OS X standard web server account, www, the owner of repository files and also the account that the Apache2 process runs as. Then create an HTTP/Apache authentication file using htpasswd to set up the users for the repository.

Enough talk, time for action! Create the repository on the server using the following command (perform the following commands as root or authenticated via sudo):


svnadmin create <path to repository>
chown -R www <path to repository>

Configure Apache2 to access the repository by editing /usr/local/apache/conf/httpd.conf. Add the command to load the WebDAV/Subversion module at the end of the LoadModule commands (around line 262) as follows:


LoadModule dav_svn_module modules/mod_dav_svn.so

Set the Apache-Unix process account to be www by replacing the existing line that sets the default account as "User nobody" with the following:


# User nobody
User www

To avoid conflict with the standard OS X Apache configuration, set a different port to listen for http requests. Replace the existing line configuring "Listen <port>" with the following (for the rest of this article we'll assume use of port 8800):


# Listen 80
Listen 8008

Add the following text to the end of the configuration file to let Apache2 know the path to the repository and the HTTP/Apache user accounts file. Replace the text "<path to repository>" with the path you used above.


<Location /svn>
  DAV svn
  SVNPath <path to repository>
  AuthType Basic
  AuthName "Subversion Repository"
  AuthUserFile /usr/local/apache/etc/svn-auth-file
  Require valid-user
</Location>

Now, configure HTTP/Apache accounts. I put the authentication file in /usr/local/apache/etc/svn-auth-file. To CREATE this file enter the following command (you will be prompted for a password):


htpasswd -c /usr/local/apache/etc/svn-auth-file <username>

Note, to add users to an existing file, skip the -c option:


htpasswd /usr/local/apache/etc/svn-auth-file <username>

Now start up Apache2 by issuing the command:

	
/usr/local/apache/bin/apachectl start

You're now done with the setup and installation! To verify that the server installation was successful enter the URL specified for the location of the repository (as configured in the httpd.conf file) into Safari. You should be prompted for a username/password combination and upon successful authentication see a revision number and the contents of the top directory of your repository (it should be empty).

Using Subversion

These suggestions on using Subversion are taken from the book Version Control with Subversion. This is a simplified view of using Subversion, and I've included page/section references where the Subversion book addresses an issue more completely.

1. Choosing a repository layout scheme.
Before adding projects to the repository, it's worth choosing how you'd like to organize the repository layout. On the other hand, thanks to the ease of moving and renaming directories in Subversion, it's easy to rearrange things later. I'll recommend one simple layout taken directly from the Subversion book (see page 81: Choosing a Repository Layout).

This layout is based around tracking three aspects of each project:

  1. Trunk -- the 'main line' where active development is managed.
  2. Branches -- where a copy of the project can be managed without affecting the main line - useful for testing out big changes that may or may not be later integrated into the main line (see page 39: Branching and Merging).
  3. Releases (or tags) -- where snapshots (usually corresponding to an official release of the project) of the source tree are kept so that it can be restored, examined and rebuilt if needed (see page 51: Tags).

The following example demonstrates how this layout would work for two projects, ProjectA and ProjectB.

	
  ProjectA/
     trunk/
        ... project files ...
     branches/
        CustomClientBuild
           ... project files ...
     releases/
	v0.9b/
           ... project files ...
        v1.0/
           ... project files ...
  ProjectB/
     trunk/
        ... project files ...
     branches/
        ... project files ...
     releases/
        ... project files ...

2. Importing a project into the repository.
So this is the big event -- actually taking one of your projects and adding it to the repository. Using the repository layout described above, here's how you would add ProjectWidget to the repository. (Note, the svn import command and all arguments must be entered on the same line, the \ is used to indicate line continuation.)


% svn import -m "my import message" <path_to_project> \
http://<svn_server>:<apache2_port>/svn/<project_name>/trunk

For example:

	
% svn import -m "Importing project widget" \
~/MyWorkArea/ProjectWidget \
http://localhost:8008/svn/ProjectWidget/trunk

By default, your Unix login/user name is used to choose the HTTP/Apache2 account associated with a change to repository. To specify another account use the --username <user> option.

Note that importing ~/MyWorkArea/ProjectWidget simply adds the project to the repository, the directory that the files were imported from is unaffected. To put the local directory under the control of Subversion you need to check it out first (see 3. Checking out a project).

If you are importing a project from CVS, you can preserve the full revision history of your project with cvs2svn.

3. Checking out a project.
To get access to a project that is in a Subversion repository, you need to check it out from the repository. (If you're checking out a project you just imported, move the original directory out of the way: mv ProjectWidget ProjectWidget_preSVN). Then check out the source from Subversion:

	
svn checkout http://localhost:8008/svn/ProjectWidget/trunk ProjectWidget

This will create a new ProjectWidget directory in the current working directory you issued the command from.

4. Managing your project with subversion.
For the most part Subversion just lets you work the way you normally would, but in some cases you need to directly inform Subversion of the change (adding, deleting, renaming), or when reconciling conflicting changes between your local copy and an updated version in the repository.

4.1 Checking the status.
From within the ProjectWidget directory, you can perform Subversion commands like svn status to see if any of the files in the project have been changed locally, or svn update to update files in your work area with anything newly added or modified in the repository. To check if the status of files has changed both locally and/or in the repository, use svn status u. Files that are unchanged will not be mentioned at all - this list (extracted from the svn help status output) provides the basic codes for describing the status of a file:

	
'A' Added
'C' Conflicted
'D' Deleted
'G' Merged
'I' Ignored
'M' Modified
'R' Replaced
'X' item is unversioned, but is used by an externals definition
'?' item is not under version control
'!' item is missing (removed by non-svn command) or incomplete
'~' versioned item obstructed by some item of a different kind

For example (after editing README.txt in ProjectWidget's top level directory):

	
% svn status

  M      README.txt

4.2 Adding, deleting, and renaming files/directories.
When you add a new file or directory to your work area, use the command svn add <file_or_dir> to let Subversion know that you've added it. When you delete a file or directory from your work area, use the command svn delete <file_or_dir> so that the repository is updated with the change. When you want to rename a file or directory, use the command svn rename <oldname> <newname>.

4.3 Committing changes.
When you are ready to commit the changes you've made to your local work area and share them with the rest of your team, you need to commit those changes to the repository. Take a look at the status of your work area to verify what changes will be committed to the repository:


svn status

Before you commit your changes, you'll need to make sure your work area is up-to-date with the latest version of the repository (using svn update). And once everything looks ready to go, commit your project work area via the following command:


svn commit -m "Look at all the work I did" 

You can optionally select files individually or in groups by specifying them in the command as follows:


svn commit -m "Look at some of the work I did" ./README.txt 

4.4 Conflict resolution.
If you've made changes to a file, and your changes conflict with the changes it has in the repository, you won't be able to check in your changes until you resolve them (see page 28, Resolve Conflicts). When you attempt to update, Subversion will create three temporary copies of the file experiencing conflict:


filename.mine         (your version  pre-update)
filename.r<OLDREV>    (the version before you made your changes)
filename.r<NEWREV>    (the newest revision from the repository)

It is now up to you to manually edit the filename file using the other three temporary files as reference to merge the changes from your version and the new repository version. Once this is finished let Subversion know the conflict is resolved by issuing the command:


svn resolved filename

This will delete the .mine, .r<OLDREV> and .r<NEWREV> copies of the file and you will be able to proceed with checking in your changes.

Conclusion

Congratulations! You've set up an industrial-strength revision control system, one that is secure, fast, flexible, and free.

Subversion and Apache provide a myriad of options and configurations that can be tailored to suit just about any type of organization's or individual's needs. The setup described in this article is designed to get you up and running with a solid, secure configuration with as little administrative overhead as possible. I hope that once you become comfortable with this basic configuration you will explore the many ways of enhancing your use of Subversion.

Related Reading

Version Control with Subversion
By Ben Collins-Sussman, Brian W. Fitzpatrick, C. Michael Pilato

Resources and Tips

Some useful resources and links:

Things to Do

Things to Watch Out For

Some applications that store documents as directory bundles may delete the .svn folder that Subversion uses from inside the bundle directory. EOModeler will delete the .svn directory when you save your document. This is annoying but not difficult to work around -- when you are ready to check in your changes, if Subversion displays the status code '~' (meaning: versioned item obstructed by some item of a different kind) perform the following steps (based on a model named MyModel):


% mv MyModel.eomodeld MyModel.mine 
% svn update MyModel.eomodeld
% mv MyModel.eomodeld/.svn MyModel.mine/
% rm -r MyModel.eomodeld
% mv MyModel.mine MyModel.eomodeld

An important note for former CVS users: Use svn status where you would have used cvs update to check the status of your work area. Use svn -u status to include working revision and server out-of-date information from the repository.

When Things Go Wrong

Adam Swift is a longtime software engineer, developing WebObjects applications since its first release, and Cocoa software since it was called the AppKit on his NeXT slab, circa 1991.


Return to MacDevCenter.com.

Copyright © 2009 O'Reilly Media, Inc.