- •Table of Contents
- •Foreword
- •Preface
- •Audience
- •How to Read this Book
- •Conventions Used in This Book
- •Typographic Conventions
- •Icons
- •Organization of This Book
- •New in Subversion 1.1
- •This Book is Free
- •Acknowledgments
- •From Ben Collins-Sussman
- •From Brian W. Fitzpatrick
- •From C. Michael Pilato
- •Chapter 1. Introduction
- •What is Subversion?
- •Subversion's History
- •Subversion's Features
- •Subversion's Architecture
- •Installing Subversion
- •Subversion's Components
- •A Quick Start
- •Chapter 2. Basic Concepts
- •The Repository
- •Versioning Models
- •The Problem of File-Sharing
- •The Lock-Modify-Unlock Solution
- •The Copy-Modify-Merge Solution
- •Subversion in Action
- •Working Copies
- •Revisions
- •How Working Copies Track the Repository
- •The Limitations of Mixed Revisions
- •Summary
- •Chapter 3. Guided Tour
- •Help!
- •Import
- •Revisions: Numbers, Keywords, and Dates, Oh My!
- •Revision Numbers
- •Revision Keywords
- •Revision Dates
- •Initial Checkout
- •Basic Work Cycle
- •Update Your Working Copy
- •Make Changes to Your Working Copy
- •Examine Your Changes
- •svn status
- •svn diff
- •svn revert
- •Resolve Conflicts (Merging Others' Changes)
- •Merging Conflicts by Hand
- •Copying a File Onto Your Working File
- •Punting: Using svn revert
- •Commit Your Changes
- •Examining History
- •svn diff
- •Examining Local Changes
- •Comparing Working Copy to Repository
- •Comparing Repository to Repository
- •svn list
- •A Final Word on History
- •Other Useful Commands
- •svn cleanup
- •svn import
- •Summary
- •Chapter 4. Branching and Merging
- •What's a Branch?
- •Using Branches
- •Creating a Branch
- •Working with Your Branch
- •The Key Concepts Behind Branches
- •Copying Changes Between Branches
- •Copying Specific Changes
- •The Key Concept Behind Merging
- •Best Practices for Merging
- •Tracking Merges Manually
- •Previewing Merges
- •Merge Conflicts
- •Noticing or Ignoring Ancestry
- •Common Use-Cases
- •Merging a Whole Branch to Another
- •Undoing Changes
- •Resurrecting Deleted Items
- •Common Branching Patterns
- •Release Branches
- •Feature Branches
- •Switching a Working Copy
- •Tags
- •Creating a Simple Tag
- •Creating a Complex Tag
- •Branch Maintenance
- •Repository Layout
- •Data Lifetimes
- •Summary
- •Chapter 5. Repository Administration
- •Repository Basics
- •Understanding Transactions and Revisions
- •Unversioned Properties
- •Repository Data-Stores
- •Berkeley DB
- •FSFS
- •Repository Creation and Configuration
- •Hook Scripts
- •Berkeley DB Configuration
- •Repository Maintenance
- •An Administrator's Toolkit
- •svnlook
- •svnadmin
- •svndumpfilter
- •svnshell.py
- •Berkeley DB Utilities
- •Repository Cleanup
- •Managing Disk Space
- •Repository Recovery
- •Migrating a Repository
- •Repository Backup
- •Adding Projects
- •Choosing a Repository Layout
- •Creating the Layout, and Importing Initial Data
- •Summary
- •Chapter 6. Server Configuration
- •Overview
- •Network Model
- •Requests and Responses
- •Client Credentials Caching
- •svnserve, a custom server
- •Invoking the Server
- •Built-in authentication and authorization
- •Create a 'users' file and realm
- •Set access controls
- •SSH authentication and authorization
- •SSH configuration tricks
- •Initial setup
- •Controlling the invoked command
- •httpd, the Apache HTTP server
- •Prerequisites
- •Basic Apache Configuration
- •Authentication Options
- •Basic HTTP Authentication
- •SSL Certificate Management
- •Authorization Options
- •Blanket Access Control
- •Per-Directory Access Control
- •Disabling Path-based Checks
- •Extra Goodies
- •Repository Browsing
- •Other Features
- •Supporting Multiple Repository Access Methods
- •Chapter 7. Advanced Topics
- •Runtime Configuration Area
- •Configuration Area Layout
- •Configuration and the Windows Registry
- •Configuration Options
- •Servers
- •Config
- •Properties
- •Why Properties?
- •Manipulating Properties
- •Special Properties
- •svn:executable
- •svn:mime-type
- •svn:ignore
- •svn:keywords
- •svn:eol-style
- •svn:externals
- •svn:special
- •Automatic Property Setting
- •Peg and Operative Revisions
- •Externals Definitions
- •Vendor branches
- •General Vendor Branch Management Procedure
- •svn_load_dirs.pl
- •Localization
- •Understanding locales
- •Subversion's use of locales
- •Subversion Repository URLs
- •Chapter 8. Developer Information
- •Layered Library Design
- •Repository Layer
- •Repository Access Layer
- •RA-DAV (Repository Access Using HTTP/DAV)
- •RA-SVN (Custom Protocol Repository Access)
- •RA-Local (Direct Repository Access)
- •Your RA Library Here
- •Client Layer
- •Using the APIs
- •The Apache Portable Runtime Library
- •URL and Path Requirements
- •Using Languages Other than C and C++
- •Inside the Working Copy Administration Area
- •The Entries File
- •Pristine Copies and Property Files
- •WebDAV
- •Programming with Memory Pools
- •Contributing to Subversion
- •Join the Community
- •Get the Source Code
- •Become Familiar with Community Policies
- •Make and Test Your Changes
- •Donate Your Changes
- •Chapter 9. Subversion Complete Reference
- •The Subversion Command Line Client: svn
- •svn Switches
- •svn Subcommands
- •svn blame
- •svn checkout
- •svn cleanup
- •svn commit
- •svn copy
- •svn delete
- •svn diff
- •svn export
- •svn help
- •svn list
- •svn merge
- •svn mkdir
- •svn move
- •svn propedit
- •svn proplist
- •svn resolved
- •svn revert
- •svn status
- •svn switch
- •svn update
- •svnadmin
- •svnadmin Switches
- •svnadmin Subcommands
- •svnadmin create
- •svnadmin deltify
- •svnadmin dump
- •svnadmin help
- •svnadmin list-dblogs
- •svnadmin list-unused-dblogs
- •svnadmin load
- •svnadmin lstxns
- •svnadmin recover
- •svnadmin rmtxns
- •svnadmin setlog
- •svnadmin verify
- •svnlook
- •svnlook Switches
- •svnlook
- •svnlook author
- •svnlook changed
- •svnlook date
- •svnlook help
- •svnlook history
- •svnlook tree
- •svnlook uuid
- •svnserve
- •svnserve Switches
- •svnversion
- •svnversion
- •mod_dav_svn Configuration Directives
- •Appendix A. Subversion for CVS Users
- •Revision Numbers Are Different Now
- •Directory Versions
- •More Disconnected Operations
- •Distinction Between Status and Update
- •Branches and Tags
- •Metadata Properties
- •Conflict Resolution
- •Binary Files and Translation
- •Versioned Modules
- •Authentication
- •Converting a Repository from CVS to Subversion
- •Appendix B. Troubleshooting
- •Common Problems
- •Problems Using Subversion
- •Every time I try to access my repository, my Subversion client just hangs.
- •Every time I try to run svn, it says my working copy is locked.
- •I'm getting errors finding or opening a repository, but I know my repository URL is correct.
- •How can I specify a Windows drive letter in a file:// URL?
- •I'm having trouble doing write operations to a Subversion repository over a network.
- •Under Windows XP, the Subversion server sometimes seems to send out corrupted data.
- •What is the best method of doing a network trace of the conversation between a Subversion client and Apache server?
- •Why does the svn revert command require an explicit target? Why is it not recursive by default? This behavior differs from almost all the other subcommands.
- •On FreeBSD, certain operations (especially svnadmin create) sometimes hang.
- •I can see my repository in a web browser, but svn checkout gives me an error about 301 Moved Permanently.
- •Appendix C. WebDAV and Autoversioning
- •Basic WebDAV Concepts
- •Just Plain WebDAV
- •DeltaV Extensions
- •Subversion and DeltaV
- •Mapping Subversion to DeltaV
- •Autoversioning Support
- •The mod_dav_lock Alternative
- •Autoversioning Interoperability
- •Win32 WebFolders
- •Unix: Nautilus 2
- •Linux davfs2
- •Appendix D. Third Party Tools
- •Clients and Plugins
- •Language Bindings
- •Repository Converters
- •Higher Level Tools
- •Repository Browsing Tools
- •Appendix E. Copyright
Repository Administration
min hotcopy command—will perform the necessary steps for backing up your live repository—without requiring that you bar public repository access at all—and then will clean out the dead Berkeley log files from your live repository.
Even if you also have an incremental backup, you might want to run this program on a regular basis. For example, you might consider adding hot-backup.py to a program scheduler (such as cron on Unix systems). Or, if you prefer fine-grained backup solutions, you could have your post-commit hook script call hot-backup.py (see the section called “Hook Scripts”), which will then cause a new backup of your repository to occur with every new revision created. Simply add the following to the hooks/post-commit script in your live repository directory:
(cd /path/to/hook/scripts; ./hot-backup.py ${REPOS} /path/to/backups &)
The resulting backup is a fully functional Subversion repository, able to be dropped in as a replacement for your live repository should something go horribly wrong.
There are benefits to both types of backup methods. The easiest is by far the full backup, which will always result in a perfect working replica of your repository. This again means that should something bad happen to your live repository, you can restore from the backup with a simple recursive directory copy. Unfortunately, if you are maintaining multiple backups of your repository, these full copies will each eat up just as much disk space as your live repository.
Incremental backups using the repository dump format are excellent to have on hand if the database schema changes between successive versions of Subversion itself. Since a complete repository dump and load are generally required to upgrade your repository to the new schema, it's very convenient to already have half of that process (the dump part) finished. Unfortunately, the creation of—and restoration from—incremental backups takes longer, as each commit is effectively replayed into either the dump file or the repository.
In either backup scenario, repository administrators need to be aware of how modifications to unversioned revision properties affect their backups. Since these changes do not themselves generate new revisions, they will not trigger post-commit hooks, and may not even trigger the pre-revprop-change and post-revprop-change hooks. 17 And since you can change revision properties without respect to chronological order—you can change any revision's properties at any time—an incremental backup of the latest few revisions might not catch a property modification to a revision that was included as part of a previous backup.
Generally speaking, only the truly paranoid would need to backup their entire repository, say, every time a commit occurred. However, assuming that a given repository has some other redundancy mechanism in place with relatively fine granularity (like per-commit emails), a hot backup of the database might be something that a repository administrator would want to include as part of a system-wide nightly backup. For most repositories, archived commit emails alone provide sufficient redundancy as restoration sources, at least for the most recent few commits. But it's your data—protect it as much as you'd like.
Often, the best approach to repository backups is a diversified one. You can leverage combinations of full and incremental backups, plus archives of commit emails. The Subversion developers, for example, back up the Subversion source code repository after every new revision is created, and keep an archive of all the commit and property change notification emails. Your solution might be similar, but should be catered to your needs and that delicate balance of convenience with paranoia. And while all of this might not save your hardware from the iron fist of Fate, 18 it should certainly help you recover from those trying times.
Adding Projects
Once your repository is created and configured, all that remains is to begin using it. If you have a collection of existing data that is ready to be placed under version control, you will more than likely want to use the svn client program's import subcommand to accomplish that. Before doing this, though, you should carefully consider your
17svnadmin setlog can be called in a way that bypasses the hook interface altogether. 18You know—the collective term for all of her “fickle fingers”.
89
Repository Administration
long-term plans for the repository. In this section, we will offer some advice on how to plan the layout of your repository, and how to get your data arranged in that layout.
Choosing a Repository Layout
While Subversion allows you to move around versioned files and directories without any loss of information, doing so can still disrupt the workflow of those who access the repository often and come to expect things to be at certain locations. Try to peer into the future a bit; plan ahead before placing your data under version control. By “laying out” the contents of your repositories in an effective manner the first time, you can prevent a load of future headaches.
There are a few things to consider when setting up Subversion repositories. Let's assume that as repository administrator, you will be responsible for supporting the version control system for several projects. The first decision is whether to use a single repository for multiple projects, or to give each project its own repository, or some compromise of these two.
There are benefits to using a single repository for multiple projects, most obviously the lack of duplicated maintenance. A single repository means that there is one set of hook scripts, one thing to routinely backup, one thing to dump and load if Subversion releases an incompatible new version, and so on. Also, you can move data between projects easily, and without losing any historical versioning information.
The downside of using a single repository is that different projects may have different commit mailing lists or different authentication and authorization requirements. Also, remember that Subversion uses repository-global revision numbers. Some folks don't like the fact that even though no changes have been made to their project lately, the youngest revision number for the repository keeps climbing because other projects are actively adding new revisions.
A middle-ground approach can be taken, too. For example, projects can be grouped by how well they relate to each other. You might have a few repositories with a handful of projects in each repository. That way, projects that are likely to want to share data can do so easily, and as new revisions are added to the repository, at least the developers know that those new revisions are at least remotely related to everyone who uses that repository.
After deciding how to organize your projects with respect to repositories, you'll probably want to think about directory hierarchies in the repositories themselves. Because Subversion uses regular directory copies for branching and tagging (see Chapter 4, Branching and Merging), the Subversion community recommends that you choose a repository location for each project root—the “top-most” directory which contains data related to that project—and then create three subdirectories beneath that root: trunk, meaning the directory under which the main project development occurs; branches, which is a directory in which to create various named branches of the main development line; tags, which is a directory of branches that are created, and perhaps destroyed, but never changed.
For example, your repository might look like:
/
calc/
trunk/
tags/
branches/
calendar/
trunk/
tags/
branches/
spreadsheet/
trunk/
tags/
branches/
…
Note that it doesn't matter where in your repository each project root is. If you have only one project per repository,
90
Repository Administration
the logical place to put each project root is at the root of that project's respective repository. If you have multiple projects, you might want to arrange them in groups inside the repository, perhaps putting projects with similar goals or shared code in the same subdirectory, or maybe just grouping them alphabetically. Such an arrangement might look like:
/
utils/
calc/
trunk/
tags/
branches/
calendar/
trunk/
tags/
branches/
…
office/
spreadsheet/
trunk/
tags/
branches/
…
Lay out your repository in whatever way you see fit. Subversion does not expect or enforce a layout schema—in its eyes, a directory is a directory is a directory. Ultimately, you should choose the repository arrangement that meets the needs of the people who work on the projects that live there.
Creating the Layout, and Importing Initial Data
After deciding how to arrange the projects in your repository, you'll probably want to actually populate the repository with that layout and with initial project data. There are a couple of ways to do this in Subversion. You could use the svn mkdir command (see Chapter 9, Subversion Complete Reference) to create each directory in your skeletal repository layout, one-by-one. A quicker way to accomplish the same task is to use the svn import command (see the section called “svn import”). By first creating the layout in a temporary location on your drive, you can import the whole layout tree into the repository in a single commit:
$ mkdir tmpdir $ cd tmpdir
$ mkdir projectA
$ mkdir projectA/trunk
$ mkdir projectA/branches $ mkdir projectA/tags
$ mkdir projectB
$ mkdir projectB/trunk
$ mkdir projectB/branches $ mkdir projectB/tags
…
$ svn import . file:///path/to/repos --message 'Initial repository layout'
Adding |
projectA |
Adding |
projectA/trunk |
Adding |
projectA/branches |
Adding |
projectA/tags |
Adding |
projectB |
Adding |
projectB/trunk |
Adding |
projectB/branches |
Adding |
projectB/tags |
… |
|
Committed revision 1. $ cd ..
91