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:
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.
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.
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.".
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
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.
In this example note that the
% hdiutil attach <disk_image_file> % installer -pkg <package_file> -target <target_volume>
installercommand 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:
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).
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:
The following example demonstrates how this layout would work for two projects, ProjectA and ProjectB.
2. Importing a project into the repository.
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 ...
svn importcommand 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
% 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:
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.
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.
Some useful resources and links:
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.
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.