This book is an incomplete draft. It is not yet the authoritative reference on svk. Be careful!

For SVK 1.04

(book compiled from Revision 120)

Michael L.H.Brouwer

RussellBrown

This work is licensed under the Creative
Commons Attribution License. To view a copy of this license,
visit http://creativecommons.org/licenses/by/2.0/ or send a
letter to Creative Commons, 559 Nathan Abbott Way, Stanford,
California 94305, USA.

Foreword

After playing with Subversion and SVK for a long time,
without really being able to use either for real work since our
main repository was still using CVS, the author convinced his
management to let him switch their SCM over to SVK directly
instead of moving to Subversion which would have been at best a
step sideways from CVS.

The transistion went smoothly and after the CVS repository
was converted to Subversion using cvs2svn, we mirrored it to a
SVK depot and setup a quick and easy bootstrap proccess for
everyone to use. Almost all of the developers started using SVK
immediately without any problems. A few of them asked the
question:

Q: You expect me to use a piece of software without
documentation for mission critical work?

A: It has documentation, look at the built in help or go
to the svk wiki.

Of course I started to realize that without hanging out in
the #svk irc channel, the help and the wiki were really not
sufficient to help get someone going in using SVK. So I started
writing a guide to using SVK day by day on our internal
wiki.

After a few days of manually updating the wiki and keeping
the table of contents in sync with the actual content, I
started to realize that a wiki isn't the best way to write a
book, which is what this guide was turning into. I also watched
people coming to #svk on a daily basis asking very similar
questions about SVK which should have been answered in a
document somewhere.

After some encouragement from clkao in irc I decided to
start with a copy of the Subversion book's docbook XML sources
and write a book about SVK. The idea was to collect information
from the wiki, FAQs, from #svk and things I was putting on our
internal wiki that really applied to SVK in general into one
place.

In the world of open-source software, the Concurrent
Versions System (CVS) has long been the tool of choice for
version control. And rightly so. CVS itself is free software,
and its non-restrictive modus
operandi and support for networked
operation—which allow dozens of geographically dispersed
programmers to share their work—fits the collaborative
nature of the open-source world very well. CVS and its
semi-chaotic development model have become cornerstones of
open-source culture.

Like many tools that have lasted 25 years, CVS is starting
to show its age.
Subversion is a relatively new version control system designed
to be the successor to CVS. The designers set out to win the
hearts of CVS users in two ways: by creating an open-source
system with a design (and “look and feel”) similar
to CVS, and by attempting to fix most of CVS's noticeable flaws.
While the result isn't necessarily the next great evolution in
version control design, Subversion is very
powerful, very usable, and very flexible.

For some people, a plain successor to CVS wasn't good
enough. One of those people was Chia-liang Kao. He took a year
off his regular work to sit down and write a version control
system that would help raise his own productivity once he got
back to doing paid work. The result of his labor, and more
recently that of an entire community of users and developers is SVK.
While Subversion set out take over CVS's user base, SVK attempts
to provide an answer for many others - including people who had
already defected to another version control system
and users who had never before used version control. SVK is written
in Perl and uses the underlying revision-tracking filesystem
built by the Subversion project.

This book documents SVK version 1.04. We have made every
attempt to be thorough in our coverage. However, SVK has a thriving and
energetic development community — a number of features and
improvements planned for future versions of SVK may change some
of the commands and specific notes in this book.

Audience

This book is written for computer-literate folk who want to
use SVK to manage their data. While SVK runs on a
number of different operating systems, its primary user
interface is command-line based. It is that command-line tool
(svk) which is discussed and used in this
book. For consistency, the examples in this book assume the
reader is using a Unix-like operating system, and is relatively
comfortable with Unix and command-line interfaces.

That said, the svk program also runs on
non-Unix platforms like Microsoft Windows. With a few minor
exceptions, such as the use of backward slashes
(\) instead of forward slashes
(/) for path separators, the input to and
output from this tool when run on Windows are identical to its
Unix counterpart. However, Windows users may find more success
by running the examples inside the Cygwin Unix emulation
environment.

Most readers are probably programmers or sysadmins who need
to track changes to source code. This is the most common use
for SVK, and therefore it is the scenario underlying all
of the book's examples. But SVK can be used to manage
changes to any sort of information: images, music, databases,
documentation, and so on. To SVK, all data is just
data.

While this book is written with the assumption that the
reader has never used version control, we've also tried to make
it easy for users of CVS or Subversion to make a painless leap
into SVK. Special sidebars may discuss CVS or Subversion from
time to time, and a special appendix summarizes most of the
differences between CVS, Subversion and SVK.

How to Read this Book

This book aims to be useful to people of widely different
backgrounds—from people with no previous experience in
version control to experienced sysadmins. Depending on your own
background, certain chapters may be more or less important to
you. The following can be considered a “recommended
reading list” for various types of readers:

Experienced sysadmins

The assumption here is that you've probably used CVS
before, and are dying to get a Subversion server up and
running ASAP. Chapters 5 and 6 will show you how to create
your first repository and make it available over the
network. After that's done, chapter 3 and appendix A are
the fastest routes to learning the SVK client while
drawing on your CVS or Subversion experience.

New users

Your administrator has probably set up Subversion
already, and you need to learn how to use SVK as a client.
If you've never used a version control system (like CVS or
Subversion), then chapters 2 and 3 are a vital
introduction. If you're already an old hand at CVS or
Subversion, chapter 3 and appendix A are the best place to
start.

Advanced users

Whether you're a user or administrator, eventually
your project will grow larger. You're going to want to
learn how to do more advanced things with SVK, such
as how to use branches and perform merges (chapter 4),
how to use SVK's property support, how to configure
runtime options (chapter 7), and other things. Chapters 4
and 7 aren't vital at first, but be sure to read them once
you're comfortable with the basics.

Developers

Presumably, you're already familiar with SVK,
and now want to either extend it or add new tests or fixes
to it. Chapter 8 is just for you.

The book ends with reference material—chapter 9 is a
reference guide for all SVK commands, and the appendices
cover a number of useful topics. These are the chapters you're
mostly likely to come back to after you've finished the
book.

Conventions Used in This Book

This section covers the various conventions used in this
book.

Typographic Conventions

Constant width

Used for commands, command output, and
switches

Constant width
italic

Used for replaceable items in code and text

Italic

Used for file and directory names

Icons

Note

This icon designates a note relating to the surrounding
text.

Tip

This icon designates a helpful tip relating to the
surrounding text.

Warning

This icon designates a warning relating to the
surrounding text.

Note that the source code examples are just
that—examples. While they will compile with the proper
compiler incantations, they are intended to illustrate the
problem at hand, not necessarily serve as examples of good
programming style.

Organization of This Book

Covers the history of SVK as well as its
features, architecture, components, and install
methods. Also includes a quick-start guide.

Chapter 2, Basic Concepts

Explains the basics of version control and different
versioning models, along with SVK's depot, working
copies and revisions.

Chapter 3, Guided Tour

Walks you through a day in the life of a SVK user.
It demonstrates how to use SVK to obtain, modify, and
commit data.

Chapter 4, Branching and Merging

Discusses branches, merges, and tagging, including
best practices for branching and merging, common use
cases, how to undo changes, and how to easily swing from
one branch to the next.

Chapter 5, Depot Administration

Describes the basics of the SVK depot, how to
create, configure and maintain a depot, how to setup a
shared repository and the tool you can use to do all
this.

Chapter 6, Server Configuration

Explains how to configure a Subversion server for
use with SVK, and the three ways to access your
repository: HTTP, the
svn protocol, and local access. It
also covers the details of authentication, authorization
and anonymous access.

Chapter 7, Advanced Topics

Explores the SVK client environment variables, file
and directory properties, how to
ignore files in your working copy,
and lastly how to handle vendor branches.

Chapter 8, Developer Information

Describes the internals of SVK, the $SVKROOT
administrative areas from a programmer's point of view.
Shows how to write new tests for SVK and most
importantly, how to contribute to the development of
SVK.

Chapter 9, SVK Complete
Reference

Explains in great detail every subcommand of
svk with plenty of examples for
the whole family!

Appendix A, SVK for Subversion
Users

Covers the similarities and differences between
SVK and Subversion.

Appendix B, Troubleshooting

Addresses common problems and difficulties using and
building SVK.

Appendix C, Third Party Tools

Discusses tools that support or use Subversion,
including alternative client programs, repository
browser tools, and so on.

This Book is Free

This book started out as a branch of the Version Control
With Subversion book. Over time is was morphed into an SVK
specific book by the authors. As such, it has always been under
a free license. (See Appendix D, Copyright.) In
fact, the book was written in the public eye, as a part of SVK.
This means two things:

You will always find the latest version of this book in
the book's own Subversion repository at svn://svn.clkao.org/svkbook/trunk.

You can distribute and make changes to this book however
you wish—it's under a free license. Of course,
rather than distribute your own private version of this
book, we'd much rather you send feedback and patches to the
SVK developer community. See the section called “” to learn about joining
this community.

A relatively recent online version of this book can be found
at http://svkbook.elixus.org.

Acknowledgments

This book would not be possible (nor very useful) if SVK did
not exist. For that, the authors would like to thank Chia-liang
Kao for having the vision of writing an Open Source version
control system with the power, speed and interoperability that
SVK has.

In addition this book wouldn't have existed, or at least
would have taken much longer to write if it wasn't for the
Subversion book written by Ben Collins-Sussman, Brian W.
Fitzpatrick and C. Michael Pilato

The original book on which this book is based is titled
Version Control With Subversion and is Copyright 2002, 2003,
2004, 2005 by Ben Collins-Sussman, Brian W. Fitzpatrick and C.
Michael Pilato

We would also like to thank the countless people who
contributed to the SVK book with reviews, suggestions and fixes:
While this is undoubtedly not a complete list, this book would
be incomplete and incorrect without the help of: Gary Hoo, Jesse
Vincent, Michael Hendricks, Chris Russo and the entire SVK
community.

Chapter 1. Introduction

Version control is the art of managing changes to
information. It has long been a critical tool for programmers,
who typically spend their time making small changes to software
and then undoing those changes the next day. But the usefulness
of version control software extends far beyond the bounds of the
software development world. Anywhere you can find people using
computers to manage information that changes often, there is
room for version control. And that's where SVK comes
into play.

This chapter contains a high-level introduction to
SVK—what it is; what it does; how to get it.

What is SVK?

SVK is a free/open-source version control system.
That is, SVK manages files and directories over time. A
tree of files is placed into a depot on
the user's machine. The depot remembers every change ever made
to your files and directories, and also to other files and
directories that you mirror from other
places. This allows you to recover older versions of your data,
or examine the history of how your data changed. In this
regard, many people think of a version control system as a sort
of “time machine”.

Also central to many uses of Version Control is the concept
of a repository. A repository is like a
filesystem that can either be hosted on a remote server or
locally on the same machine as the user's depot. While SVK
doesn't currently provide a repository server, it has been
designed to be able to work with repositories created by other
Version Control systems; in particular Subversion repositories.

SVK can access repositories across networks, which allows
them to be used by people on different computers. This is
convenient to those who like a centralized repository model, and
SVK supports this fully. Others prefer to use other more
detached or
distributed models, and again SVK is at
home in these environments too. Whichever model is used, because
the work is versioned, can always track back through the changes
that have been made, and undo them if required.

Some version control systems are also software configuration
management (SCM) systems. These systems are specifically
tailored to manage trees of source code, and have many features
that are specific to software development—such as natively
understanding programming languages, or supplying tools for
building software. SVK, however, is not one of these
systems. It is a general system that can be used to manage
any collection of files. For you, those
files might be source code—for others, anything from
grocery shopping lists to digital video mix-downs and
beyond.

SVK's History

The idea of source control management has been around for many
years. Early on the centralized repository scheme became the
standard for many developer teams. In more recent times,
distributed source control has become part of the normal work
flow process. CVS is a widely known and used standard for Source
Control Management. Because of some shortcomings a team of
developers decided to create an improved version of CVS called
Subversion (svn). While Subversion, is
still a centralized repository system, because it was a new
design, it was
developed to be more flexible than its predecessor. Because of
this fact, developers are able to take key components and
connect them together in ways that the original designers never
dreamt of. SVK is one of those dreams.

This particular dream came from Chia-liang Kao, who took a
year out from work to develop SVK.###TODO: Expand this some
more.

SVK's Features

While Subversion aimed to take the basic Source Control
model already provided by CVS and improve on its design and
implementation, SVK aims to open up other Source Control
techniques and features offered by other Source Control Systems
and models.

Because some of these features are very different to those
offered by fully-centralized systems such as CVS and Subversion,
there may be a number of techniques or terms that are unfamiliar
to you. These will be explained later.

Below is a list of some of the key features provided by SVK

SVK provides:

Disconnected Operation

If a repository is being used,
all read-only operations are
available without a connection to the repository.

Decentralized Operation

It is possible to use SVK without any connection to a
repository whatsoever.

Merge Tracking

Merges between branches are tracked automatically, and
therefore do not need manual lists of revision numbers to
be specified.

High Performance and Scalability

SVK performs very well when compared with other
version control systems.###TODO Need more here.

Support for multiple repository systems

SVK can mirror repositories created by a number of
Source Control Systems other than Subversion. ###TODO:
List some here

Consistent data handling

Subversion expresses file differences using a binary
differencing algorithm, which works identically on both
text (human-readable) and binary (human-unreadable) files.
Both types of files are stored equally compressed in the
repository, and differences are transmitted in both
directions across the network.

SVK's Architecture

Because of the extremely flexible nature of SVK, it's very
difficult to pin down one definitive way of describing its
architecture; either in words or graphically. The way in which
it all works depends largely on the source control model that
you're currently using, and that gets even more complicated when
you consider that you could be using more than one model with
multiple projects in the same svk installation.

On one end is a Subversion repository that holds all of your
versioned data. On the other end is your Subversion client
program, which manages local reflections of portions of that
versioned data (called “working copies”). Between
these extremes are multiple routes through various Repository
Access (RA) layers. Some of these routes go across computer
networks and through network servers which then access the
repository. Others bypass the network altogether and access the
repository directly.

Installing SVK

SVK is a set of Perl 5 modules written on top of
Subversion's Perl bindings. In order to run SVK you will need to
install Subversion with Perl bindings. Subversion itself is
built on a portability layer called APR (Apache Portable Runtime
library). This means SVK should work on any operating system
that supports Perl 5 and the Apache httpd server runs on:
Windows, Linux, all flavors of BSD, Mac OS X, Netware, and
others.

The easiest way to get SVK is to download a binary
package built for your operating system. SVK's website
(http://svk.elixus.org) often has
these packages available for download, posted by volunteers.
The site usually contains graphical installer packages for users
of Apple and Microsoft operating systems. If you run a Unix-like
operating system, you can use your system's native package
distribution system (RPMs, DEBs, the ports tree, etc.) to get
SVK.

Alternately, you can build SVK directly from source
code. Below are instructions from the SVK wiki at http://svk.elixus.org/index.php?BuildingSvkInYourHomeDirectory,
on how to build SVK in your home directory without root
access:

SVK's Components

SVK, once installed, has a number of different
pieces. The following is a quick overview of what you get.
Don't be alarmed if the brief descriptions leave you scratching
your head—there are plenty more pages
in this book devoted to alleviating that confusion.

svk

The command-line client program.

svnadmin

A tool for creating, tweaking or repairing a Subversion
repository—this is technically part of subversion,
however svk need it to be installed in order to create
depots..

Assuming you have SVK installed correctly, you should
be ready to start. The next two chapters will walk you through
the use of svk, SVK's command-line client
program.

A Quick Start

Some people have trouble absorbing a new technology by
reading the sort of “top down” approach provided by this
book. This section is a very short introduction to SVK, and is
designed to give “bottom up” learners a fighting chance.
If you're one of those folks who prefers to learn by
experimentation, the following demonstration will get you up and
running. Along the way, we give links to the relevant chapters
of this book.

If you're new to the entire concept of version control or to
the “copy-modify-merge” model used by both CVS,
Subversion and SVK, then you should read
Chapter 2, Basic Concepts before going any further.

Note

The following example assumes that you have
svk, the SVK command-line client,
and svnadmin, the administrative tool which
is part of Subversion, ready to go. It also assumes you are
using Subversion 1.2 or later (run svnadmin
--version to check.) and SVK-1.00 or later (run
svk --version to check.

SVK stores all versioned data in a depot. To begin, create
the default depot (make sure to answer
y<return> to the question svk asks
you):

This command creates a new directory
~/.svk[1] which contains SVK's administrative
files, and a Subversion repository called local.

An SVK depot is actually a Subversion repository
under the hood. This Subversion repository is a collection of
database files. You won't see your versioned files if you peek
inside. For more information about depot creation and
maintenance, see Chapter 10, Depot Management.

SVK has no concept of a “project”. The
depot is just a virtual versioned filesystem, a large tree
that can hold anything you wish. Some people prefer to
store only one project in a depot, and others prefer to
store multiple projects in a depot by placing them into
separate directories. The merits of each approach are discussed
in the section called “”.
Either way, the depot only manages files and directories,
so it's up to humans to interpret particular directories
as “projects”.

In this example, we assume that you already have some sort
of project (a collection of files and directories) that you wish
to import into your newly created SVK depot. Begin
by organizing them into a single directory
called myproject (or whatever you wish).
For reasons that will be clear later on (see
Chapter 4, Branching and Merging), your project's tree
structure should contain three top-level directories
named branches,
tags, and
trunk. The trunk
directory should contain all of your data,
while branches
and tags directories are empty:

Now the depot contains this tree of data. As mentioned
earlier, you won't see your files by directly peeking into the
depot; they're all stored within a database. But the
depot's imaginary filesystem now contains a top-level
directory named myproject, which in turn
contains your data.

Note that the original /tmp/myproject
directory is unchanged; SVK is unaware of it. (In fact,
you can even delete that directory if you wish.) In order to
start manipulating repository data, you need to create a new
“working copy” of the data, a sort of private
workspace. Ask SVK to “check out” a working
copy of the myproject/trunk directory in
the depot:

At this point, you have the option of making your depot
available to others over a network. See Chapter 6, Server Configuration to learn about the different sorts of
server processes available and how to configure them.

[1] It's possible to
change the location of ~/.svk by setting the
$SVKROOT environment
variable.

This chapter is a short, casual introduction to SVK.
If you're new to version control, this chapter is definitely for
you. We begin with a discussion of general version control
concepts, work our way into the specific ideas behind
SVK, and show some simple examples of SVK in
use.

Even though the examples in this chapter show people sharing
collections of program source code, keep in mind that SVK
can manage any sort of file collection—it's not limited to
helping computer programmers.

The Depot

SVK is a system for tracking history.
At its core is a depot[2], which is a central store of data.
The depot stores information in the form of a
filesystem tree—a typical hierarchy
of files and directories.

So why is this interesting? So far, this sounds like the
definition of a typical file system. And indeed, the depot
is a kind of file system but it's not your
usual breed. What makes the SVK depot special is
that it remembers every change ever written
to it: every change to every file, and even changes to the
directory tree itself, such as the addition, deletion, and
rearrangement of files and directories.

When SVK reads data from the depot, it normally
sees only the latest version of the filesystem tree. But it
also has the ability to view
previous states of the filesystem. For
example, you can ask SVK historical questions like, “What
did this directory contain last Wednesday?” or “Who
was the last person to change this file, and what changes did
they make?” These are the sorts of questions that are at
the heart of any version control system:
systems that are designed to record and track changes to data
over time.

Versioning Models

The core mission of a version control system is to enable
collaborative editing and sharing of data. But different
systems use different strategies to achieve this.

The Problem of File-Sharing

All version control systems have to solve the same
fundamental problem: how will the system allow users to share
information, but prevent them from accidentally stepping on
each other's feet? It's all too easy for users to
accidentally overwrite each other's changes in the
depot.

Consider the scenario shown in Figure 2.1, “The problem to avoid”. Suppose we have two co-workers,
Harry and Sally. They each decide to edit the same repository
file at the same time. If Harry saves his changes to the
repository first, then it's possible that (a few moments
later) Sally could accidentally overwrite them with her own
new version of the file. While Harry's version of the file
won't be lost forever (because the system remembers every
change), any changes Harry made won't be
present in Sally's newer version of the file, because she
never saw Harry's changes to begin with. Harry's work is
still effectively lost—or at least missing from the
latest version of the file—and probably by accident.
This is definitely a situation we want to avoid!

Figure 2.1. The problem to avoid

The Lock-Modify-Unlock Solution

Many version control systems use a
lock-modify-unlock model to address
this problem. In such a system, the repository allows only
one person to change a file at a time. First Harry must
“lock” the file before he can begin making
changes to it. Locking a file is a lot like borrowing a book
from the library; if Harry has locked a file, then Sally
cannot make any changes to it. If she tries to lock the file,
the repository will deny the request. All she can do is read
the file, and wait for Harry to finish his changes and release
his lock. After Harry unlocks the file, his turn is over, and
now Sally can take her turn by locking and editing. Figure 2.2, “The lock-modify-unlock solution” demonstrates this simple
solution.

Figure 2.2. The lock-modify-unlock solution

The problem with the lock-modify-unlock model is that it's
a bit restrictive, and often becomes a roadblock for
users:

Locking may cause administrative
problems.
Sometimes Harry will lock a file and then forget about it.
Meanwhile, because Sally is still waiting to edit the file,
her hands are tied. And then Harry goes on vacation. Now
Sally has to get an administrator to release Harry's lock.
The situation ends up causing a lot of unnecessary delay
and wasted time.

Locking may cause unnecessary
serialization.
What if Harry is editing the beginning of a text file,
and Sally simply wants to edit the end of the same file?
These changes don't overlap at all. They could easily
edit the file simultaneously, and no great harm would
come, assuming the changes were properly merged together.
There's no need for them to take turns in this
situation.

Locking may create a false sense of
security.
Pretend that Harry locks and edits file A, while
Sally simultaneously locks and edits file B. But suppose
that A and B depend on one another, and the changes made
to each are semantically incompatible. Suddenly A and B
don't work together anymore. The locking system was
powerless to prevent the problem—yet it somehow
provided a false sense of security. It's easy for Harry and
Sally to imagine that by locking files, each is beginning a
safe, insulated task, and thus not bother
discussing their incompatible changes early
on.

The Copy-Modify-Merge Solution

SVK, Subversion, CVS, and other version control systems use a
copy-modify-merge model as an
alternative to locking. In this model, each user's client
contacts the project repository and creates a personal
working copy—a local reflection
of the repository's files and directories. Users then work in
parallel, modifying their private copies. Finally, the
private copies are merged together into a new, final version.
The version control system often assists with the merging, but
ultimately a human being is responsible for making it happen
correctly.

Here's an example. Say that Harry and Sally each create
working copies of the same project, copied from the
repository. They work concurrently, and make changes to the
same file A within their copies. Sally saves her changes to
the repository first. When Harry attempts to save his changes
later, the repository informs him that his file A is
out-of-date. In other words, that file
A in the repository has somehow changed since he last copied
it. So Harry asks his client to merge
any new changes from the repository into his working copy of
file A. Chances are that Sally's changes don't overlap with
his own; so once he has both sets of changes integrated, he
saves his working copy back to the repository. Figure 2.3, “The copy-modify-merge solution” and Figure 2.4, “The copy-modify-merge solution (continued)”
show this process.

Figure 2.3. The copy-modify-merge solution

Figure 2.4. The copy-modify-merge solution (continued)

But what if Sally's changes do overlap
with Harry's changes? What then? This situation is called a
conflict, and it's usually not much of
a problem. When Harry asks his client to merge the latest
repository changes into his working copy, his copy of file A
is somehow flagged as being in a state of conflict: he'll be
able to see both sets of conflicting changes, and manually
choose between them. Note that software can't automatically
resolve conflicts; only humans are capable of understanding
and making the necessary intelligent choices. Once Harry has
manually resolved the overlapping changes—perhaps after
a discussion with Sally—he can safely save the
merged file back to the repository.

The copy-modify-merge model may sound a bit chaotic, but
in practice, it runs extremely smoothly. Users can work in
parallel, never waiting for one another. When they work on
the same files, it turns out that most of their concurrent
changes don't overlap at all; conflicts are infrequent. And
the amount of time it takes to resolve conflicts is far less
than the time lost by a locking system.

In the end, it all comes down to one critical factor: user
communication. When users communicate poorly, both syntactic
and semantic conflicts increase. No system can force users to
communicate perfectly, and no system can detect semantic
conflicts. So there's no point in being lulled into a false
promise that a locking system will somehow prevent conflicts;
in practice, locking seems to inhibit productivity more than
anything else.

When Locking is Necessary

While the lock-modify-unlock model is considered
generally harmful to collaboration, there are still times
when locking is appropriate.

The copy-modify-merge model is based on the assumption
that files are contextually mergeable: that is, that the
majority of the files in the repository are line-based text
files (such as program source code). But for files with
binary formats, such as artwork or sound, it's often
impossible to merge conflicting changes. In these
situations, it really is necessary to users to take strict
turns when changing the file. Without serialized access,
somebody ends up wasting time on changes that are ultimately
discarded.

While CVS and Subversion are still primarily
copy-modify-merge systems, they both recognize the need to
lock an occasional file and provide mechanisms for this.
See the section called “”.

SVK in Action

It's time to move from the abstract to the concrete. In
this section, we'll show real examples of SVK being
used.

Working Copies

You've already read about working copies; now we'll
demonstrate how the SVK client creates and uses
them.

A SVK working copy is an ordinary directory tree on
your local system, containing a collection of files. You can
edit these files however you wish, and if they're source code
files, you can compile your program from them in the usual
way. Your working copy is your own private work area:
SVK will never incorporate changes from the depot, nor
publish your own changes to the depot, until you
explicitly tell it to do so.

After you've made some changes to the files in your
working copy and verified that they work properly, SVK
provides you with commands to “publish” your
changes to the depot. If the depot contained changes not yet
in your working copy[3], SVK provides you with
commands to merge those changes into your working directory
(by reading from the depot).

A SVK working copy doesn't contain any extra files, unlike
Subversion and CVS working copies. Instead SVK keeps track of
the state of your working copy in a subdirectory of your home
directory named .svk.

A typical SVK depot often holds the files (or
source code) for several projects; usually, each project is a
subdirectory in the depot's filesystem tree. In this
arrangement, a user's working copy will usually correspond to
a particular subtree of the depot.

For example, suppose you have two software projects,
paint and calc, for
which you wish to start keeping a history.

To add these 2 projects to your depot you would run the
following commands:

Then repeat the same steps for the paint project. Now you
have 2 projects in the depot. Each project lives in its own
top-level subdirectory, as shown in Figure 2.5, “The depot's filesystem”.

Figure 2.5. The depot's filesystem

Since the calc and paint projects have been imported into
the depot, it's safe to remove the directories we imported
from, so lets run:

$ rm -rf calc
$ rm -rf paint

Now in order to get a working copy, you must
check out some subtree of the
depot[4].
(The term “check out” may sound like it has
something to do with locking or reserving resources, but it
doesn't; it simply creates a private copy of the project for
you.) For example, if you check out
/calc, you will get a working copy like
this:

The list of letter A's indicates that SVK is adding
a number of items to your working copy. You now have a
editable copy of the depot's /calc
directory.

Depot Paths

SVK depots are always on a local disk.[5] A
depotpath always starts with a / followed
by the name of the depot[6], followed by another
/. It just so happens the default depot
has the empty name , so the way to refer
to the default depot is //.

Suppose you make changes to button.c.
Since SVK knows the revision that the file in your working
copy was based on, SVK can tell that you've changed the file.
However, SVK does not make your changes public until you
explicitly tell it to. The act of publishing your changes is
more commonly known as committing (or
checking in) changes to the
depot.

To publish your changes to others, you can use
SVK's commit command:

$ svk commit button.c
Committed revision 57.

Now your changes to button.c have
been committed to the depot; if another user checks out a
working copy of /calc, they will see
your changes in the latest version of the file.

Suppose you have a collaborator, Sally, who checked out a
working copy of /calc at the same time
you did. When you commit your change to
button.c, Sally's working copy is left
unchanged; SVK only modifies working copies at the
user's request.

To bring her project up to date, Sally can ask
SVK to update her working copy,
by using the SVK update command.
This will incorporate your changes into her working copy, as
well as any others that have been committed since she checked
it out.

The output from the svk update command
indicates that SVK updated the contents of
button.c. Note that Sally didn't need to
specify which files to update; SVK uses the information
about the working copy stored inside
~/.svk/config, and further information from
the depot, to decide which files need to be brought up to
date.

Revisions

A svk commit operation can publish
changes to any number of files and directories as a single
atomic transaction. In your working copy, you can change
files' contents, create, delete, rename and copy files and
directories, and then commit the complete set of changes as a
unit.

In the depot, each commit is treated as an atomic
transaction: either all the commit's changes take place, or
none of them take place. SVK tries to retain this
atomicity in the face of program crashes, system crashes,
network problems, and other users' actions.

Each time the depot accepts a commit, this creates a
new state of the filesystem tree, called a
revision. Each revision is assigned a
unique natural number, one greater than the number of the
previous revision. The initial revision of a freshly created
depot is numbered zero, and consists of nothing but an
empty root directory.

Figure 2.6, “The depot” illustrates a nice way to
visualize the depot. Imagine an array of revision
numbers, starting at 0, stretching from left to right. Each
revision number has a filesystem tree hanging below it, and
each tree is a “snapshot” of the way the
depot looked after a commit.

Figure 2.6. The depot

Global Revision Numbers

Unlike those of many other version control systems,
SVK's revision numbers apply to entire
trees, not individual files. Each revision
number selects an entire tree, a particular state of the
depot after some committed change. Another way to
think about it is that revision N represents the state of
the depot filesystem after the Nth commit. When a
SVK user talks about “revision 5 of
foo.c”, they really mean
“foo.c as it appears in revision 5.”
Notice that in general, revisions N and M of a file do
not necessarily differ! Because CVS
uses per-file revisions numbers, CVS users might want to see
Appendix A, SVK for CVS Users for more details.

It's important to note that working copies do not always
correspond to any single revision in the depot; they may
contain files from several different revisions. For example,
suppose you check out a working copy from a depot whose
most recent revision is 4:

calc/Makefile:4
integer.c:4
button.c:4

At the moment, this working directory corresponds exactly
to revision 4 in the repository. However, suppose you make a
change to button.c, and commit that
change. Assuming no other commits have taken place, your
commit will create revision 5 of the depot, and your
working copy will now look like this:

calc/Makefile:4
integer.c:4
button.c:5

Suppose that, at this point, Sally commits a change to
integer.c, creating revision 6. If you
use svk update to bring your working copy
up to date, then it will look like this:

calc/Makefile:6
integer.c:6
button.c:6

Sally's change to integer.c will
appear in your working copy, and your change will still be
present in button.c. In this example,
the text of Makefile is identical in
revisions 4, 5, and 6, but SVK will mark your working
copy of Makefile with revision 6 to
indicate that it is still current. So, after you do a clean
update at the top of your working copy, it will generally
correspond to exactly one revision in the repository.

How Working Copies Track the Depot

For each working copy, SVK records
three essential pieces of information in the
hash: subsection of the
checkout: section in the
~/.svk/config file:

An absolute path to the working copy, or a
subdirectory thereof, and

what revision your working copy is based on (this is
called the working copy's working
revision), and

the encoding in which the filenames are stored by the
filesystem.

Given this information, by consulting the depot,
SVK can tell which of the following four states a
working file is in:

Unchanged, and current

The file is unchanged in the working directory, and
no changes to that file have been committed to the
depot since its working revision. An svk
commit of the file will do nothing, and an
svk update of the file will do
nothing.

Locally changed, and current

The file has been changed in the working directory,
and no changes to that file have been committed to the
depot since its base revision. There are local
changes that have not been committed to the depot,
thus an svk commit of the file will
succeed in publishing your changes, and an svk
update of the file will do nothing.

Unchanged, and out-of-date

The file has not been changed in the working
directory, but it has been changed in the depot.
The file should eventually be updated, to make it
current with the depot revision. An svk
commit of the file will do nothing, and an
svk update of the file will fold the
latest changes into your working copy.

Locally changed, and out-of-date

The file has been changed both in the working
directory, and in the depot. An svk
commit of the file will fail with an
“out-of-date” error. The file should be
updated first; an svk update command
will attempt to merge the public changes with the local
changes. If SVK can't complete the merge in a
plausible way automatically, it will ask the user how to
resolve the conflict.

This may sound like a lot to keep track of, but the
svk status command will show you the state
of any item in your working copy. For more information on
that command, see the section called “svk status”.

Mixed Revision Working Copies

As a general principle, Subversion tries to be as flexible
as possible. One special kind of flexibility is the ability
to have a working copy containing files and directories with a
mix of different working revision numbers. Unfortunately,
this flexibility tends to confuse a number of new users. If
the earlier example showing mixed revisions perplexed you,
here's a primer on both why the feature exists and how to make
use of it.

Updates and Commits are Separate

One of the fundamental rules of Subversion is that
a “push” action does not cause
a “pull”, nor the other way around. Just
because you're ready to submit new changes to the repository
doesn't mean you're ready to receive changes from other
people. And if you have new changes still in progress,
then svn update should gracefully merge
repository changes into your own, rather than forcing you to
publish them.

The main side-effect of this rule is that it means a
working copy has to do extra bookkeeping to track mixed
revisions, and be tolerant of the mixture as well. It's
made more complicated by the fact that directories
themselves are versioned.

For example, suppose you have a working copy entirely at
revision 10. You edit the
file foo.html and then perform
an svn commit, which creates revision 15
in the repository. After the commit succeeds, many new
users would expect the working copy to be entirely at
revision 15, but that's not the case! Any number of changes
might have happened in the repository between revisions 10
and 15. It would be a lie to claim that we had a working
copy of revision 15, the client simply doesn't know. If, on
the other hand, svn commit were to
automatically download the newest changes, then it would be
possible to set the entire working copy to revision
15—but then we'd be breaking the fundamental rule
of “push” and “pull” remaining
separate actions. Therefore the only safe thing the
Subversion client can do is mark the one
file—foo.html—as being at
revision 15. The rest of the working copy remains at
revision 10. Only by running svn update
can the latest changes be downloaded, and the whole working
copy be marked as revision 15.

Mixed revisions are normal

The fact is, every time you
run svn commit, your working copy ends
up with some mixture of revisions. The things you just
committed are marked as having larger working revisions
than everything else. After several commits (with no
updates in-between) your working copy will contain a whole
mixture of revisions. Even if you're the only person
using the repository, you will still see this phenomenon.
To examine your mixture of working revisions, use
the svn status --verbose command (see
the section called “svk status” for more
information.)

Often, new users are completely unaware that their
working copy contains mixed revisions. This can be
confusing, because many client commands are sensitive to
the working revision of the item they're examining. For
example, the svn log command is used to
display the history of changes to a file or directory (see
the section called “svk log”). When the user
invokes this command on a working copy object, they expect
to see the entire history of the object. But if the
object's working revision is quite old (often
because svn update hasn't been run in a
long time), then the history of
the older version of the object is
shown.

Mixed revisions are useful

If your project is sufficiently complex, you'll
discover that it's sometimes nice to forcibly
“backdate” portions of your working copy to
an earlier revision; you'll learn how to do that in
Chapter 3, Guided Tour. Perhaps you'd like to test an
earlier version of a sub-module contained in a
subdirectory, or perhaps you'd like to figure out when a
bug first came into existence in a specific file. This is
the “time machine” aspect of a version
control system — the feature which allows you to
move any portion of your working copy forward and backward
in history.

Mixed revisions have limitations

However you make use of mixed revisions in your
working copy, there are limitations to this
flexibility.

First, you cannot commit the deletion of a file or
directory which isn't fully up-to-date. If a newer
version of the item exists in the repository, your attempt
to delete will be rejected, to prevent you from
accidentally destroying changes you've not yet
seen.

Second, you cannot commit a metadata change to a
directory unless it's fully up-to-date. You'll learn
about attaching
“properties” to items in
Chapter 7, Advanced Topics A directory's working
revision defines a specific set of entries and properties,
and thus committing a property change to an out-of-date
directory may destroy properties you've not yet
seen.

Summary

We've covered a number of fundamental Subversion concepts in
this chapter:

We've introduced the notions of the central repository,
the client working copy, and the array of repository
revision trees.

We've seen some simple examples of how two collaborators
can use Subversion to publish and receive changes from one
another, using the “copy-modify-merge”
model.

We've talked a bit about the way Subversion tracks and
manages information in a working copy.

At this point, you should have a good idea of how Subversion
works in the most general sense. Armed with this knowledge, you
should now be ready to jump into the next chapter, which is a
detailed tour of Subversion's commands and features.

[2] Technically you can have
more than one depot, but well talk about that
later.

[4] Actually we could have caused the
directory from which we imported to become a working copy
simply by adding the --to-checkout switch to
the import command.

[5] If
your home directory is on a networked filesystem this is not
strictly true, and it is in fact possible to share a depot
amongst different users by having your depot on a shared
volume. However in chapter 3 we will show better ways of
working together on the same projects.

[6] Yes you can have
more than one depot, but don't worry about it for now.
Chances are you won't ever need more than
one.

Now we will go into the details of using SVK. By the
time you reach the end of this chapter, you will be able to
perform almost all the tasks you need to use SVK in a
normal day's work. You'll start with an initial checkout of
your code, and walk through making changes and examining those
changes. You'll also see how to bring changes made by others
into your working copy, examine them, and work through any
conflicts that might arise.

Note that this chapter is not meant to be an exhaustive list
of all SVK's commands—rather, it's a conversational
introduction to the most common SVK tasks you'll
encounter. This chapter assumes that you've read and understood
Chapter 2, Basic Concepts and are familiar with the general
model of SVK. For a complete reference of all commands,
see Chapter 9, SVK Complete Reference.

Help!

Before reading on, here is the most important command you'll
ever need when using SVK: svk help.
The SVK command-line client is
self-documenting—at any time, a quick svk help
<subcommand> will describe the syntax, switches,
and behavior of the subcommand.

Import

You use svk import to import a new
project into a SVK depot. While this is most likely
the very first thing you will do when you set up your depot,
it's not something that happens very often. For a
detailed description of import, see the section called “svk import” later in this chapter.

Mirror

You use svk mirror to mirror a remote
Subversion repository into a SVK depot[7]. SVK will then allow you to check out
working copies from your local mirror as well as commit changes
back to the mirrored repository. Basically this makes SVK a
Subversion client with a local cache, which as it turns out
makes SVK orders of magnitude faster than the basic Subversion
client. In addition this opens up the possibility to create local
branches and track changes between those and the mirror in both
directions, for more information on working with local branches,
see Chapter 4, Branching and Merging.

What About My Disk Space?

Although having a local mirror of a Subversion repository
uses up some disk space, in practice it turns out that due to
SVK's much more efficient working copies—which unlike
Subversion's own working copies contain no meta info or extra
copies of every file in your tree, SVK uses less total
disk space once you have about 2 or 3 working copies checked
out at once. That said, disk space is cheap these days and
SVK's local mirror dramatically reduces the network bandwidth
used and increases the speed of almost all operations.

Revisions: Numbers, Keywords, and Dates, Oh My!

Before we go on, you should know a bit about how to identify
a particular revision in your depot. As you learned in
the section called “Revisions”, a revision is a
“snapshot” of the depot at a particular moment
in time. As you continue to commit and grow your depot,
you need a mechanism for identifying these snapshots.

You specify these revisions by using the
--revision (-r) switch plus
the revision you want (svk <subcommand>
--revision REV) or you can specify a range by
separating two revisions with a colon (svk
<subcommand> --revision REV1:REV2). And SVK
lets you refer to these revisions by number, keyword, or
date.

Revision Numbers

When you create a new SVK depot, it begins its
life at revision zero and each successive commit increases the
revision number by one. After your commit completes, the
SVK client informs you of the new revision
number:

If at any point in the future you want to refer to that
revision (we'll see how and why we might want to do that later
in this chapter), you can refer to it as
“3”.

If, however, you were committing from a working copy that was
a direct checkout of a mirrored depotpath, things would be a
little more complicated. This is because the mirrored
repository has its own idea of revision numbers which is
distinct from the local depots idea of revision
numbers.

What happened here is that SVK first committed the change
you made to the original mirrored repository. After that it
automatically performs a svk sync to
download the change on the mirror to the local depot again.
This ensures that you can never commit anything to a mirrored
path that isn't also on the mirror itself.

Above we showed you how to use the
--revision switch to refer to a specific
revision number. By default the revision numbers you specify
are the ones in your depot. Sometimes you want to refer to a
particular revision of the mirrored repository instead.
Luckily SVK keeps a mapping from local to remote revision
numbers and allows you to specify both local depot revision
numbers or revision numbers in the mirrored repository when
performing operations. To do so you only need to add a
@ right after the revision number. To get
the log message for the revision we just committed above you
would use:

Notice how the log output shows both the local depots
r15, and mirrored repositories
r45 revision numbers. This can be a useful
aid in certain situations as well.

Revision Keywords

The SVK client understands a number of
revision keywords. These keywords
can be used instead of integer arguments to the
--revision switch, and are resolved into
specific revision numbers by SVK:

Note

For every file and directory in your working copy SVK
keeps track of the revision you last updated to. You can
refer to this as the “BASE” revision.

HEAD

The latest revision in the depot.

BASE

The last revision an item in a working copy was
updated to.

Note

BASE, can be used to refer to local
paths, but not to DEPOTPATHs.

Here are some examples of revision keywords in action.
Don't worry if the commands don't make sense yet; we'll be
explaining these commands as we go through the chapter:

$ svk diff --revision BASE:HEAD foo.c
# shows the changes in the depot not yet in your working copy.
$ svk log --revision HEAD
# shows log message for the latest depot commit
$ svk diff --revision HEAD
# compares your working file (with local mods) to the latest version
# in the depot.
$ svk diff --revision BASE:HEAD foo.c
# compares your “pristine” foo.c (no local mods) with the
# latest version in the depot
$ svk log --revision BASE:HEAD
# shows all commit logs since you last updated

These keywords allow you to perform many common (and
helpful) operations without having to look up specific
revision numbers or remember the exact revision of your
working copy.

Revision Dates

Anywhere that you specify a revision number or revision
keyword, you can also specify a date
inside curly braces “{}”. You can even access
a range of changes in the depot using both dates and
revisions together!

Here are examples of the date formats that SVK
accepts. Remember to use quotes around any date that contains
spaces.

If you specify a single date as a revision without
specifying a time of day (for example
2005-07-27), you may think that SVK
should give you the last revision that took place on the
27th of July. Instead, you'll get back a revision from
the 26th, or even earlier. Remember that SVK will
find the most recent revision of the
depot as of the date you give. If you give
a date without a timestamp, like
2005-07-27, SVK assumes a time of
00:00:00, so looking for the most recent revision won't
return anything on the day of the 27th.

If you want to include the 27th in your search, you can
either specify the 27th with the time ({"2005-07-27
23:59"}), or just specify the next day
({2005-07-28}).

You can also use a range of dates. SVK will find
all revisions between both dates, inclusive:

$ svk log --revision {2005-07-20}:{2005-07-29}
…

As we pointed out, you can also mix dates and revisions:

$ svk log --revision {2005-07-20}:4040

Users should be aware of a subtlety that can become quite
a stumbling-block when dealing with dates in SVK. Since
the timestamp of a revision is stored as a property of the
revision—an unversioned, modifiable
property—revision timestamps can be changed to represent
complete falsifications of true chronology, or even removed
altogether. This will wreak havoc on the internal
date-to-revision conversion that SVK performs.

Initial Checkout

Most of the time, you will want to start using SVK by
creating a mirror of a remote Subversion
repository containing your project. Mirroring a repository
creates a copy of it on your local machine. This copy contains
as much of the original history of the Subversion repository as
you want. For this example let's mirror everything:

Warning

When mirroring a project you will have the choice between
mirroring just trunk or the branch you are interested in as
opposed to the entire project. In most cases you will want to
mirror the entire project tree including the trunk, branches
and tags directories. Since branches and tags are cheap
copies on the remote server the mirror will also store them as
cheap copies and thus not use significantly more disk
space.

If you choose not to do this and mirror just a single
branch or trunk, and you later decide you need access to other
branches or tags in the remote repository, separately mirroring
those will cause you local depot to contain disjoint mirrors
of the individual branches and tags, and copies that were
originally cheap copies in the remote repository will become
full blown copies in your local depot. In addition you might
run into problems with merge tracking across remote
branches.

Tip

Creating a mirror of a large Subversion repository can
take quite a while. However rest assured that once you have
the mirror keeping it up to date is very fast. We will also
discuss several ways to speed up getting an initial mirror on
a large number of machines, see ##TODO.

Now that we have a mirror of the Subversion repository in
our depot we are ready to create a working copy:

$ svk checkout //mirror/svk/trunk
Syncing //mirror/svk/trunk(/mirror/svk/trunk) in /Users/sally/trunk to 1282.
A trunk/utils
A trunk/utils/extract-docs
A trunk/utils/extract-message-catalog
A trunk/utils/svk-ediff.el
A trunk/SIGNATURE
A trunk/pkg
…

Depot Layout

If you're wondering what trunk is all
about in the above DEPOTPATH, it's part of the way we recommend
you lay out your depot, and your Subversion repositories which
we'll talk a lot more about in Chapter 4, Branching and Merging.

Although the above example checks out the trunk directory,
you can just as easily check out any deep subdirectory of a
depot by specifying the subdirectory in the checkout
DEPOTPATH:

$ svk checkout //mirror/svk/trunk/lib/SVK/Command
Syncing //mirror/svk/trunk(/mirror/svk/trunk) in /Users/sally/Command to 1282.
A Command/Propdel.pm
A Command/Checkout.pm
A Command/Revert.pm
A Command/Cat.pm
…

Since SVK uses a “copy-modify-merge”
model instead of “lock-modify-unlock” (see Chapter 2, Basic Concepts), you're already able to start making
changes to the files and directories in your working copy. Your
working copy is just like any other collection of files and
directories on your system. You can edit and change them, move
them around, you can even delete the entire working copy and
forget about it—though you should run svk
checkout --detach to let svk know you removed
it.

Note

While your working copy is “just like any other
collection of files and directories on your system”,
you need to let SVK know if you're going to be
rearranging anything inside of your working copy. If you
want to copy or move an item in a working copy, you should
use svk copy or svk
move instead of the copy and move commands
provided by your operating system. We'll talk more about
them later in this chapter.

Unless you're ready to commit a new file or directory, or
changes to existing ones, there's no need to further notify the
Subversion server you mirrored from that you've done
anything.

While you can certainly check out a working copy with the
DEPOTPATH as the only argument, you can also specify
a directory after your DEPOTPATH. This places your working
copy in the new directory that you name. For example:

$ svk checkout //mirror/svk/trunk svk
Syncing //mirror/svk/trunk(/mirror/svk/trunk) in /Users/sally/svk to 1282.
A svk/utils
A svk/utils/extract-docs
A svk/utils/extract-message-catalog
A svk/utils/svk-ediff.el
A svk/SIGNATURE
…

That will place your working copy in a directory named
svk instead of a directory named
trunk as we did previously.

Managing Working Copies

In SVK, unlike CVS and Subversion, working copies contain
no files or directories other than the ones in your project.
There are no .svn or CVS
directories to get in your, or your tools way. This huge
advantage comes at a small price. If you move or remove a
working copy, you need to let SVK know. You can do so by
using the --relocate or
--detach switches to the svk
checkout command, see svk checkout for some examples.

Basic Work Cycle

SVK has numerous features, options, bells and whistles, but on
a day-to-day basis, odds are that you will only use a few of them. In
this section we'll run through the most common things that you might
find yourself doing with SVK in the course of a day's work.

The typical work cycle looks like this:

Update your working copy

svk sync

svk update

Make changes

svk add

svk delete

svk copy

svk move

Examine your changes

svk status

svk diff

svk revert

Merge others' changes into your working copy

svk update

svk resolved

Commit your changes

svk commit

Update Your Working Copy

When working on a project with a team, you'll want to
update your mirror to receive any changes made by other
developers on the project since your last update.

Tip

You can combine the first 2 steps by passing the
--sync (-s) switch to
svk update

In this case, someone else checked in modifications to
both foo.c and bar.c
since the last time you updated, and SVK has updated
your working copy to include those changes.

Let's examine the output of svk update
a bit more. When the server sends changes to your working
copy, a letter code is displayed next to each item to let you
know what actions SVK performed to bring your working
copy up-to-date:

U foo

File foo was
Updated (received changes
from the server).

A foo

File or directory foo was
Added to your working
copy.

D foo

File or directory foo was
Deleted from your working
copy.

R foo

File or directory foo was
Replaced in your working
copy; that is, foo was deleted, and a
new item with the same name was added. While they may have
the same name, the depot considers them to be distinct
objects with distinct histories.

G foo

File foo received new changes
from the depot, but your working copy version of the
file had your modifications. The changes did not
intersect, so SVK has successfully
merGed the depot's
changes into the file without a problem.

g foo

File foo received new changes
from the depot, but your working copy version of the
file had your modifications. However the changes were
exactly the same as your local modifications, so SVK has
successfully merged the
depot's changes into the file without changing a
thing.

C foo

File foo received
Conflicting changes from
the server. The changes from the server directly overlap
your own changes to the file. No need to panic, though.
This overlap needs to be resolved by a human (you); we
discuss this situation later in this chapter.

Make Changes to Your Working Copy

Now you can get to work and make changes in your
working copy. It's usually most convenient to decide on a
particular change (or set of changes) to make, such as writing
a new feature, fixing a bug, etc. The SVK commands
that you will use here are svk add,
svk delete, svk copy,
and svk move. However, if you are merely
editing files that are already in SVK, you may not need
to use any of these commands until you commit. Changes you can
make to your working copy:

File changes

This is the simplest sort of change. You don't need
to tell SVK that you intend to change a file;
just make your changes. SVK will be able to
automatically detect which files have been
changed.

Tree changes

You can ask SVK to “mark” files
and directories for scheduled removal, addition,
copying, or moving. While these changes may take place
immediately in your working copy, no additions or
removals will happen in the depot until you commit
them.

To make file changes, use your text editor, word
processor, graphics program, or whatever tool you would
normally use. SVK handles binary files just as easily
as it handles text files—and just as efficiently
too.

Here is an overview of the four SVK subcommands
that you'll use most often to make tree changes (we'll cover
svk import and svk mkdir
later).

Warning

While you can edit your files with whatever tool you
like, you shouldn't change the structure of your working
copy without letting SVK know what you're doing. Use
the svk copy, svk
delete, and svk move commands
to change the structure of your working copy, and use the
svk add command to place new files and
directories under version control.

svk add foo

Schedule file, directory, or symbolic link
foo to be added to the depot.
When you next commit, foo will
become a child of its parent directory. Note that if
foo is a directory, everything
underneath foo will be scheduled
for addition. If you only want to add
foo itself, pass the
--non-recursive (-N)
switch.

svk delete foo

Schedule file, directory, or symbolic link
foo to be deleted from the
depot. If foo is a file or
link, it is immediately deleted from your working copy.
If foo is a directory, it is not
deleted, but SVK schedules it for deletion. When
you commit your changes, foo will
be removed from your working copy and the depot.
[8]

svk copy foo bar

Create a new item bar as a
duplicate of foo.
bar is automatically scheduled for
addition. When bar is added to the
depot on the next commit, its copy history is
recorded (as having originally come from
foo). svk copy
does not create intermediate directories unless you pass
it the --parent switch.

svk move foo bar

This command is exactly the same as running
svk copy foo bar; svk delete foo.
That is, bar is scheduled for
addition as a copy of foo, and
foo is scheduled for removal.
svk move does not create intermediate
directories unless you pass it the
--parent switch.

Changing the Depot Without a Working Copy

Earlier in this chapter, we said that you have to commit
any changes that you make in order for the depot to
reflect these changes. That's not entirely true—there
are some use cases that immediately
commit tree changes to the depot. This only happens
when a subcommand is operating directly on a depot path, rather
than on a working-copy path. Any SVK command that can
operate on your working copy can also operate directly on
depot paths

Depot path operations behave in this manner because
commands that operate on a working copy can use the working
copy as a sort of “staging area” to set up your
changes before committing them to the depot. Commands
that operate on depot paths don't have this luxury, so when
you operate directly on a depot paths, the commands actions
represent an immediate commit.

Examine Your Changes

Once you've finished making changes, you need to commit
them to the depot, but before you do so, it's usually a
good idea to take a look at exactly what you've changed. By
examining your changes before you commit, you can make a
more accurate log message. You may also discover that
you've inadvertently changed a file, and this gives you a
chance to revert those changes before committing.
Additionally, this is a good opportunity to review and
scrutinize changes before publishing them. You can see
exactly what changes you've made by using svk
status, svk diff, and
svk revert. You will usually use the first
two commands to find out what files have changed in your
working copy, and then perhaps the third to revert some (or
all) of those changes.

svk status

You'll probably use the svk status
command more than any other SVK command.

CVS Users: Hold That Update!

You're probably used to using cvs update
-qn to see what changes you've made to your
working copy. svk status will give you
all the information you need regarding what has changed in
your working copy—without potentially incorporating
new changes published by other users.

In SVK, update does just
that—it updates your working copy with any changes
committed to the depot since the last time you've
updated your working copy. You'll have to break the habit
of using the update command to see what
local modifications you've made.

If you run svk status at the top of
your working copy with no arguments, it will detect all file
and tree changes you've made. Below are examples of
the different status codes that svk
status can return. (Note that the text following
# is not
actually printed by svk status.)

M bar.c # the content in bar.c has local modifications
M baz.c # baz.c has property but no content modifications
? foo.o # svk doesn't manage foo.o
! some_dir # svk manages this, but it's missing or incomplete
~ qux # versioned as file/dir/link, but type has changed
I .screenrc # svk doesn't manage this, and is set to ignore it
A moved_dir # added with history of where it came from
M moved_dir/README # added with history and has local modifications
D stuff/fish.c # file is scheduled for deletion
A stuff/loot/bloo.h # file is scheduled for addition
C stuff/loot/lump.c # file has textual conflicts from an update
C stuff/loot/glub.c # file has property conflicts from an update
R xyz.c # file is scheduled for replacement

In this output format svk status
prints three columns of characters, followed by a whitespace
character, followed by a file or directory name. The first
column tells the status of a file or directory and/or its
contents. The codes printed here are:

A item

The file, directory, or symbolic link
item has been scheduled for
addition into the depot.

C item

The file item is in a state
of conflict. That is, changes received from the
server during an update overlap with local changes
that you have in your working copy. You must resolve
this conflict before committing your changes to the
depot.

D item

The file, directory, or symbolic link
item has been scheduled for
deletion from the depot.

M item

The contents of the file item
have been modified.

R item

The file, directory, or symbolic link
item has been scheduled to
replace item in the depot.
This means that the object is first deleted, then
another object of the same name is added, all within a
single revision.

? item

The file, directory, or symbolic link
item is not under version
control. You can silence the question marks by either
passing the --quiet
(-q) switch to svk
status, or by setting the
svn:ignore property on the parent
directory. For more information on ignored files, see
the section called “”.

! item

The file, directory, or symbolic link
item is under version control but
is missing or somehow incomplete. The item can be
missing if it's removed using a non-SVK command. In
the case of a directory, it can be incomplete if you
happened to interrupt a checkout or update. A quick
svk revert --recursive item
will refetch the directory from the depot, or
svk revert item will restore a
missing file.

~ item

The file, directory, or symbolic link
item is in the depot as one
kind of object, but what's actually in your working
copy is some other kind. For example, SVK
might have a file in the depot, but you removed
the file and created a directory in its place, without
using the svk delete or
svk add command.

I item

The file, directory, or symbolic link
item is not under version control,
and SVK is configured to ignore it during
svk add, svk import
and svk status operations. For more
information on ignored files, see the section called “”. Note that this
symbol only shows up if you pass the
--no-ignore switch to svk
status—otherwise the file would be
ignored and not listed at all!

The second column tells the status of a file or
directory's properties (see the section called “” for more information on
properties). If an M
appears in the second column, then the properties have been
modified, otherwise a whitespace will be printed.

The third column will only show whitespace or a
which means that the file
or directory is scheduled to be added or modified with
additional attached history. This typically happens when you
svk move or svk copy a file
or directory. If you see
A , this means
the item is scheduled for addition-with-history. It could be
a file, or the root of a copied directory.
means the item is part of a subtree scheduled for
addition-with-history, i.e. some parent got copied, and it's
just coming along for the ride.
M means the item
is part of a subtree scheduled for addition-with-history,
and it has local modifications. When you
commit, first the parent will be added-with-history (copied),
which means this file will automatically exist in the copy.
Then the local modifications will be uploaded into the
copy.

If you pass a specific path to svk
status, it gives you information about that item
alone:

$ svk status stuff/fish.c
D stuff/fish.c

svk status also has a
--verbose (-v) switch,
which will show you the status of every
item in your working copy, even if it has not been
changed:

This is the “long form” output of
svk status. The first column remains
the same, but the second column shows the working-revision of
the item. The third and fourth columns show the revision in
which the item last changed, and who changed it.

None of the above invocations to svk
status show you changes in the depot that your
working copy does not yet have. To do this you need to use
the svk update with the
--check-only (-C) switch,
which will show what would happen if you actually ran
svk update:

Notice the two entries.
svk update at this point, you would
receive changes to README
and trout.c. This tells you some very
useful information—you'll need to update and get the
server changes on README before you
commit, or the depot will reject your commit for being
out-of-date. (More on this subject later.)

svk diff

Another way to examine your changes is with the
svk diff command. You can find out
exactly how you've modified things by
running svk diff with no arguments, which
prints out file changes in unified diff
format:[9]

The svk diff command produces this
output by comparing your working files against the
BASE revision in the depot. Files
scheduled for addition are displayed as all added-text, and
files scheduled for deletion are displayed as all deleted
text.

Output is displayed in unified diff
format. That is, removed lines are prefaced
with a - and added lines are prefaced
with a . svk diff
also prints filename and offset information useful to the
patch program, so you can generate
“patches” by redirecting the diff output to a
file:

$ svk diff > patchfile

You could, for example, email the patch file to another
developer for review or testing prior to commit.

Note

However SVK has a much better way to create patches,
which is by using the --patch switch to
svk commit or almost any other command
that modifies the depot. Some notable advantages of this
method over using svk diff include that
patches contain log messages, and tree changes, as well as
binary file changes, while remaining safe to be sent
though email.

$ svk commit --message '' --patch - > patchfile

svk revert

Now suppose you see the above diff output, and realize
that your changes to README are a
mistake; perhaps you accidentally typed that text into the
wrong file in your editor.

This is a perfect opportunity to use svk
revert.

$ svk revert README
Reverted README

SVK reverts the file to its pre-modified state by
overwriting it with the version your working copy was based
on. But also note that svk revert can
undo any scheduled operations—for
example, you might decide that you don't want to add a new
file after all:

Any svk command that is not a commit to a mirrored
repository or a sync with a mirror can be used without any
network access. This makes it easy to manage your
changes-in-progress when you are somewhere without a network
connection, such as traveling on an airplane, riding a
commuter train or hacking on the beach.

Resolve Conflicts (Merging Others' Changes)

We've already seen how svk update --check-only
can predict conflicts. Suppose you run svk
update and some interesting things occur:

The U,
G and
g codes are no cause for
concern; those files cleanly absorbed changes from the
depot. The files marked with
U contained no local changes
but were Updated with changes
from the repository. The G
stands for merGed, which
means that the file had local changes to begin with, but the
changes coming from the depot didn't overlap with the local
changes. Finally the g
stands for merged, but in
this case your local copy already contained all the changes
from the depot, so the update operation did not modify the
file.

When a file has local changes, and the changes coming from
the depot overlap with the local changes, that file is
considered to have a conflict. When this happens SVK gives
you a number of choices:

If SVK doesn't consider the file to be of a mergeable type
then only the t and y
options below are available. (SVK uses the
svn:mime-type property to decide if a
file is capable of contextual, line-based merging. See
the section called “” to
learn more.)

e—edit

After SVK places conflict
markers—special strings of text which
delimit the “sides” of the
conflict—into the file to visibly demonstrate the
overlapping areas, the file is opened in an editor
window.

If after editing the file all the conflict markers
have been removed SVK will now give you the option to
accept (a) the changes you have made.
All the other options remain available as well, so you
can now view the diffs after your edits, re-edit the
file, etc.

d—diff

Diff your file against the merged file.
This runs the internal diff tool or that specified by the
$SVKDIFF environment variable.

dm—diff merged

Diff the base revision of the file against
the merged file.
This runs the internal diff tool or that specified by the
$SVKDIFF environment variable.

dt—diff theirs

Diff the base revision of the file against
the revision of the file from the depot.
This runs the internal diff tool or that specified by the
$SVKDIFF environment variable.

dy—diff yours

Diff the base revision of the file against
the local version of the file (or when merging directly to
a depot against revision of the file being merged to).
This runs the internal diff tool or that specified by the
$SVKDIFF environment variable.

m—merge

Invokes a 3 way merging tool or your choice and lets
you resolve the conflicts using that. If you have more
than one supported merging tool installed SVK will
prompt you to pick one like so:

The merge tools listed will vary based on which ones
you have installed. Like the message says you can set
your $SVKMERGE environment variable
to avoid having to choose a merge tool each time you
select the merge (m) option.
Currently SVK supports the following merge tools:
AraxisMerge, Emacs, FileMerge, GVim, GtkDiff, Guiffy,
KDiff3, Meld, P4WinMerge, TkDiff, TortoiseMerge, Vim,
XXDiff.

Entering q will return you to the
previous menu and let you choose any of the other
options again.

This option is very similar to the edit
(e) option in that, after merging the
file SVK will give you the option to accept
(a) the changes you have made. All
the other options remain available as well, so you can
now view the diffs after your edits, edit the file,
re-merge it, etc.

SVK places conflict
markers—special strings of text which
delimit the “sides” of the
conflict—into the file to visibly demonstrate the
overlapping areas.

The file in question remains in conflict and running
svk status on it will show it as
being in state C or
conflicting. You will need to manually edit the file to
remove the conflicts, and run svk
resolved once you have done so to let SVK know
the file is no longer in conflict.

t—theirs

Keep the changes between the base and depot
version of the file. This discards the local changes you
made to the file (or when merging directly to a depot,
discards the changes between the merge base and the
revision of the file being merged to).

y—yours

Keep the local version of the file (or when
merging directly to a depot keep the revision of the file
being merged to). This discards the changes made between
the base and the depot version of the file.

h—help

Displays help explaining all the different
options presented.

For example, Sally makes changes to the file
sandwich.txt in the depot. Harry has
just changed the file in his working copy and checked it in.
Sally updates her working copy before checking in and she gets
a conflict. She decides to skip doing the merge and do it by
hand after the fact:

Merging Conflicts by Hand

Merging conflicts by hand can be quite intimidating the
first time you attempt it, but with a little practice, it
can become as easy as falling off a bike.

Here's an example. Due to a miscommunication, you and
Sally, your collaborator, both edit the file
sandwich.txt at the same time. Sally
commits her changes, and when you go to update your working
copy, you get a conflict and we're going to have to edit
sandwich.txt to resolve the conflicts.
First, let's take a look at the file:

The lines ending in 112646405792039[11] are conflict markers, and are
not part of the actual data in conflict. You generally want
to ensure that those are removed from the file before your
next commit. The text between the first two sets of markers
is composed of the changes you made in the conflicting
area:

Usually you won't want to just delete the conflict
markers and Sally's changes—she's going to be awfully
surprised when the sandwich arrives and it's not what she
wanted. So this is where you pick up the phone or walk
across the office and explain to Sally that you can't get
sauerkraut from an Italian deli.[12] Once you've agreed on the changes
you will check in, edit your file and remove the conflict
markers.

Resolving the changes

If you get a conflict and you want to resolve it right
away you can choose the edit option to
edit the file in conflict. SVK will launch your selected
editor with a buffer containing the exact same contents you
would have gotten if you used the skip
option above. Once you finish editing the file and all the
conflict markers have been removed SVK will allow you to
accept the changes you made:

It's rare that you would do this blindly (since you
don't know what the changes are that you are discarding) so
in most cases you'd want to look at the changes first. To
do so you would use dt to show their
changes:

Punting: Using svk revert

If you get a conflict, and upon examination decide that
you want to throw out your changes and start your edits
again, just revert your changes:

$ svk revert sandwich.txt
Reverted 'sandwich.txt'

Note that when you revert a conflicted file, you don't
have to run svk resolved.

Now you're ready to check in your changes. Note that
svk resolved, unlike most of the other
commands we've dealt with in this chapter, requires an
argument. In any case, you want to be careful and only run
svk resolved when you're certain that you've
fixed the conflict in your file—once you have run svk
resolved, SVK will let you commit the file even if it still
contains conflict markers.

Commit Your Changes

Finally! Your edits are finished, you've merged all
changes from the server, and you're ready to commit your
changes to the depot.

The svk commit command sends all of
your changes to the depot. When you commit a change, you
need to supply a log message,
describing your change. Your log message will be attached to
the new revision you create. If your log message is brief,
you may wish to supply it on the command line using the
--message (or -m)
switch:

However, if you've been composing your log message as you
work, you may want to tell SVK to get the message from
a file by passing the filename with the
--file switch:

$ svk commit --file logmsg
Committed revision 71.

If you fail to specify either the
--message or --file switch,
then SVK will automatically launch your favorite editor (see
the $SVN_EDITOR section in the section called “”) for composing a
log message.

Tip

If you're in your editor writing a commit message and
decide that you want to cancel your commit, you can just
quit your editor without saving changes. If you've already
saved your commit message, simply delete the text and save
again.

The depot doesn't know or care if your changes make
any sense as a whole; it only checks to make sure that nobody
else has changed any of the same files that you did when you
weren't looking. If somebody has done
that, the entire commit will fail with a message informing you
that one or more of your files is out-of-date:

$ svk commit --message "Add more cheese"
Transaction is out of date: Out of date: '/bread/trunk/sandwich.txt' in transaction '71-1'
Please update checkout first.

At this point, you need to run svk
update, deal with any merges or conflicts that
result, and attempt your commit again.

That covers the basic work cycle for using SVK. There are
many other features in SVK that you can use to manage your
repository and working copy, but you can get by quite easily
using only the commands that we've discussed so far in this
chapter.

Examining History

As we mentioned earlier, the depot is like a time
machine. It keeps a record of every change ever committed,
and allows you to explore this history by examining previous
versions of files and directories as well as the metadata that
accompanies them. With a single SVK command, you can
check out the depot (or restore an existing working copy)
exactly as it was at any date or revision number in the past.
However, sometimes you just want to peer
into the past instead of going
into the past.

There are several commands that can provide you with
historical data from the depot:

svk log

Shows you broad information: log messages attached
to revisions, and which paths changed in each
revision.

svk diff

Shows you the specific details of how a file changed
over time.

svk cat

This is used to retrieve any file as it existed in a
particular revision number and display it on your
screen.

svk list

Displays the files in a directory for any given
revision.

svk log

To find information about the history of a file or
directory, use the svk log
command. svk log will provide you with a
record of who made changes to a file or directory, at what
revision it changed, the time and date of that revision, and,
if it was provided, the log message that accompanied the
commit.

Note that the log messages are printed in
reverse chronological order by default.
If you wish to see a different range of revisions in a
particular order, or just a single revision, pass the
--revision (-r)
switch:

You can also examine the log history of a single file or
directory. For example:

$ svk log foo.c
…
$ svk log //trunk/code/foo.c
…

These will display log messages only
for those revisions in which the working file (or DEPOTPATH)
changed.

If you want even more information about a file or
directory, svk log also takes a
--verbose (-v) switch.
Because SVK allows you to move and copy files and
directories, it is important to be able to track path changes
in the filesystem, so in verbose mode, svk
log will include a list of changed paths in a
revision in its output:

At first glance, this seems like an error. But recall
that while revisions are depot-wide, svk
log operates on a path in the depot. If you
supply no path, SVK uses the current working directory as
the default target. As a result, if you're operating in a
subdirectory of your working copy and attempt to see the log
of a revision in which neither that directory nor any of its
children was changed, SVK will show you an empty log. If
you want to see what changed in that revision, try pointing
svk log directly at the top of your
depot, as in svk log -r 2 //.

svk diff

We've already seen svk diff
before—it displays file differences in unified diff
format; it was used to show the local modifications made to
our working copy before committing to the repository.

In fact, it turns out that there are
three distinct uses of svk
diff:

Examine local changes

Compare your working copy to the depot

Compare depot to depot

Examining Local Changes

As we've seen, invoking svk diff with
no switches will compare your working files to the revision
from the depot that your working copy is based on:

Not only can you use svk diff to
compare files in your working copy to the depot, but if
you supply a depotpath argument, you can examine the differences
between items in the depot without even having a
working copy. This is especially useful if you wish to
inspect changes in a file when you don't have a working copy
on your local machine:

$ svk diff --revision 4:5 //example/trunk/text/rules.txt
…
$

svk cat

If you want to examine an earlier version of a file and
not necessarily the differences between two files, you can use
svk cat:

You're probably wondering why we don't just use
svk update --revision to update the file to
the older revision. There are a few reasons why we might
prefer to use svk cat.

First, you may want to see the differences between two
revisions of a file using an external diff program (perhaps a
graphical one, or perhaps your file is in such a format that
the output of unified diff is nonsensical). In this case,
you'll need to grab a copy of the old revision, redirect it to
a file, and pass both that and the file in your working copy
to your external diff program.

Sometimes it's easier to look at an older version of a
file in its entirety as opposed to just the differences
between it and another revision.

svk list

The svk list command shows you what
files are in a repository directory without actually
downloading the files to your local machine:

$ svk list //
README
bread/
calc/
mirror/
paint/
tags/

If you want a more detailed listing, pass the
--verbose (-v) flag to get
output like this:

Other Useful Commands

While not as frequently used as the commands previously
discussed in this chapter, you will occasionally need these
commands.

svk cleanup

When SVK modifies your working copy, it tries to do
so as safely as possible. Before changing the working copy,
SVK writes its intentions to a log file. Next it executes
the commands in the log file to apply the requested change.
Finally, SVK removes the log file. Architecturally, this
is similar to a journaled filesystem. If a SVK operation is
interrupted (if the process is killed, or if the machine
crashes, for example), the log files remain on disk. By
re-executing the log files, SVK can complete the
previously started operation, and your working copy can get
itself back into a consistent state.

And this is exactly what svk cleanup
does: it searches your working copy and runs any leftover
logs, removing locks in the process. If SVK ever tells you
that some part of your working copy is “locked”,
then this is the command that you should run:

[7] SVK can
even mirror other types of repositories such as CVS and
perforce by using vcp. However as of now this is a read only
mirror.

[8] Of course, nothing is ever totally
deleted from the depot—just from the
HEAD of the depot. You can get
back anything you delete by checking out (or updating
your working copy) a revision earlier than the one in
which you deleted it.

[9] SVK uses its internal diff engine,
which produces unified diff format, by default. If you want
diff output in a different format, specify an external diff
program with any options you wish to pass to it by setting
the $SVKDIFF environment variable. For
example, to see local differences in file
foo.c in context output format while
ignoring whitespace changes, you might run
SVKDIFF="diff -bc" svk diff foo.c.

Branching, tagging, and merging are concepts common to
almost all version control systems. If you're not familiar with
these ideas, we provide a good introduction in this chapter. If
you are familiar, then hopefully you'll find it interesting to
see how SVK implements these ideas.

Branching is a fundamental part of version control. If
you're going to allow SVK to manage your data, then this
is a feature you'll eventually come to depend on. This chapter
assumes that you're already familiar with SVK's basic
concepts (Chapter 2, Basic Concepts).

What's a Branch?

Suppose it's your job to maintain a document for a division
in your company, a handbook of some sort. One day a different
division asks you for the same handbook, but with a few parts
“tweaked” for them, since they do things slightly
differently.

What do you do in this situation? You do the obvious thing:
you make a second copy of your document, and begin maintaining
the two copies separately. As each department asks you to make
small changes, you incorporate them into one copy or the
other.

You often want to make the same change to both copies. For
example, if you discover a typo in the first copy, it's very
likely that the same typo exists in the second copy. The two
documents are almost the same, after all; they only differ in
small, specific ways.

This is the basic concept of a
branch—namely, a line of
development that exists independently of another line, yet still
shares a common history if you look far enough back in time. A
branch always begins life as a copy of something, and moves on
from there, generating its own history (see Figure 4.1, “Branches of development”).

Figure 4.1. Branches of development

SVK has commands to help you maintain parallel
branches of your files and directories. It allows you to create
branches by copying your data, and remembers that the copies are
related to one another. It also helps you duplicate changes
from one branch to another. Finally, it keep track of which
changes are present on each branch so that you only need to
resolve conflicting changes once.

Using Branches

At this point, you should understand how each commit creates
an entire new filesystem tree (called a “revision”)
in the depot. If not, go back and read about revisions in
the section called “Revisions”.

For this chapter, we'll go back to the same example from
Chapter 2. Remember that you and your collaborator, Sally, are
sharing a depot that contains two projects,
paint and calc.
Notice that in Figure 4.2, “Starting depot layout”, however, each
project directory now contains subdirectories named
trunk and branches.
The reason for this will soon become clear.

Figure 4.2. Starting depot layout

As before, assume that Sally and you both have working
copies of the “calc” project. Specifically, you
each have a working copy of /calc/trunk.
All the files for the project are in this subdirectory rather
than in /calc itself, because your team has
decided that /calc/trunk is where the
“main line” of development is going to take
place.

Let's say that you've been given the task of performing a
radical reorganization of the project. It will take a long time
to write, and will affect all the files in the project. The
problem here is that you don't want to interfere with Sally, who
is in the process of fixing small bugs here and there. She's
depending on the fact that the latest version of the project (in
/calc/trunk) is always usable. If you
start committing your changes bit-by-bit, you'll surely break
things for Sally.

One strategy is to crawl into a hole: you and Sally can stop
sharing information for a week or two. That is, start gutting
and reorganizing all the files in your working copy, but don't
commit or update until you're completely finished with the task.
There are a number of problems with this, though. First, it's
not very safe. Most people like to save their work to the
depot frequently, should something bad accidentally happen
to their working copy. Second, it's not very flexible. If you
do your work on different computers (perhaps you have a working
copy of /calc/trunk on two different
machines), you'll need to manually copy your changes back and
forth, or just do all the work on a single computer. By that
same token, it's difficult to share your changes-in-progress
with anyone else. A common software development “best
practice” is to allow your peers to review your work as you
go. If nobody sees your intermediate commits, you lose
potential feedback. Finally, when you're finished with all your
changes, you might find it very difficult to re-merge your final
work with the rest of the company's main body of code. Sally
(or others) may have made many other changes in the depot
that are difficult to incorporate into your working
copy—especially if you run svk update
after weeks of isolation.

The better solution is to create your own branch, or line of
development, in the depot. This allows you to save your
half-broken work frequently without interfering with others, yet
you can still selectively share information with your
collaborators. You'll see exactly how this works later
on.

Creating a Branch

Creating a branch is very simple—you make a copy of
the project in the depot using the svk
copy command. SVK is not only able to copy
single files, but whole directories as well. In this case,
you want to make a copy of the
/calc/trunk directory. Where should the
new copy live? Wherever you wish—it's a matter of
project policy. Let's say that your team has a policy of
creating branches in the /calc/branches
area of the repository, and you want to name your branch
my-calc-branch. You'll want to create a
new directory,
/calc/branches/my-calc-branch, which
begins its life as a copy of
/calc/trunk.

There are two different ways to make a copy. We'll
demonstrate the messy way first, just to make the concept
clear. To begin, check out a working copy of the project's
root directory, /calc:

$ svk checkout //calc bigwc
Syncing //calc(/calc) in /Users/sally/bigwc to 78.
A bigwc/trunk
A bigwc/trunk/button.c
A bigwc/trunk/Makefile
A bigwc/trunk/integer.c
A bigwc/branches

Making a copy is now simply a matter of passing two
working-copy paths to the svk copy
command:

In this case, the svk copy command
recursively copies the trunk working
directory to a new working directory,
branches/my-calc-branch. As you can see
from the svk status command, the new
directory is now scheduled for addition to the repository.
But also notice the “” sign in the third column.
This indicates that the scheduled addition is a
copy of something, not something new.
When you commit your changes, SVK will create
/calc/branches/my-calc-branch in the
depot by copying /calc/trunk:

There's really no difference between these two methods.
Both procedures create a new directory in revision 79, and
the new directory is a copy of
/calc/trunk. This is shown in Figure 4.3, “Depot with new copy”. Notice that the second method,
however, performs an immediate commit.
[14]
It's an easier procedure, because it doesn't require you to
check out a large mirror of the depot. In fact, this
technique doesn't even require you to have a working copy at
all.

Figure 4.3. Depot with new copy

Cheap Copies

SVK's depot has a special design. When you
copy a directory, you don't need to worry about the
depot growing huge—SVK doesn't actually
duplicate any data. Instead, it creates a new directory
entry that points to an existing tree.
If you're a Unix user, this is the same concept as a
hard-link. From there, the copy is said to be
“lazy”. That is, if you commit a change to one
file within the copied directory, then only that file
changes—the rest of the files continue to exist as
links to the original files in the original
directory.

This is why you'll often hear SVK users talk
about “cheap copies”. It doesn't matter how
large the directory is—it takes a very tiny, constant
amount of time to make a copy of it. In fact, this feature
is the basis of how commits work in SVK: each
revision is a “cheap copy” of the previous
revision, with a few items lazily changed within. (To read
more about this, visit Subversion's website and read about
the “bubble up” method in Subversion's design
documents.)

Of course, these internal mechanics of copying and
sharing data are hidden from the user, who simply sees
copies of trees. The main point here is that copies are
cheap, both in time and space. Make branches as often as
you want.

Working with Your Branch

Now that you've created a branch of the project, you can
check out a new working copy to start using it:

There's nothing special about this working copy; it simply
mirrors a different directory in the depot. When you
commit changes, however, Sally won't ever see them when she
updates. Her working copy is of
/calc/trunk. (Be sure to read the section called “Switching a Working Copy” later in this chapter: the
svk switch command is an alternate way of
creating a working copy of a branch.)

Let's pretend that a week goes by, and the following
commits happen:

You make a change to
/calc/branches/my-calc-branch/integer.c,
which creates revision 80.

You make a change to
/calc/branches/my-calc-branch/button.c,
which creates revision 81.

Sally makes a change to
/calc/trunk/integer.c, which creates
revision 82.

Notice that SVK is only tracing the history of your
branch's integer.c to the point where it
was copied. It shows the creation of the branch as an event in the
history, because integer.c was implicitly
copied when all of /calc/trunk/ was
copied. If you want to see the history prior to the copy you
need to supply the --cross
(-x) switch to the svk log
command:

Sally sees her own revision 82 change, but not the change
you made in revision 80. As far as SVK is concerned,
these two commits affected different files in different
depot locations. However, SVK
does show that the two files share a
common history. Before the branch-copy was made in revision
79, they used to be the same file. That's why you and Sally
both see the changes made in revisions 45 and 2.

The Key Concepts Behind Branches

There are two important lessons that you should remember
from this section.

Unlike many other version control systems,
SVK's branches exist as normal filesystem
directories in the depot, not in an extra
dimension. These directories just happen to carry some
extra historical information.

SVK has no internal concept of a
branch—only copies. When you copy a directory, the
resulting directory is only a “branch”
because you attach that meaning to
it. You may think of the directory differently, or treat
it differently, but to SVK it's just an ordinary
directory that happens to have been created by
copying.

Copying Changes Between Branches

Now you and Sally are working on parallel branches of the
project: you're working on a private branch, and Sally is
working on the trunk, or main line of
development.

For projects that have a large number of contributors, it's
common for most people to have working copies of the trunk.
Whenever someone needs to make a long-running change that is
likely to disrupt the trunk, a standard procedure is to create a
private branch and commit changes there until all the work is
complete.

So, the good news is that you and Sally aren't interfering
with each other. The bad news is that it's very easy to drift
too far apart. Remember that one of the
problems with the “crawl in a hole” strategy is
that by the time you're finished with your branch, it may be
near-impossible to merge your changes back into the trunk
without a huge number of conflicts.

Instead, you and Sally might continue to share changes as
you work. It's up to you to decide which changes are worth
sharing; SVK gives you the ability to selectively
“copy” changes between branches. And when you're
completely finished with your branch, your entire set of branch
changes can be copied back into the trunk.

Copying Specific Changes

In the previous section, we mentioned that both you and
Sally made changes to integer.c on
different branches. If you look at Sally's log message for
revision 344, you can see that she fixed some spelling errors.
No doubt, your copy of the same file still has the same spelling
errors. It's likely that your future changes to this file will
be affecting the same areas that have the spelling errors, so
you're in for some potential conflicts when you merge your
branch someday. It's better, then, to receive Sally's change
now, before you start working too heavily
in the same places.

It's time to use the svk merge command.
This command, it turns out, is a very close cousin to the
svk diff command (which you read about in
Chapter 3). Both commands are able to compare any two objects
in the repository and describe the differences. For example,
you can ask svk diff to show you the exact
change made by Sally in revision 82:

The output of svk merge shows that your
copy of integer.c was patched. It now
contains Sally's change—the change has been
“copied” from the trunk to your working copy of
your private branch, and now exists as a local modification.
At this point, it's up to you to review the local modification
and make sure it works correctly.

In another scenario, it's possible that things may not have
gone so well, and that integer.c may have
entered a conflicted state. You might need to resolve the
conflict using standard procedures (see Chapter 3), or if you
decide that the merge was a bad idea altogether, simply give up
and svk revert the local change.

But assuming that you've reviewed the merged change, you can
svk commit the change as usual. At that
point, the change has been merged into your repository branch.
In version control terminology, this act of copying changes
between branches is commonly called
porting changes.

When you commit the local modification, make sure your log
message mentions that you're porting a specific change from
one branch to another. For example:

In this particular case, yes, there really is no
difference. But svk merge has special
abilities that surpass the patch program.
The file format used by patch is quite
limited; it's only able to tweak file contents. There's no
way to represent changes to trees, such
as the addition, removal, or renaming of files and
directories. If Sally's change had, say, added a new
directory, the output of svk diff
wouldn't have mentioned it at all. svk
diff only outputs the limited patch-format, so
there are some ideas it simply can't express.
[15]
The svk merge command, however, can express
tree-changes by directly applying them to your working
copy.

A word of warning: while svk diff and
svk merge are very similar in concept, they
do have different syntax in many cases. Be sure to read about
them in Chapter 9 for details, or ask svk
help. For example, svk merge
requires a working-copy path as a target, i.e. a place where
it should apply the tree-changes. If the target isn't
specified, it assumes you are trying to perform one of the
following common operations:

You want to merge directory changes into your current
working directory.

You want to merge the changes in a specific file into
a file by the same name which exists in your current working
directory.

If you are merging a directory and haven't specified a
target path, svk merge assumes the first case
above and tries to apply the changes into your current
directory. If you are merging a file, and that file (or a file
by the same name) exists in your current working directory,
svk merge assumes the second case and tries
to apply the changes to a local file with the same name.

If you want changes applied somewhere else, you'll
need to say so. For example, if you're sitting in the parent
directory of your working copy, you'll have to specify the
target directory to receive the changes:

The Key Concept Behind Merging

You've now seen an example of the svk
merge command, and you're about to see several
more. If you're feeling confused about exactly how merging
works, you're not alone. Many users (especially those new
to version control) are initially perplexed about the proper
syntax of the command, and about how and when the feature
should be used. But fear not, this command is actually much
simpler than you think! There's a very easy technique for
understanding exactly how svk merge
behaves.

The main source of confusion is the
name of the command. The term
“merge” somehow denotes that branches are
combined together, or that there's some sort of mysterious
blending of data going on. That's not the case. A better
name for the command might have been svk
diff-and-apply, because that's all that happens:
two repository trees are compared, and the differences are
applied to a working copy.

The command takes three arguments:

An initial repository tree (often called the
left side of the
comparison),

An final repository tree (often called the
right side of the
comparison),

A working copy to accept the differences as
local changes (often called the target
of the merge).

Once these three arguments are specified, the two trees
are compared, and the resulting differences are applied to the
target working copy as local modifications. When the command
is done, the results are no different than if you had
hand-edited the files, or run various svk
add or svk delete commands
yourself. If you like the results, you can commit them. If
you don't like the results, you can simply svk
revert all of the changes.

The syntax of svk merge allows you to
specify the three necessary arguments rather flexibly. Here
are some examples:

The first syntax lays out all three arguments explictly,
naming each tree in the form URL@REV and
naming the working copy target. The second syntax can be used
as a shorthand for situations when you're comparing two
different revisions of the same URL. The last syntax shows
how the working-copy argument is optional; if omitted, it
defaults to the current directory.

Best Practices for Merging

Tracking Merges Manually

Merging changes sounds simple enough, but in practice it
can become a headache. The problem is that if you
repeatedly merge changes from one branch to another, you
might accidentally merge the same change
twice. When this happens, sometimes
things will work fine. When patching a file, Subversion
typically notices if the file already has the change, and
does nothing. But if the already-existing change has been
modified in any way, you'll get a conflict.

Ideally, your version control system should prevent the
double-application of changes to a branch. It should
automatically remember which changes a branch has already
received, and be able to list them for you. It should use
this information to help automate merges as much as
possible.

Unfortunately, Subversion is not such a system. Like
CVS, Subversion does not yet record any information about
merge operations. When you commit local modifications, the
repository has no idea whether those changes came from
running svk merge, or from just
hand-editing the files.

What does this mean to you, the user? It means that
until the day Subversion grows this feature, you'll have to
track merge information yourself. The best place to do this
is in the commit log-message. As demonstrated in the
earlier example, it's recommended that your log-message
mention a specific revision number (or range of revisions)
that are being merged into your branch. Later on, you can
run svk log to review which changes your
branch already contains. This will allow you to carefully
construct a subsequent svk merge command
that won't be redundant with previously ported
changes.

In the next section, we'll show some examples of this
technique in action.

Previewing Merges

Because merging only results in local modifications,
it's not usually a high-risk operation. If you get the
merge wrong the first time, simply svk
revert the changes and try again.

It's possible, however, that your working copy might
already have local modifications. The changes applied by a
merge will be mixed with your pre-existing ones, and running
svk revert is no longer an option. The
two sets of changes may be impossible to separate.

In cases like this, people take comfort in being able to
predict or examine merges before they happen. One simple
way to do that is to run svk diff with
the same arguments you plan to pass to svk
merge, as we already showed in our first example
of merging. Another method of previewing is to pass the
--dry-run option to the merge
command:

The --dry-run option doesn't actually
apply any local changes to the working copy. It only shows
status codes that would be printed in a
real merge. It's useful for getting a “high
level” preview of the potential merge, for those
times when running svk diff gives too
much detail.

Subversion and Changesets

Everyone seems to have a slightly different definition
of “changeset”, or at least a different
expectation of what it means for a version control system to
have “changeset features”. For our purpose,
let's say that a changeset is just a collection of changes
with a unique name. The changes might include textual edits
to file contents, modifications to tree structure, or tweaks
to metadata. In more common speak, a changeset is just a
patch with a name you can refer to.

In Subversion, a global revision number N names a tree
in the repository: it's the way the repository looked after
the Nth commit. It's also the name of an implicit
changeset: if you compare tree N with tree N-1, you can
derive the exact patch that was committed. For this reason,
it's easy to think of “revision N” as not just
a tree, but a changeset as well. If you use an issue
tracker to manage bugs, you can use the revision numbers to
refer to particular patches that fix bugs—for example,
“this issue was fixed by revision 9238.”.
Somebody can then run svk log -r9238 to
read about the exact changeset which fixed the bug, and run
svk diff -r9237:9238 to see the patch
itself. And Subversion's merge command also uses revision
numbers. You can merge specific changesets from one branch
to another by naming them in the merge arguments:
svk merge -r9237:9238 would merge
changeset #9238 into your working copy.

Merge Conflicts

Just like the svk update command,
svk merge applies changes to your working
copy. And therefore it's also capable of creating
conflicts. The conflicts produced by svk
merge, however, are sometimes different, and this
section explains those differences.

To begin with, assume that your working copy has no
local edits. When you svk update to a
particular revision, the changes sent by the server will
always apply “cleanly” to your working copy.
The server produces the delta by comparing two trees: a
virtual snapshot of your working copy, and the revision tree
you're interested in. Because the left-hand side of the
comparison is exactly equal to what you already have, the
delta is guaranteed to correctly convert your working copy
into the right-hand tree.

But svk merge has no such guarantees
and can be much more chaotic: the user can ask the server to
compare any two trees at all, even ones
that are unrelated to the working copy! This means there's
large potential for human error. Users will sometimes
compare the wrong two trees, creating a delta that doesn't
apply cleanly. svk merge will do its
best to apply as much of the delta as possible, but some
parts may be impossible. Just like the Unix
patch command sometimes complains about
“failed hunks”, svk merge
will complain about “skipped targets”:

In the previous example it might be the case that
baz.c exists in both snapshots of the
branch being compared, and the resulting delta wants to
change the file's contents, but the file doesn't exist in
the working copy. Whatever the case, the
“skipped” message means that the user is most
likely comparing the wrong two trees; they're the classic
sign of driver error. When this happens, it's easy to
recursively revert all the changes created by the merge
(svk revert --recursive), delete any
unversioned files or directories left behind after the
revert, and re-run svk merge with
different arguments.

Also notice that the previous example shows a conflict
happening on glorb.h. We already
stated that the working copy has no local edits: how can a
conflict possibly happen? Again, because the user can use
svk merge to define and apply any old
delta to the working copy, that delta may contain textual
changes that don't cleanly apply to a working file, even if
the file has no local modifications.

Another small difference between svk
update and svk merge are the
names of the full-text files created when a conflict
happens. In the section called “Resolve Conflicts (Merging Others' Changes)”, we saw
that an update produces files named
filename.mine,
filename.rOLDREV, and
filename.rNEWREV. When svk
merge produces a conflict, though, it creates
three files named filename.working,
filename.left, and
filename.right. In this case, the
terms “left” and “right” are
describing which side of the double-tree comparison the file
came from. In any case, these differing names will help you
distinguish between conflicts that happened as a result of an
update versus ones that happened as a result of a
merge.

Noticing or Ignoring Ancestry

When conversing with a Subversion developer, you might
very likely hear reference to the term
ancestry. This word is used to
describe the relationship between two objects in a
repository: if they're related to each other, then one
object is said to be an ancestor of the other.

For example, suppose you commit revision 100, which
includes a change to a file foo.c.
Then foo.c@99 is an
“ancestor” of foo.c@100.
On the other hand, suppose you commit the deletion of
foo.c in revision 101, and then add a
new file by the same name in revision 102. In this case,
foo.c@99 and
foo.c@102 may appear to be related
(they have the same path), but in fact are completely
different objects in the repository. They share no history
or “ancestry”.

The reason for bringing this up is to point out an
important difference between svk diff and
svk merge. The former command ignores
ancestry, while the latter command is quite sensitive to it.
For example, if you asked svk diff to
compare revisions 99 and 102 of foo.c,
you would see line-based diffs; the diff command is blindly
comparing two paths. But if you asked svk
merge to compare the same two objects, it would
notice that they're unrelated and first attempt to delete
the old file, then add the new file; you would see a
D foo.c followed by a A
foo.c.

Most merges involve comparing trees that are ancestrally
related to one another, and therefore svk
merge defaults to this behavior. Occasionally,
however, you may want the merge command to compare two
unrelated trees. For example, you may have imported two
source-code trees representing different vendor releases of
a software project (see the section called “”).
If you asked svk merge to compare the two
trees, you'd see the entire first tree being deleted,
followed by an add of the entire second tree!

In these situations, you'll want svk
merge to do a path-based comparison only, ignoring
any relations between files and directories. Add the
--ignore-ancestry option to your merge
command, and it will behave just like svk
diff. (And conversely, the
--notice-ancestry option will cause
svk diff to behave like the merge
command.)

Common Use-Cases

There are many different uses for branching and svk
merge, and this section describes the most common ones
you're likely to run into.

Merging a Whole Branch to Another

To complete our running example, we'll move forward in
time. Suppose several days have passed, and many changes have
happened on both the trunk and your private branch. Suppose
that you've finished working on your private branch; the
feature or bug fix is finally complete, and now you want to
merge all of your branch changes back into the trunk for
others to enjoy.

So how do we use svk merge in this
scenario? Remember that this command compares two trees, and
applies the differences to a working copy. So to receive the
changes, you need to have a working copy of the trunk. We'll
assume that either you still have your original one lying
around (fully updated), or that you recently checked out a
fresh working copy of /calc/trunk.

But which two trees should be compared? At first glance,
the answer may seem obvious: just compare the latest trunk
tree with your latest branch tree. But beware—this
assumption is wrong, and has burned many
a new user! Since svk merge operates like
svk diff, comparing the latest trunk and
branch trees will not merely describe
the set of changes you made to your branch. Such a comparison
shows too many changes: it would not only show the addition of
your branch changes, but also the removal
of trunk changes that never happened on your branch.

To express only the changes that happened on your branch,
you need to compare the initial state of your branch to its
final state. Using svk log on your branch,
you can see that your branch was created in revision 341. And
the final state of your branch is simply a matter of using the
HEAD revision. That means you want to
compare revisions 341 and HEAD of your
branch directory, and apply those differences to a working
copy of the trunk.

Tip

A nice way of finding the revision in which a branch was
created (the “base” of the branch) is to use the
--stop-on-copy option to svk
log. The log subcommand will normally show every
change ever made to the branch, including tracing back
through the copy which created the branch. So normally,
you'll see history from the trunk as well. The
--stop-on-copy will halt log output as soon
as svk log detects that its target was
copied or renamed.

Again, notice that the commit log message very
specifically mentions the range of changes that was merged
into the trunk. Always remember to do this, because it's
critical information you'll need later on.

For example, suppose you decide to keep working on your
branch for another week, in order to complete an enhancement
to your original feature or bug fix. The repository's
HEAD revision is now 480, and you're ready
to do another merge from your private branch to the trunk.
But as discussed in the section called “Best Practices for Merging”, you
don't want to merge the changes you've already merged before;
you only want to merge everything “new” on your
branch since the last time you merged. The trick is to figure
out what's new.

The first step is to run svk log on the
trunk, and look for a log message about the last time you
merged from the branch:

Aha! Since all branch-changes that happened between
revisions 341 and 405 were previously merged to the trunk as
revision 406, you now know that you want to merge only the
branch changes after that—by comparing revisions 406 and
HEAD.

Now the trunk contains the complete second wave of changes
made to the branch. At this point, you can either delete your
branch (we'll discuss this later on), or continue working on
your branch and repeat this procedure for subsequent
merges.

Undoing Changes

Another common use for svk merge is to
roll back a change that has already been committed. Suppose
you're working away happily on a working copy of
/calc/trunk, and you discover that the
change made way back in revision 303, which changed
integer.c, is completely wrong. It never
should have been committed. You can use svk
merge to “undo” the change in your
working copy, and then commit the local modification to the
repository. All you need to do is to specify a
reverse difference:

One way to think about a repository revision is as a
specific group of changes (some version control systems call
these changesets). By using the
-r switch, you can ask svk
merge to apply a changeset, or whole range of
changesets, to your working copy. In our case of undoing a
change, we're asking svk merge to apply
changeset #303 to our working copy
backwards.

Keep in mind that rolling back a change like this is just
like any other svk merge operation, so you
should use svk status and svk
diff to confirm that your work is in the state you
want it to be in, and then use svk commit
to send the final version to the repository. After
committing, this particular changeset is no longer reflected
in the HEAD revision.

Again, you may be thinking: well, that really didn't undo
the commit, did it? The change still exists in revision 303.
If somebody checks out a version of the
calc project between revisions 303 and
349, they'll still see the bad change, right?

Yes, that's true. When we talk about
“removing” a change, we're really talking about
removing it from HEAD. The original change
still exists in the repository's history. For most
situations, this is good enough. Most people are only
interested in tracking the HEAD of a
project anyway. There are special cases, however, where you
really might want to destroy all evidence of the commit.
(Perhaps somebody accidentally committed a confidential
document.) This isn't so easy, it turns out, because
Subversion was deliberately designed to never lose
information. Revisions are immutable trees which build upon
one another. Removing a revision from history would cause a
domino effect, creating chaos in all subsequent revisions and
possibly invalidating all working copies.
[16]

Resurrecting Deleted Items

The great thing about version control systems is that
information is never lost. Even when you delete a file or
directory, it may be gone from the HEAD
revision, but the object still exists in earlier revisions.
One of the most common questions new users ask is, “How
do I get my old file or directory back?”

The first step is to define exactly which item you're trying to resurrect.
Here's a useful metaphor: you can think of every object in the
repository as existing in a sort of two-dimensional coordinate
system. The first coordinate is a particular revision tree,
and the second coordinate is a path within that tree. So
every version of your file or directory can be defined by a
specific coordinate pair.

Subversion has no Attic directory
like CVS does,
[17]
so you need to use svk
log to discover the exact coordinate pair you wish
to resurrect. A good strategy is to run svk log
--verbose in a directory which used to contain your
deleted item. The --verbose option shows a
list of all changed items in each revision; all you need to do
is find the revision in which you deleted the file or
directory. You can do this visually, or by using another tool
to examine the log output (via grep, or
perhaps via an incremental search in an editor).

In the example, we're assuming that you're looking for a
deleted file real.c. By looking through
the logs of a parent directory, you've spotted that this file
was deleted in revision 808. Therefore, the last version of
the file to exist was in the revision right before that.
Conclusion: you want to resurrect the path
/calc/trunk/real.c from revision
807.

That was the hard part—the research. Now that you
know what you want to restore, you have two different
choices.

One option is to use svk merge to apply
revision 808 “in reverse”. (We've already
discussed how to undo changes, see the section called “Undoing Changes”.) This would have the effect of
re-adding real.c as a local modification.
The file would be scheduled for addition, and after a commit,
the file would again exist in HEAD.

In this particular example, however, this is probably not
the best strategy. Reverse-applying revision 808 would not
only schedule real.c for addition, but
the log message indicates that it would also undo certain
changes to integer.c, which you don't
want. Certainly, you could reverse-merge revision 808 and
then svk revert the local modifications to
integer.c, but this technique doesn't
scale well. What if there were 90 files changed in revision
808?

A second, more targeted strategy is not to use
svk merge at all, but rather the
svk copy command. Simply copy the exact
revision and path “coordinate pair” from the
repository to your working copy:

The plus sign in the status output indicates that the item
isn't merely scheduled for addition, but scheduled for
addition “with history”. Subversion remembers
where it was copied from. In the future, running svk
log on this file will traverse back through the
file's resurrection and through all the history it had prior
to revision 807. In other words, this new
real.c isn't really new; it's a direct
descendant of the original, deleted file.

Although our example shows us resurrecting a file, note
that these same techniques work just as well for resurrecting
deleted directories.

Common Branching Patterns

Version control is most often used for software
development, so here's a quick peek at two of the most common
branching/merging patterns used by teams of programmers. If
you're not using Subversion for software development, feel
free to skip this section. If you're a software developer
using version control for the first time, pay close attention,
as these patterns are often considered best practices by
experienced folk. These processes aren't specific to
Subversion; they're applicable to any version control system.
Still, it may help to see them described in Subversion
terms.

Release Branches

Most software has a typical lifecycle: code, test,
release, repeat. There are two problems with this process.
First, developers need to keep writing new features while
quality-assurance teams take time to test supposedly-stable
versions of the software. New work cannot halt while the
software is tested. Second, the team almost always needs to
support older, released versions of software; if a bug is
discovered in the latest code, it most likely exists in
released versions as well, and customers will want to get
that bugfix without having to wait for a major new
release.

Here's where version control can help. The typical
procedure looks like this:

Developers commit all new work to the
trunk.
Day-to-day changes are committed to
/trunk: new features, bugfixes, and
so on.

The trunk is copied to a
“release” branch.
When the team thinks the software is ready for release
(say, a 1.0 release), then /trunk
might be copied to
/branches/1.0.

Teams continue to work in parallel.
One team begins rigorous testing of the release branch,
while another team continues new work (say, for version
2.0) on /trunk. If bugs are
discovered in either location, fixes are ported back and
forth as necessary. At some point, however, even that
process stops. The branch is “frozen” for
final testing right before a release.

The branch is tagged and released.
When testing is complete,
/branches/1.0 is copied to
/tags/1.0.0 as a reference
snapshot. The tag is packaged and released to
customers.

The branch is maintained over time.
While work continues on /trunk for
version 2.0, bugfixes continue to be ported from
/trunk to
/branches/1.0. When enough
bugfixes have accumulated, management may decide to do a
1.0.1 release: /branches/1.0 is
copied to /tags/1.0.1, and the tag
is packaged and released.

This entire process repeats as the software matures:
when the 2.0 work is complete, a new 2.0 release branch is
created, tested, tagged, and eventually released. After
some years, the repository ends up with a number of release
branches in “maintenance” mode, and a number
of tags representing final shipped versions.

Feature Branches

A feature branch is the sort of
branch that's been the dominant example in this chapter, the
one you've been working on while Sally continues to work on
/trunk. It's a temporary branch
created to work on a complex change without interfering with
the stability of /trunk. Unlike
release branches (which may need to be supported forever),
feature branches are born, used for a while, merged back to
the trunk, then ultimately deleted. They have a finite span
of usefulness.

Again, project policies vary widely concerning exactly
when it's appropriate to create a feature branch. Some
projects never use feature branches at all: commits to
/trunk are a free-for-all. The
advantage to this system is that it's simple—nobody
needs to learn about branching or merging. The disadvantage
is that the trunk code is often unstable or unusable. Other
projects use branches to an extreme: no change is
ever committed to the trunk directly.
Even the most trivial changes are created on a short-lived
branch, carefully reviewed and merged to the trunk. Then
the branch is deleted. This system guarantees an
exceptionally stable and usable trunk at all times, but at
the cost of tremendous process overhead.

Most projects take a middle-of-the-road approach. They
commonly insist that /trunk compile and
pass regression tests at all times. A feature branch is
only required when a change requires a large number of
destabilizing commits. A good rule of thumb is to ask this
question: if the developer worked for days in isolation and
then committed the large change all at once (so that
/trunk were never destabilized), would
it be too large a change to review? If the answer to that
question is “yes”, then the change should be
developed on a feature branch. As the developer commits
incremental changes to the branch, they can be easily
reviewed by peers.

Finally, there's the issue of how to best keep a feature
branch in “sync” with the trunk as work
progresses. As we mentioned earlier, there's a great risk
to working on a branch for weeks or months; trunk changes
may continue to pour in, to the point where the two lines of
development differ so greatly that it may become a nightmare
trying to merge the branch back to the trunk.

This situation is best avoided by regularly merging
trunk changes to the branch. Make up a policy: once a week,
merge the last week's worth of trunk changes to the branch.
Take care when doing this; the merging needs to be
hand-tracked to avoid the problem of repeated merges (as
described in the section called “Tracking Merges Manually”). You'll
need to write careful log messages detailing exactly which
revision ranges have been been merged already (as
demonstrated in the section called “Merging a Whole Branch to Another”). It
may sound intimidating, but it's actually pretty easy to
do.

At some point, you'll be ready to merge the
“synchronized” feature branch back to the
trunk. To do this, begin by doing a final merge of the
latest trunk changes to the branch. When that's done, the
latest versions of branch and trunk will be absolutely
identical except for your branch changes. So in this
special case, you would merge by comparing the branch with
the trunk:

By comparing the HEAD revision of the
trunk with the HEAD revision of the
branch, you're defining a delta that describes only the
changes you made to the branch; both lines of development
already have all of the trunk changes.

Another way of thinking about this pattern is that your
weekly sync of trunk to branch is analogous to running
svk update in a working copy, while the
final merge step is analogous to running svk
commit from a working copy. After all, what else
is a working copy but a very shallow
private branch? It's a branch that's only capable of
storing one change at a time.

Switching a Working Copy

The svk switch command transforms an
existing working copy into a different branch. While this
command isn't strictly necessary for working with branches, it
provides a nice shortcut to users. In our earlier example,
after creating your private branch, you checked out a fresh
working copy of the new repository directory. Instead, you can
simply ask Subversion to change your working copy of
/calc/trunk to mirror the new branch
location:

After “switching” to the branch, your working
copy is no different than what you would get from doing a fresh
checkout of the directory. And it's usually more efficient to
use this command, because often branches only differ by a small
degree. The server sends only the minimal set of changes
necessary to make your working copy reflect the branch
directory.

The svk switch command also takes a
--revision (-r) option, so you
need not always move your working copy to the “tip”
of the branch.

Of course, most projects are more complicated than our
calc example, containing multiple
subdirectories. Subversion users often follow a specific
algorithm when using branches:

Copy the project's entire “trunk” to a
new branch directory.

Switch only part of the trunk
working copy to mirror the branch.

In other words, if a user knows that the branch-work only
needs to happen on a specific subdirectory, they use
svk switch to move only that subdirectory to
the branch. (Or sometimes users will switch just a single
working file to the branch!) That way, they can continue to
receive normal “trunk” updates to most of their
working copy, but the switched portions will remain immune
(unless someone commits a change to their branch). This feature
adds a whole new dimension to the concept of a “mixed
working copy”—not only can working copies contain a
mixture of working revisions, but a mixture of repository
locations as well.

If your working copy contains a number of switched subtrees
from different repository locations, it continues to function as
normal. When you update, you'll receive patches to each subtree
as appropriate. When you commit, your local changes will still
be applied as a single, atomic change to the repository.

Note that while it's okay for your working copy to reflect a
mixture of repository locations, these locations must all be
within the same repository. Subversion
repositories aren't yet able to communicate with one another;
that's a feature planned beyond Subversion
1.0.[18]

Switches and Updates

Have you noticed that the output of svk
switch and svk update look the
same? The switch command is actually a superset of the
update command.

When you run svk update, you're asking
the repository to compare two trees. The repository does so,
and then sends a description of the differences back to the
client. The only difference between svk
switch and svk update is that the
update command always compares two identical paths.

That is, if your working copy is a mirror of
/calc/trunk, then svk
update will automatically compare your working copy
of /calc/trunk to
/calc/trunk in the
HEAD revision. If you're switching your
working copy to a branch, then svk switch
will compare your working copy of
/calc/trunk to some
other branch-directory in the
HEAD revision.

In other words, an update moves your working copy through
time. A switch moves your working copy through time
and space.

Because svk switch is essentially a
variant of svk update, it shares the same
behaviors; any local modifications in your working copy are
preserved when new data arrives from the repository. This
allows you to perform all sorts of clever tricks.

For example, suppose you have a working copy of
/calc/trunk and make a number of changes to
it. Then you suddenly realize that you meant to make the
changes to a branch instead. No problem! When you svk
switch your working copy to the branch, the local
changes will remain. You can then test and commit them to the
branch.

Tags

Another common version control concept is a
tag. A tag is just a
“snapshot” of a project in time. In Subversion,
this idea already seems to be everywhere. Each repository
revision is exactly that—a snapshot of the filesystem
after each commit.

However, people often want to give more human-friendly names
to tags, like release-1.0. And they want to
make snapshots of smaller subdirectories of the filesystem.
After all, it's not so easy to remember that release-1.0 of a
piece of software is a particular subdirectory of revision
4822.

Creating a Simple Tag

Once again, svk copy comes to the
rescue. If you want to create a snapshot of
/calc/trunk exactly as it looks in the
HEAD revision, then make a copy of it:

This example assumes that a
/calc/tags directory already exists. (If it
doesn't, see svk mkdir).
After the copy completes, the new
release-1.0 directory is forever a
snapshot of how the project looked in the
HEAD revision at the time you made the
copy. Of course you might want to be more precise about
exactly which revision you copy, in case somebody else may
have committed changes to the project when you weren't
looking. So if you know that revision 350 of
/calc/trunk is exactly the snapshot you
want, you can specify it by passing -r 350 to
the svk copy command.

But wait a moment: isn't this tag-creation procedure the
same procedure we used to create a branch? Yes, in fact, it
is. In Subversion, there's no difference between a tag and a
branch. Both are just ordinary directories that are created
by copying. Just as with branches, the only reason a copied
directory is a “tag” is because
humans have decided to treat it that way:
as long as nobody ever commits to the directory, it forever
remains a snapshot. If people start committing to it, it
becomes a branch.

If you are administering a repository, there are two
approaches you can take to managing tags. The first approach
is “hands off”: as a matter of project policy,
decide where your tags will live, and make sure all users know
how to treat the directories they copy in there. (That is,
make sure they know not to commit to them.) The second
approach is more paranoid: you can use one of the
access-control scripts provided with Subversion to prevent
anyone from doing anything but creating new copies in the
tags-area (See Chapter 6, Server Configuration.) The paranoid
approach, however, isn't usually necessary. If a user
accidentally commits a change to a tag-directory, you can
simply undo the change as discussed in the previous section.
This is version control, after all.

Creating a Complex Tag

Sometimes you may want your “snapshot” to be
more complicated than a single directory at a single
revision.

For example, pretend your project is much larger than our
calc example: suppose it contains a
number of subdirectories and many more files. In the course
of your work, you may decide that you need to create a working
copy that is designed to have specific features and bug fixes.
You can accomplish this by selectively backdating files or
directories to particular revisions (using svk update
-r liberally), or by switching files and directories
to particular branches (making use of svk
switch). When you're done, your working copy is a
hodgepodge of repository locations from different revisions.
But after testing, you know it's the precise combination of
data you need.

Time to make a snapshot. Copying one URL to another won't
work here. In this case, you want to make a snapshot of your
exact working copy arrangement and store it in the repository.
Luckily, svk copy actually has four
different uses (which you can read about in Chapter 9),
including the ability to copy a working-copy tree to the
repository:

Now there is a new directory in the repository,
/calc/tags/mytag, which is an exact
snapshot of your working copy—mixed revisions, URLs,
and all.

Other users have found interesting uses for this feature.
Sometimes there are situations where you have a bunch of local
changes made to your working copy, and you'd like a
collaborator to see them. Instead of running svk
diff and sending a patch file (which won't capture
tree changes), you can instead use svk copy
to “upload” your working copy to a private area
of the repository. Your collaborator can then either checkout
a verbatim copy of your working copy, or use svk
merge to receive your exact changes.

Branch Maintenance

You may have noticed by now that Subversion is extremely
flexible. Because it implements branches and tags with the same
underlying mechanism (directory copies), and because branches
and tags appear in normal filesystem space, many people find
Subversion intimidating. It's almost too
flexible. In this section, we'll offer some suggestions for
arranging and managing your data over time.

Repository Layout

There are some standard, recommended ways to organize a
repository. Most people create a trunk
directory to hold the “main line” of development,
a branches directory to contain branch
copies, and a tags directory to contain
tag copies. If a repository holds only one project, then
often people create these top-level directories:

/trunk
/branches
/tags

If a repository contains multiple projects, admins
typically index their layout by project (see the section called “” to read more about
“project roots”):

Of course, you're free to ignore these common layouts.
You can create any sort of variation, whatever works best for
you or your team. Remember that whatever you choose, it's not
a permanent commitment. You can reorganize your repository at
any time. Because branches and tags are ordinary directories,
the svk move command can move or rename
them however you wish. Switching from one layout to another
is just a matter of issuing a series of server-side moves; if
you don't like the way things are organized in the repository,
just juggle the directories around.

Remember, though, that while moving directories may be
easy to do, you need to be considerate of your users as well.
Your juggling can be disorienting to users with existing
working copies. If a user has a working copy of a particular
repository directory, your svk move
operation might remove the path from the latest revision.
When the user next runs svk update, they'll
be told that their working copy represents a path that no
longer exists, and the user will be forced to svk
switch to the new location.

Data Lifetimes

Another nice feature of Subversion's model is that
branches and tags can have finite lifetimes, just like any
other versioned item. For example, suppose you eventually
finish all your work on your personal branch of the
calc project. After merging all of your
changes back into /calc/trunk, there's
no need for your private branch directory to stick around
anymore:

And now your branch is gone. Of course it's not really
gone: the directory is simply missing from the
HEAD revision, no longer distracting
anyone. If you use svk checkout,
svk switch, or svk list
to examine an earlier revision, you'll still be able to see
your old branch.

If browsing your deleted directory isn't enough, you can
always bring it back. Resurrecting data is very easy in
Subversion. If there's a deleted directory (or file) that
you'd like to bring back into HEAD, simply
use svk copy -r to copy it from the old
revision:

In our example, your personal branch had a relatively
short lifetime: you may have created it to fix a bug or
implement a new feature. When your task is done, so is the
branch. In software development, though, it's also common to
have two “main” branches running side-by-side for
very long periods. For example, suppose it's time to release
a stable calc project to the public, and
you know it's going to take a couple of months to shake bugs
out of the software. You don't want people to add new
features to the project, but you don't want to tell all
developers to stop programming either. So instead, you create
a “stable” branch of the software that won't
change much:

And now developers are free to continue adding
cutting-edge (or experimental) features to
/calc/trunk, and you can declare a
project policy that only bug fixes are to be committed to
/calc/branches/stable-1.0. That is, as
people continue to work on the trunk, a human selectively
ports bug fixes over to the stable branch. Even after the
stable branch has shipped, you'll probably continue to
maintain the branch for a long time—that is, as long
as you continue to support that release for customers.

Summary

We've covered a lot of ground in this chapter. We've
discussed the concepts of tags and branches, and demonstrated
how Subversion implements these concepts by copying directories
with the svk copy command. We've shown how
to use svk merge to copy changes from one
branch to another, or roll back bad changes. We've gone over
the use of svk switch to create
mixed-location working copies. And we've talked about how one
might manage the organization and lifetimes of branches in a
repository.

Remember the Subversion mantra: branches and tags are cheap.
So use them liberally!

[14] SVK does not support
cross-depot copying. When using DEPOTPATHs with svk
copy or svk move, you can only
copy items within the same depot.

[15] In the future, the Subversion project plans to use
(or invent) an expanded patch format that describes
tree-changes.

[16] The Subversion project has plans, however, to someday
implement an svnadmin obliterate
command that would accomplish the task of permanently
deleting information. In the meantime, see the section called “” for a possible
workaround.

[17] Because CVS doesn't version trees, it creates an
Attic area within each repository
directory as a way of remembering deleted files.

[18] You can, however, use
svk switch with the
--relocate switch if the URL of your server
changes and you don't want to abandon an existing working copy.
See the svk switch section in Chapter 9, SVK Complete Reference for more information and an example.

This chapter is intended to be a complete reference to using
the command svk line client and all its
subcommands.

The SVK Command Line Client:
svk

To use the command line client, you type
svk, the subcommand you wish to use
[19], and any switches or targets that
you wish to operate on—the switches always come after the
subcommand that they apply to. There are no global switches to
svk, with the exception of the
--help (-h) switch, which will
give you help for a particular subcommand.

svk Switches

While SVK has different switches for its
subcommands, all switches are global[20]—that is, each switch is
guaranteed to mean the same thing regardless of the subcommand
you use it with. For example, --verbose
(-v) always means “verbose
output”, regardless of the subcommand you use it
with.

You can specify a command line switch anywhere on the
command line after the name of the subcommand itself. So it's
OK to mix switches and options. SVK knows what is
what.

--all (-a)

Causes SVK to operate on all instances of a
particular kind. It depends on the subcommand what
exactly this means.

--auto (-a)

Requests svk uses the previous merge point as the
starting point for this cmerge or merge operation.

--base (-b)
REV[@]

Use REV[@] as the merge base.
See the --revision for an explanation
of valid values for REV[@].

--baseless (-B)

Use the youngest revision as the merge base.

--change (-c)
[-]REV[@]

Act on the change made by revision
[-]REV[@]. Specifying an
@ after the revision number will
cause SVK to operate on the mirrored repository's
revision number rather than the local depots revision
number if the path being operated on is a mirrored path.
Specifying REV is the same
as --revision REV-1:REV, whereas
specifying -REV is equivalent
to --revision REV:REV-1.

--check-only (-C)

Goes through all the motions of running a command,
but makes no actual changes—either on disk or in
the depot.

--cross (-x)

Causes a SVK subcommand which is traversing the
history of a versioned resource to continue harvesting
that historical information when a copy—that is, a
location in history where that resource was copied from
another location in the repository—is
encountered.

--depotDEPOTNAME

Apply the svk patch operation to
the depot specified by
DEPOTNAME.

--depth (-d)
LEVEL

Recurse at most LEVEL
levels deep. This is used together with the
--recursive switch to svk
list.

--detach (-d)
[DEPOTPATH | PATH]

Request that SVK forget about a depot, mirror or
working copy.

--direct

Commit directly even if the path is mirrored.

Warning

Don't ever use this option unless you know what
you are doing. Better yet don't use this option
unless your IRC handle is clkao.

--encodingENC

Tells SVK that your commit message is encoded
in the charset provided. The default is your operating
system's native locale, and you should specify the
encoding if your commit message is in any other
encoding.

--export

Export mode, checkout a detached copy.

--file (-F)
FILENAME

Uses the contents of the file passed as an argument
to this switch for the specified subcommand.

--from (-f)

Merges or pushes from the specified
PATH.

--from-checkout (-f)

Allows a svk import to be run on
a working copy.

--full-path (-f)

Shows the full path of listed files rather than
showing files and directories as a tree.

--help (-h or
-?)

If used with one or more subcommands, shows the
built-in help text for each subcommand. If used alone,
it displays the general client help text.

--hostHOST

Use HOST as the hostname
shown in the merge log.

--import

Import mode. Automatically add any new nodes and
delete any missing ones. This switch is used with the
commit command. An example of how it could be used to
track a third party product is:

Generate a commit log message consisting of all the
log messages of the revision being merged.

--lump (-l)

When causes the svk push and
svk pull commands to lump all the
changes together in a single commit, rather than commit
each change incrementally when calling svk
smerge.

--merge (-m)

If the depotpath for the working copy being updated
is a copy of another depotpath—i.e. a branch,
perform a svk smerge --log --message ''
from the original to the copy before executing the
actual command.

--message (-m)
MESSAGE

Indicates that you will specify a commit message
on the command line, following this switch. For
example:

$ svk commit --message "They don't make Sunday."

--parent (-p)

Recursively create intermediate directories in the
depot as required.

--patch (-P)
NAME

Rather than committing a change SVK will generate a
patch named NAME. The name
- will cause svk to output the
patch the standard output rather than storing it.

--non-recursive (-N)

Stops a subcommand from recursing into
subdirectories. Most subcommands recurse by default,
but some subcommands—usually those that have the
potential to remove or undo your local
modifications—do not.

--no-ignore

Do not ignore files that would normally be
ignored.

--no-ticket

Indicates that you do not with this merge point to
be recorded for merge tracking purposes.

--quiet (-q)

Requests that the client print only essential
information while performing an operation.

--recover

Recover the state of a mirrored depot path.

--recursive (-R)

Makes a subcommand recurse into subdirectories.
Most subcommands recurse by default.

--relocate[FROM] TO

Used with the svk mirror
subcommand, changes the location of the remote
repository that the mirror in a local depot references.
This is useful if the location of your repository
changes and you have an existing mirror that you'd
like to continue to use. See svk
mirror for an example.

Used with the svk checkout to
move a working copy to a different location.

Used with the svk depotmap to
move a depot to a different location.

--remoterev

Makes a generated merge log use revision numbers
from the remote mirror rather than those in the
depot.

--revision (-r)
REV[@]:[REV2[@]]

Indicates that you're going to supply a revision (or
range of revisions) for a particular operation. You can
provide revision numbers, revision keywords or dates (in
curly braces), as arguments to the revision switch. If
you wish to provide a range of revisions, you can
provide two revisions separated by a colon. For
example:

If the path for which you specified
REV is a mirrored path, you may
append an @ to then end of the
REV to refer to the revision
number in the remote mirror rather than the one in the
local depot. For example:

Operates on a revision property instead of a
property specific to a file or directory. This switch
requires that you also pass a revision with the
--revision (-r)
switch. See the section called “”
for more details on unversioned properties.

--sign (-S)

Causes SVK to use sign the change being
committed.

--skipto (-s) REMOTEREV

During svk sync will start
mirroring from the remote repositories revision
REMOTEREV, rather than the
first not yet mirrored revision.

--strict

Causes SVK to use strict semantics, a notion
which is rather vague unless talking about specific
subcommands.

--summarize (-s)

Causes svk diff to show a status
like summary of changes rather than the actual
diffs.

--sync (-s)

Synchronize with mirrored sources before starting
the operation.

--template

Used together with the --message
(-m) or the --file
(-F) switch, it uses the specified
message as a template to edit rather than as the actual
commit message.

--to (-t)

Merges to the specified
PATH.

--to-checkout (-t)

Request that a tree on which svk import
is run be turned into a working copy immediately

--torev (-t) REMOTEREV

During svk sync will mirror up to
the specified remote repositories revision
REMOTEREV, rather than
HEAD.

--track-rename

Requests that SVK track changes made to renamed
nodes and do the right thing when this occurs.

--unlock

Forcibly remove a stale lock on a mirror.

--upgrade

Upgrade a mirror to the latest version.

--verbatim

Produces a verbatim merge log without any indents or
headers.

--verbose (-v)

Requests that the client print out as much
information as it can while running any subcommand.
This may result in SVK printing out additional
fields, detailed information about every file, or
additional information regarding its actions.

--version

Prints the client version info.

svk Subcommands

Name

svk add — Add files, directories, or symbolic links.

Synopsis

svk add PATH...

Description

Add files, directories, or symbolic links to your
working copy and schedule them for addition to the
repository. They will be uploaded and added to the
repository on your next commit. If you add something and
change your mind before committing, you can unschedule the
addition using svk revert.

Alternate Names

None

Changes

Working Copy

Accesses Depot

No

Accesses Mirrored Repository

No

Switches

--non-recursive (-N)
--quiet (-q)

Examples

To add a file to your working copy:

$ svk add foo.c
A foo.c

When adding a directory, the default behavior of
svk add is to recurse:

$ svk add testdir
A testdir
A testdir/a
A testdir/b
A testdir/c
A testdir/d

You can add a directory without adding its
contents:

$ svk add --non-recursive otherdir
A otherdir

The command svk add *
will even recurse down into directories that are already
under version control, looking for unversioned objects
deeper down in the tree.

$ svk add *
A foo.c
A somedir/bar.c
A otherdir/docs/baz.doc
…

Name

svk admin — Administration tools.

Synopsis

Name

svk annotate — Show author and revision information in-line
for the specified files or URLs.

Synopsis

svk annotate TARGET[@REV[@]]...

Description

Show author and revision information in-line for the
specified files or URLs. Each line of text is annotated
at the beginning with the author (username) and the
revision number for the last change to that line.

Alternate Names

ann, blame, praise

Changes

Nothing

Accesses Depot

Yes

Accesses Mirrored Repository

No

Switches

--revision (-r) REV[@]
--cross (-x)

Examples

If you want to see annotated source for
readme.txt in your test
depot:

By default svk annotate will not
look further back than the closest copy. If you wish to
see the entire history of the file including who changed
what before the copy use the --cross
switch. In particular if you are running annotate on a
branched or tagged revision of a file you might want to
see it history back beyond the copy:

Name

Synopsis

Description

Output the contents of the specified files or URLs.
For listing the contents of directories, see svk
list.

Alternate Names

None

Changes

Nothing

Accesses Depot

Yes

Accesses Mirrored Repository

No

Switches

--revision (-r) REV[@]

Examples

If you want to view readme.txt in your depot
without checking it out:

$ svk cat //test/readme.txt
This is a README file.
You should read this.

Tip

If your working copy is out of date (or you have
local modifications) and you want to see the
HEAD revision of a file in your
working copy, svk cat will
automatically fetch the HEAD revision
when you give it a path:

$ cat foo.c
This file is in my local working copy
and has changes that I've made.
$ svk cat foo.c
Latest revision fresh from the repository!

Name

svk checkout — Check out a working copy from a repository.

Synopsis

svk checkout DEPOTPATH[@REV[@]] [PATH]

svk checkout URL [PATH]

svk checkout --list

svk checkout --relocate DEPOTPATH|PATH PATH

svk checkout --detach [DEPOTPATH|PATH]

svk checkout --purge

Description

Check out a working copy from a repository. If
PATH is omitted, the
basename of the DEPOTPATH will be used as the
destination.

Using the second form, svk will setup a mirror of the
specified URL if you don't have one already, sync the
mirror and checkout a working copy from the mirror.

Warning

Unlike Subversion or CVS, SVK working copies do not
contain any administrative files or directories. This
means things like diff -r and
find work great on SVK working
copies. However because of this it's not possible to
simply rename an svk working copy or remove it without
telling svk about it. SVK keeps the metadata
associated with a working copy inside your
$SVKROOT (which defaults to
~/.svk). Because of this you need to
use the commands listed here to manage working
copies.

With the --list switch, output one
line per checked out working copy. Each line consists of
the depotpath followed by an absolute path to the working
copy.

If you wish to change the location of a checked out
working copy you need to use the svk
checkout with the --relocate.
Give it both the old and the new path to the working copy.
Either before or after that you should move the working
copy to it's new location so SVK can find it.

Once you are done using a working copy you should tell
svk this since it keeps track of all checked out working
copies. To do so you would run svk
checkout with the --detach
switch. This lets SVK know it no longer needs to keep
track of this particular working copy. This command does
not actually remove the working copy from disk. That's
still your job.

Tip

If you want to create a working copy that svk
doesn't track at all you can use the
--export switch to the svk
checkout command.

If you accidentally remove a working copy or working
copies that svk was tracking for you, running svk
checkout with the --purge
switch will prompt svk to forget about each working copy
it can no longer find on disk.

Examples

This command is deprecated until subversion itself is
fixed use svk merge --change instead.

Name

svk commit — Send changes from your working copy to the repository.

Synopsis

svk commit [PATH...]

Description

Send changes from your working copy to the
repository. If you do not supply a log message with your
commit by using either the --file or
--message switch,
svk will launch your editor for you
to compose a commit message. See the
editor-cmd section in the section called “”.

Tip

If you begin a commit and SVK launches your
editor to compose the commit message, you can still
abort without committing your changes. If you want to
cancel your commit, just quit your editor without saving
your commit message and Subversion will prompt you to
either abort the commit, continue with no message, or
edit the message again.

Tip

Sometimes you may wish only to commit a subset of
the changes in a working copy. For example in the case
above let's assume you wish to only commit the change to
integer.c. You would edit the buffer
to look like:

When you save the commit message and exit the
editor, SVK will only commit the files still listed
below the === Targets to commit (you may delete
items from it) === line in the commit
message.

Name

svk copy — Copy a file or directory in a working copy or
in a depot.

Synopsis

svk copy src [DST]

Description

Copy a file or directory in a working copy or in the
repository. src and
DST can each be either a
working copy (WC) path or a depot path. In addition
src can also be a URL:

WC -> WC

Copy and schedule an item for
addition (with history).

WC -> DEPOTPATH

Immediately commit a copy of WC to DEPOTPATH.

Warning

Although svk supports having mixed revision
working copies, for example by backreving
certain files or directories with a svk
update --revision, creating a copy of
such a mixed revision working copy using this
form of the svk copy command
will not create a mixed revision tag or branch.
Instead it creates a tag or branch which is a
copy of the same revision that the
WC path specified is
at without regard to the revisions of any
subdirectories or files.

DEPOTPATH

If the current directory is inside a working
copy, check out DEPOTPATH into the current
directory, and schedule it for addition.
Otherwise prompt for a destination depot path to
copy to.

DEPOTPATH -> WC

Check out DEPOTPATH into WC, and schedule it
for addition.

DEPOTPATH -> DEPOTPATH

Complete in depot copy. This is usually used
to branch and tag.

URL

Interactively sets up a mirror of URL if you
do not have one already. After the optional setup of
the mirror, creates a local copy of the mirror in
DEPOTPATH, finally checks out that local branch in
a new working copy using the basename of the local
copy. See svk mirror
for more information on valid
URL values.

URL -> PATH

Interactively sets up a mirror of URL if you
do not have one already. After the optional setup
of the mirror, prompts for a DEPOTPATH to create
a local copy of the mirror in, finally checks out
that local branch in a new working copy called
PATH.

URL -> DEPOTPATH

Interactively sets up a mirror of URL if you
do not have one already. After the optional setup
of the mirror, creates a local copy of the mirror
in DEPOTPATH.

Note

You can only copy files within a single depot.
SVK does not support cross-depot copying.

Tip

It is possible to copy files from one mirrored
repository to another, if both mirrors live inside the
same depot. This allows you to copy with history
between different mirrored repositories.

Alternate Names

cp

Changes

Depot if destination is a DEPOT or source is a URL.

Working copy if destination is a WC path.

Creates a working copy if source is a URL.

Accesses Depot

If source or destination is in the depot, or if needed
to look up the source revision number.

Accesses Mirrored Repository

If destination is in the depot at a mirrored path or
if the source is a URL which isn't yet being
mirrored.

Name

svk delete — Delete an item from a working copy
or a depot.

Synopsis

svk delete PATH...

svk delete DEPOTPATH

Description

Items specified by PATH are
scheduled for deletion upon the next commit. Files (and
directories that have not been committed) are immediately
removed from the working copy. The command will not
remove any modified items or items scheduled for addition;
use the svk revert first for
those.

Items specified by DEPOTPATH are deleted from the
repository via an immediate commit. Multiple DEPOTPATHS
are currently not supported.

Alternate Names

del, remove, rm

Changes

Working copy if operating on files, Depot if
operating on a DEPOTPATH, Mirrored repository if operation
on a mirrored DEPOTPATH

Name

Synopsis

depotmap

depotmap DEPOTNAME REPOPATH

depotmap --list

depotmap --detach [DEPOTNAME|REPOPATH]

depotmap --relocate [DEPOTNAME|REPOPATH] REPOPATH2

Description

The first form will launch you preferred editor and
show you a list of DEPOTNAME:
REPOPATH mappings. You can add or remove
new mappings in your editor, rename depots, or move where
the repository for a depot is—it won't move it but
you can update the location in the depotmap after you have
moved the repository yourself. After you save the depotmap
and exit the editor svk will ask you to create
repositories for each of the new depot entries you have
made.

The second form will display a list of depotname and
corresponding repository location pairs.

The third form will remove the specified depot from
the depotname to repository path mappings. However it will
not delete the repository that the depot referred
to.

The fourth form allows you to let svk know you moved
the repository for a depot to a new location.

Note that in all the examples above you could use
plain tmp instead of
/tmp/ to refer to the depot as
well.

Name

svk describe — Describe a change

Synopsis

svk describe REV [TARGET]

Description

Given DEPOT is the root of
the depot containing TARGET or
the depot for the current working copy if
TARGET isn't specified. This
command is equivalent to running
svk log --revision REV DEPOT followed by
svk diff --revision REV-1:REV DEPOT

Alternate Names

desc

Changes

Nothing

Accesses Depot

Yes

Accesses Mirrored Repository

No

Switches

None

Examples

Show what exactly changed and why at revision 10 in
the depot for the current working copy:

Name

Synopsis

Description

Display the differences between two paths. The four
different ways you can use svk diff
are:

svk diff [--revision REV[@]] [PATH...]
displays the differences between each file or directory
specified in the working copy, if none are specified
. is implied, with the
BASE or
REV (if it's specified)
revision of that file in the depot

svk diff --revision REV1[@]:REV2[2] DEPOTPATH|PATH...
displays the differences between
REV1 and
REV2 of the DEPOTPATH
specified, or of each file or directory specified in the
working copy.

svk diff DEPOTPATH1 DEPOTPATH2
shows the differences between 2 depot paths—this is
useful for displaying the difference between branches or
tags.

svk diff DEPOTPATH [PATH]
shows the differences between the current working copy (or
the PATH directory and the
contents of DEPOTPATH.

Running svk diff ignores the
ancestry of files and merely compares the contents of the
two files being compared.

After importing data, note that the original tree is
not under version control. If you
wish to use the original tree as a working copy right away
you need to specify the --to-checkout
switch to import. Alternatively you can
svk checkout a fresh working copy of
the tree.

By default svk will not let you import from a tree
that is already a working copy. If you wish to do so
anyway you need to specify the
--from-checkout switch.

Name

svk info — Print information about PATHs.

Synopsis

svk info [TARGET...]

Description

Print information about both working copy paths and
DEPOTPATHS, including:

Checkout Path

Depot Path

Revision

Last Changed Rev.

Mirrored From:

Copied From:

Merged From:

Alternate Names

None

Changes

Nothing

Accesses Depot

Yes

Accesses Mirrored Repository

No

Switches

None

Examples

svk info will show you all the
useful information that it has for your working
copy.

Name

svk log — Display commit log messages.

Synopsis

svk log DEPOTPATH

svk log PATH

Description

The default target is the path of your current
directory. If no arguments are supplied, svk
log shows the log messages for all files and
directories inside of (and including) the current working
directory of your working copy. You can refine the
results by specifying a path, one or more revisions, or
any combination of the two. The default revision range
for a local path is BASE:1.

If you specify a DEPOTPATH alone, then it prints log
messages for everything that the DEPOTPATH contains. The
default revision range for a URL is
HEAD:1.

With --verbose, svk log
will also print all affected paths with each log message.
With --quiet, svk log
will not print the log message body itself (this is
compatible with --verbose).

Note

Logs do not follow copy history by default. Use
--cross to enable following of copy
history.

Name

Synopsis

svk merge --revision N:M DEPOTPATH [WCPATH]

svk merge --revision DEPOTPATH1 DEPOTPATH2

svk merge --revision N:M [--to|--from] [WCPATH]

Description

TODO ## In the first and second forms, the source paths (URLs
in the first form, working copy paths in the second) are
specified at revisions N and
M. These are the two sources
to be compared. The revisions default to
HEAD if omitted.

In the third form, SOURCE
can be a URL or working copy item, in which case the
corresponding URL is used. This URL, at revisions
N and
M, defines the two sources to
be compared.

WCPATH is the working copy
path that will receive the changes. If
WCPATH is omitted, a default
value of “.” is assumed,
unless the sources have identical basenames that match a
file within “.”: in which
case, the differences will be applied to that file.

Unlike svk diff, the merge command
takes the ancestry of a file into consideration when
performing a merge operation. This is very important when
you're merging changes from one branch into another and
you've renamed a file on one branch but not the other.

Alternate Names

None

Changes

Working copy if merging to a working copy. Depot if
merging to a depotpath, and mirrored repository if the
destination is a mirrored depotpath.

If you branched at revision 23, and you want to
merge changes on trunk into your branch, you could do
this from inside the working copy of your branch:

$ svk merge --revision 23:30 //trunk/vendors
U myproj/thhgttg.txt
…

To merge changes to a single file:

$ cd myproj
$ svk merge --revision 30:31 thhgttg.txt
U thhgttg.txt

Name

svk mirror — Manage mirrors

Synopsis

mirror DEPOTPATH URL

mirror --list [DEPOTNAME...]

mirror --relocate DEPOTPATH URL

mirror --detach DEPOTPATH

mirror --recover DEPOTPATH

mirror --upgrade /DEPOTNAME/

Description

The first form sets up a new mirror of the repository
at URL in DEPOTPATH. DEPOTPATH must not yet exist, nor
can any of it's parent directories already be a mirror.
The URL can either be a Subversion repository URL, or
something that vcp understands if you
have that installed. Subversion repository mirrors are
read/write, vcp based mirrors (such as a mirror of a CVS
repository) are read only. For more details on valid URL
values, see ##TODO.

The second form lists all the mirrors in the depots
listed by DEPOTNAME, or all
mirrors if no DEPOTNAME is
given.

The third form detaches the specified path from it's
mirrored URL, causing that path and it's children to be
treated as regular DEPOTPATHs from now one. The contents
of DEPOTPATH remain unchanged, so any revisions retrieved
into the mirror prior to the detaching remain
available.

Tip

To completely remove a mirror you can use
svk delete on the mirrored path.
However when doing so be careful not to delete the
parent of an attached mirror since doing so will confuse
svk greatly right now.

If you accidentally do an SVN commit onto a mirrored
path—because you used the svn
client to commit directly to the depot's repository, or
the --direct switch to
svk, running svk mirror
--recover can undo it (reverse apply the
commit(s), and set the appropriate revprop), to get the
mirror working again.

The final form is used to upgrade the mirrors inside a
given DEPOTNAME to the current
standard way of tracking mirrored revisions. This command
is only relevant if you are upgrading from an older
version of SVK. ##TODO—How old? Which
version?

Alternate Names

mi

Changes

Depot, except mirror --list, which
changes nothing.

Accesses Depot

Yes

Accesses Mirrored Repository

Yes

Switches

--list (-l)
--detach (-d)
--relocate
--recover
--unlock
--upgrade

Examples

To mirror the svkbook sources in the /mirror/svkbook
directory of the default depot (the mirror directory will
get created automatically if it doesn't yet exist),
run:

Sometimes an administrator might change the
“base location” of the repository you are
mirroring—in other words, the contents of the
repository doesn't change, but the main URL used to reach
the root of the repository does. For example, the
hostname may change, the URL scheme, or any part of the
URL which leads to the repository itself. Rather than
create a new mirror, you can use the svn
mirror --relocate command to point the depot to
the new location of the mirrored repository.

For the sake of this example let's assume that the
book repository we mirrored, switched from using the
svnprotocol to http
instead, and that the hostname changed from svn to
svkbook, and that the svkbook virtual host has the repos
at it's root. To change our depot to refer to the mirrored
repository by it's new URL we would run:

Note

SVK won't let you relocate a mirror unless the new
mirrored repository has the same UUID as the original
mirror had. This prevents you from accidentally using
relocate to point a mirror at something that isn't
really the same repository after all.

Name

svk mkdir — Create a new directory under version control.

Synopsis

svk mkdir PATH...

svk mkdir DEPOTPATH

Description

Create a directory with a name given by the final
component of the PATH or
DEPOTPATH. A directory
specified by a working copy
PATH is scheduled for addition
in the working copy. A directory specified by a
DEPOTPATH is created in the
depot via an immediate commit. In both cases all the
intermediate directories must already exist, unless the
--parent (-p) switch is
specified.

Alternate Names

None

Changes

Working copy, depot if operating on a DEPOTPATH,
Mirrored repository if the DEPOTPATH is a mirrored path.

Name

Synopsis

svk move src DST

Description

This command moves a file or directory in your
working copy or in the repository.

Tip

This command is equivalent to an svk
copy followed by svk
delete.

Note

SVK does not support moving between working
copies and DEPOTs. In addition, you can only move files
within a single depot—SVK does not support
cross-depot moving. However if you have two mirrored
repositories in the same depot, you can move files and
directories between them.

WC -> WC

Move and schedule a file or directory for
addition (with history).

DEPOTPATH -> DEPOTPATH

Complete in depot rename.

Alternate Names

mv, ren, rename

Changes

Working copy, depot if operating on a DEPOTPATH,
Mirrored repository if either DEPOTPATH is a mirrored
path.

Tip

Currently SVK doesn't track which depot a patch is
for. If you are using more than one depot and a patch
applies to a depot other than the default, or
// depot you need to specify the
--depotDEPOTNAME switch to let SVK
know which depot the patch is meant for.

Switches

Examples

svk propedit makes it easy to
modify properties that have multiple values:

$ svk propedit svn:keywords foo.c
Waiting for editor...
<svk will launch your favorite editor here, with a buffer open
containing the current contents of the svn:keywords property. You
can add multiple values to a property easily here by entering one
value per line.>
M foo.c

Name

svk propget — Print the value of a property.

Synopsis

svk propget PROPNAME [TARGET[@REV]...]

svk propget PROPNAME --revprop --revision REV[@] [DEPOTPATH]

Description

Print the value of a property on files,
directories, or revisions. The first form prints the
versioned property of an item or items in your working
copy, while the second prints unversioned remote
property on a depot revision. See the section called “” for more information on
properties.

Alternate Names

pg, pget

Changes

Nothing

Accesses Depot

Yes

Accesses Mirrored Repository

No

Switches

--recursive (-R)
--revision (-r) REV[@]
--revprop
--strict

The --strict switch will prevent
extra newlines from being printed at the end of the
property values; when there are multiple paths involved,
it causes svk to not prefix the path name before each
value.

Examples

Examine a property of a file in your working
copy:

$ svk propget svn:keywords foo.c
Author
Date
Rev

The same goes for a revision property:

$ svk propget svn:log --revprop --revision 20
Began journal.

Name

svk proplist — List all properties.

Synopsis

svk proplist [TARGET[@REV]...]

svk proplist --revprop --revision REV[@] [DEPOTPATH]

Description

List all properties on files, directories, or
revisions. The first form lists versioned properties in
your working copy, while the second lists unversioned
properties on a depot revision.

Alternate Names

pl, plist

Changes

Nothing

Accesses Depot

Yes

Accesses Mirrored Repository

No

Switches

--recursive (-R)
--verbose (-v)
--revision (-r) REV
--revprop

Examples

You can use proplist to see the properties on an
item in your working copy:

Synopsis

Description

Set PROPNAME to
PROPVAL on files, directories,
or revisions. The first example creates a versioned, local
property change in the working copy, or directly in the
depot if a depotpath is specified. If neither are
specified it set the property on ..
The second creates an unversioned, property change on a
depot revision, using the DEPOT specified by
DEPOTPATH or
PATH or the depot associated
with ..

Tip

SVK has a number of “special”
properties that affect its behavior. See the section called “” for more on these
properties.

Alternate Names

ps, pset

Changes

Working copy, depot only if operating on a DEPOTPATH,
mirrored repository if the depotpath is mirrored.

Note

If you are working with a mirrored repository
changes to revision properties will only affect your own
depot. Also if you were to make changes to revision
properties in the Subversion repository you are
mirroring from, other people would only see the changes
you make if they hadn't already synced up to the
revision you are changing. This is because changing
revision properties does not commit a change to the
repository so the mirroring code has no way of knowing
that anything changed.

Description

Alternate Names

Changes

Accesses Depot

Accesses Mirrored Repository

Switches

Examples

##TODO

Name

svk resolved — Remove “conflicted” state on
working copy files or directories.

Synopsis

svk resolved PATH...

Description

Remove “conflicted” state on working
copy files or directories. This routine does not
semantically resolve conflict markers; it merely removes
conflict-related artifact files and allows PATH to be
committed again; that is, it tells Subversion that the
conflicts have been “resolved”. See the section called “Resolve Conflicts (Merging Others' Changes)” for an in-depth look at
resolving conflicts.

Alternate Names

None

Changes

Working copy

Accesses Depot

Yes

Accesses Mirrored Repository

No

Switches

--recursive (-R)

Examples

If you get a conflict on an update, and you decide to
skip resolving it at update time, your file will have
conflict markers in it and it will be marked as in
conflict by svk:

Once you've resolved the conflict and
integer.c is ready to be committed,
run svk resolved integer.c to let SVK
know you've taken care of everything.

Name

svk revert — Undo all local edits.

Synopsis

svk revert PATH...

Description

Reverts any local changes to a file or directory and
resolves any conflicted states. svk
revert will not only revert the contents of an
item in your working copy, but also any property
changes. Finally, you can use it to undo any scheduling
operations that you may have done (e.g. files scheduled
for addition or deletion can be
“unscheduled”).

Alternate Names

None

Changes

Working copy

Accesses Depot

Yes

Accesses Mirrored Repository

No

Switches

--recursive (-R)
--quiet (-q)

Examples

Discard changes to a file:

$ svk revert integer.c
Reverted integer.c

If you want to revert a whole directory of files,
use the --recursive flag:

Note

If you provide no targets to svk
revert, it will do nothing—to protect
you from accidentally losing changes in your working
copy, svk revert requires you to
provide at least one target. ##TODO Sadly currently this
is not true and the svk revert actually
defaults to . if no path is
given.

Tip

You can use svk revert --recursive together with svk
checkout --non-recursive to create a sparse working copy
tree. Lets say you have a project called multi with 4
subdirectories and you only need the p1 and p2
subdirectories. To do so you could run:

Name

Synopsis

Description

The first form merges changes from the specified
DEPOTPATH to the working copy
specified by PATH or
. if PATH is
omitted.

The second form performs a direct in depot merge from
DEPOTPATH1 to
DEPOTPATH2.

The third form will merge changes from the closest
copy anchor in the depot of the specified
TARGET—which must be a
depotpath that is a copy of something else, or a working
copy who's depotpath is a copy of something. Directly in
the depot to the source from which TARGET was copied.
Essentially this pushes the changes since the last smerge
on the specified branch to it's parent.

The fourth form will merge changes directly in the
depot to the closest copy anchor in the depot specified by
TARGET—which must be a
depotpath that is a copy of something else, or a working
copy who's depotpath is a copy of something, from the
source of the original upstream copy. Essentially this
pulls the parents changes since the last smerge into the
specified branch.

Alternate Names

sm

Changes

Working copy if merging to a working copy. Depot if
merging to a depotpath, and mirrored repository if the
destination is a mirrored depotpath.

Examples

Let's say you have worked on a project locally in your
svk depot until now, and you've decided it's time to
publish your project and it's history to a remote
Subversion repository. Furthermore let's assume you have
already mirrored the repository in question and there are
empty trunk tags and branches folders in the mirror.
Let's say locally your project is at
//project and the new mirror of the
Subversion reository you wish to publish to is at
//mirrors/project. To publish the
entire history of you local project you would run:

The --baseless switch makes the
smerge assume there is no common ancestor (which there
isn't yet). The --incremental switch
will make svk merge each commit to your local branch as a
separate commit to the upstream repository. And finally
the --verbatim switch will cause the log
messages of the commits to the upstream repository to be
identical to the original ones in your local svk
depot.

Name

svk status — Print the status of working copy files and directories.

Synopsis

svk status [PATH...]

Description

Print the status of working copy files and
directories. With no arguments, it prints only locally
modified items (no repository access).

The first three columns in the output are each one
character wide, and each column gives you information
about different aspects of each working copy item.

The first column indicates that an item
was added, deleted, or otherwise changed.

' '

No modifications.

'A'

Item is scheduled for Addition.

'D'

Item is scheduled for Deletion.

'M'

Item has been Modified.

'R'

Item has been Replaced in your working copy.

'C'

The contents (as opposed to the properties) of
the item conflict with updates received from the
depot.

'I'

Item is being ignored (e.g. with the
svn:ignore property).

'?'

Item is not under version control—not
displayed if --quiet switch is
present.

'!'

Item is missing (e.g. you moved or deleted it
without using svk). This also
indicates that a directory is incomplete (a checkout
or update was interrupted).

'~'

Item is versioned as one kind of object (file,
directory, link), but has been replaced by different
kind of object.

The second column tells the status of a file's or
directory's properties.

' '

No modifications.

'M'

Properties for this item have been
modified.

'C'

Properties for this item are in conflict with
property updates received from the
repository.

The third column is populated only if the item is
scheduled for addition-with-history.

' '

No history scheduled with commit.

' '

History scheduled with commit.

Remaining fields are variable width and delimited by
spaces: The working revision (with -v) The last committed
revision and last committed author (with -v) The working
copy path is always the final field, so it can include
spaces.

Alternate Names

st, stat

Changes

Nothing

Accesses Depot

Yes

Accesses Mirrored Repository

No

Switches

--quiet [-q]

do not display files not under version control

--no-ignore

disregard default and svn:ignore property ignores

-N [--non-recursive]

do not descend recursively

-v [--verbose]

print full revision information on every item

Examples

This is the easiest way to find out what changes you
have made to your working copy:

$ svk status wc
M wc/bar.c
A wc/qax.c

If you want to find out what files in your working
copy are out-of-date, you should use svk update
--check-only instead of svk
status, see svk update.

Name

svk switch — Update working copy to a different DEPOTPATH.

Synopsis

svk switch DEPOTPATH [PATH]

Description

This subcommand updates your working copy to mirror a
new DEPOTPATH—this must be a DEPOTPATH which shares
a common ancestor with your working copy. This is the svk
way to move a working copy to a new branch. See the section called “Switching a Working Copy” for an in-depth look
at switching.

Alternate Names

sw

Changes

Working copy

Accesses Depot

Yes

Accesses Mirrored Repository

No

Switches

--revision (-r) REV
--detach (-d)
--quiet (-q)

Examples

If you're currently inside the directory
vendors which was branched to
vendors-with-fix and you'd like to
switch your working copy to that branch:

Note

It's not possible to switch part of your working
copy to a branch. Currently SVK doesn't support mixed
depot path working copies.

Name

svk sync — Download upstream changes into mirrored DEPOTPATHs.

Synopsis

svk sync [--skipto REV] [--torev REV] DEPOTPATH

svk sync --all [DEPOTNAME|DEPOTPATH]...

Description

The first form downloads upstream changes to the
mirror anchored at the specified DEPOTPATH, optionally
limited to the specified revision range.. The second form
downloads all upstream changes to all mirrors in the
specified depots (which can be specified by name or a path
in the depot).

Alternate Names

sy

Changes

Depot or depots being updated.

Accesses Depot

Yes

Accesses Mirrored Repository

Yes

Switches

--all (-a)
--skipto (-s) REV
--torev (-t) REV

Examples

To mirror the svkbook sources and just mirror the
current HEAD rather than the entire history run:

Note

Running svk sync will never
modify any working copies, nor will it ever cause any
conflicts or merges to happen. This is because it's the
only way a mirrored depotpath will ever get written
to[21]. So it's
safe (and recommended) to run svk
sync whenever you have connectivity. Even
committing to a mirrored path using svk
commit or any other command the does a direct
modification of the depot will not actually change the
mirrored path directly. Instead it commits to the
mirror first and then runs an implicit svk
sync for you.

[21] With the exception of the property
changes at the mirrors anchor made by svk
mirror --relocate.

Name

svk update — Update your working copy.

Synopsis

svk update [PATH...]

Description

svk update brings changes from the
depot into your working copy. If no revision given,
it brings your working copy up-to-date with the
HEAD revision. Otherwise, it
synchronizes the working copy to the revision given by the
--revision switch.

For each updated item a line will start with a
character reporting the action taken. These characters
have the following meaning:

A

Added

D

Deleted

U

Updated

C

Conflict

G

Merged

g

Merged, but the file in your working copy
already had the changes being merged so the file is
unchanged.

A character in the first column signifies an update
to the actual file, while updates to the file's
properties are shown in the second column.

By default, when loading data into repository that
already contains revisions, svk admin
will ignore the UUID from the dump
stream. This switch will cause the repository's
UUID to be set to the
UUID from the stream.

--ignore-uuid

By default, when loading an empty repository,
svk admin will use the
UUID from the dump stream. This
switch will cause that UUID to be ignored.

--incremental

Dump a revision only as a diff against the
previous revision, instead of the usual
fulltext.

--parent-dir
DIR

When loading a dump file, root paths at
DIR instead of
/.

--revision (-r)
ARG

Specify a particular revision to operate
on.

--quiet

Do not show normal progress—show only
errors.

--use-post-commit-hook

When loading a dump file, run the repository's
post-commit hook after finalizing each newly loaded
revision.

--use-pre-commit-hook

When loading a dump file, run the repository's
pre-commit hook before finalizing each newly loaded
revision. If the hook fails, abort the commit and
terminate the load process.

svk admin Subcommands

Name

svk admin create — Create a new, empty repository.

Synopsis

svk admin create REPOS_PATH

Description

Create a new, empty repository at the path provided.
If the provided directory does not exist, it will be
created for you.[22] As of
Subversion 1.2, svk admin creates new
repositories with the fsfs filesystem
backend by default.

Switches

--bdb-txn-nosync
--bdb-log-keep
--config-dir DIR
--fs-type TYPE

Examples

Creating a new repository is just this easy:

$ svk admin create /usr/local/svn/repos

In Subversion 1.0, a Berkeley DB repository is always
created. In Subversion 1.1, a Berkeley DB repository is
the default repository type, but an FSFS repository can be
created using the --fs-type
switch:

Name

Synopsis

svk admin deltify [-r LOWER[:UPPER]] REPOS_PATH

Description

svk admin deltify only exists in
1.0.x due to historical reasons. This command is
deprecated and no longer needed.

It dates from a time when Subversion offered
administrators greater control over compression strategies
in the repository. This turned out to be a lot of
complexity for very little gain, and
this “feature” was deprecated.

Switches

--revision (-r)
--quiet

Name

svk admin dump — Dump the contents of filesystem to stdout.

Synopsis

svk admin dump REPOS_PATH [-r LOWER[:UPPER]] [--incremental]

Description

Dump the contents of filesystem to stdout in a
“dumpfile” portable format, sending feedback
to stderr. Dump revisions
LOWER rev through
UPPER rev. If no revisions are
given, dump all revision trees. If only
LOWER is given, dump that one
revision tree. See the section called “”
for a practical use.

If the size of your Subversion dumpfile is a concern,
you can use the --deltas switch to (in
some cases drastically) reduce the size of the dumpfile
that svk admin creates. With this
switch, instead of writing the full content of each
revision to the dumpfile, svk admin dump
will only emit the differences from one revision to the
next. There are, however, disadvantages to creating
deltified dumpfiles—it's more CPU intensive to
create them, svndumpfilter can't
operate on them, and non-deltified dumpfiles tend to
compress better.

Name

Synopsis

Description

This subcommand is useful when you're trapped on a
desert island with neither a net connection nor a copy of
this book.

Alternate Names

?, h

Name

svk admin hotcopy — Make a hot copy of a repository.

Synopsis

svk admin hotcopy REPOS_PATH NEW_REPOS_PATH

Description

This subcommand makes a full “hot” backup
of your repository, including all hooks, configuration
files, and, of course, database files. If you pass the
--clean-logs switch,
svk admin will perform a hotcopy of your
repository, and then remove unused Berkeley DB logs from
the original repository. You can run this command at any
time and make a safe copy of the repository, regardless of
whether other processes are using the repository.

Switches

--clean-logs

Name

svk admin list-dblogs — Ask
Berkeley DB which log files exist for a given Subversion
repository (applies only to repositories using the
bdb backend).

Synopsis

svk admin list-dblogs REPOS_PATH

Description

Berkeley DB creates logs of all changes to the
repository, which allow it to recover in the face of
catastrophe. Unless you enable
DB_LOGS_AUTOREMOVE, the log files
accumulate, although most are no longer used and can be
deleted to reclaim disk space. See the section called “” for more
information.

Name

svk admin list-unused-dblogs — Ask Berkeley DB which log files can be safely
deleted (applies only to repositories using the
bdb backend).

Synopsis

svk admin list-unused-dblogs REPOS_PATH

Description

Berkeley DB creates logs of all changes to the
repository, which allow it to recover in the face of
catastrophe. Unless you enable
DB_LOGS_AUTOREMOVE, the log files
accumulate, although most are no longer used and can be
deleted to reclaim disk space. See the section called “” for more
information.

Name

Synopsis

Description

Print the names of all uncommitted transactions. See
the section called “” for information on how
uncommitted transactions are created and what you should
do with them.

Examples

List all outstanding transactions in a
repository.

$ svk admin lstxns /usr/local/svn/repos/
1w
1x

Name

svk admin recover — Bring a repository database back into a
consistent state (applies only to repositories using the
bdb backend). In addition, if
repos/conf/passwd does not exist, it
will create a default password file .

Synopsis

svk admin recover REPOS_PATH

Description

Run this command if you get an error indicating that
your repository needs to be recovered.

Name

svk admin setlog — Set the log-message on a revision.

Synopsis

svk admin setlog REPOS_PATH --revision REVISION FILE

Description

Set the log-message on revision REVISION to the
contents of FILE.

This is similar to using svn propset
--revprop to set the svn:log property
on a revision, except that you can also use the option
--bypass-hooks to avoid running any pre- or
post-commit hooks, which is useful if the modification of
revision properties has not been enabled in the pre-revprop-change
hook.

Warning

Revision properties are not under version control,
so this command will permanently overwrite the previous
log message.

Switches

--revision (-r) ARG
--bypass-hooks

Examples

Set the log message for revision 19 to the contents of
the file msg:

$ svk admin setlog /usr/local/svn/repos/ --revision 19 msg

Name

svk admin verify — Verify the data stored in the repository.

Synopsis

svk admin verify REPOS_PATH

Description

Run this command if you wish to verify the integrity
of your repository. This basically iterates through all
revisions in the repository by internally dumping all
revisions and discarding the output.

Examples

Verify a hung repository:

$ svk admin verify /usr/local/svn/repos/
* Verified revision 1729.

Name

Synopsis

svk admin rmcache

Description

Use this command to remove SVK's cache of inode,
mtime, size tuples for files for all working copies.
Having the cache around dramatically speeds up most
working copy related SVK commands, however SVK might
sometimes leave unused cache entries around—for
example entries from since detached working copies.
Running this command purges the cache and frees up some
disk space.

This chapter goes into greater depth about the depot. It
explains what depots are, and how you manage them and how you
can best make use of them.

The primary focus of this chapter is the
depotmap command, and is best read with
reference to svk depotmap.

What is the depot?

As you will already know, a depot is SVK's primary storage
area. It is the place from which all of your code is checked
out, and to where you commit your changes and mirror other
repositories. Up to this point this book has intentionally
kept the inner workings of the depot away from the reader, as
they are not essential to using SVK for most tasks, and would
undoubtedly confuse the new user unnecessarily.

However, knowing more about how depots work and how to
manage them can be of use to all users of SVK in terms of
flexibility, and can help the reader gain a deeper understanding
of SVK; beyond the basics.

As was explained in the section called “The Depot”
depot is simply a Subversion repository, which can be located
anywhere in the filesystem. The Subversion file system used for
this repository is defined by the $SVNFSTYPE
environment variable. If $SVNFSTYPE is not
set, the file system is determined by the version of the
Subversion client installed (fsfs for version 1.1 and newer, bdb
for older versions of Subversion).

Outside of this Subversion repository, SVK also keeps
higher-level information about the depot in the
$SVKROOT/config file. The two key pieces of
information stored about a depot are:

DEPOTNAME

The DEPOTNAME is a symbolic
name give to the depot which makes up a part of the
DEPOTPATHs that you pass to SVK commands.

REPOPATH

The REPOPATH is the full
absolute path to the Subversion repository itself.

Multiple depots

Is is possible to have multiple depots in a single user's
SVK configuration. Of course, you need to have at least one
depot in order to use SVK, and after SVK was first installed
you created this depot before doing anything else. This is the
depot that you have been using throughout the book up to this
point, and is called the Default Depot.

The default depot

The default depot is special because it has no
DEPOTNAME. Or rather, its
DEPOTNAME is the empty string. By
default its REPOPATH is
$SVKROOT/local.

The Default Depot is created using the
depotmap --init command. This is the only
time that the --init switch is used with
the depotmap command

Named depots

For many users, the default depot is all that is needed.
However, some users find it useful to be able to create
additional named depots.

You can create as many additional named depots as you
like. Depots are created using svk depotmap
command.

For example, to create a new depot with
DEPOTNAME'test'
and REPOPATH/tmp/test-depot, you can use this
command:

Why use multiple depots?

At this point you may be wondering why you'd want to use
multiple depots. After all, a depot is just a Subversion
repository, and that means you are free to structure your
depot in any way you wish, with the root folder perhaps
containing a folder for each project you're working on, with
each project possibly containing a mirror for that
project.

Indeed, many people do use SVK just like this: with
everything placed in the default depot, and often never even
realizing that it is possible to have more than one
depot.

There are however some good reasons why you might want to
use more than one depot:

Separating interests

Imagine that you are mirroring two repositories: an
Open Source project and also a project for your
employer. You might want to keep the two mirrors in
separate depots so that the two projects can't affect
each other.

Disk space

You are free to create depots anywhere you have
permission to. You may want to create a depot on a
partition that has a lot of space, for example if you
are mirroring a particularly large repository.

Easy disposal

A project in its own depot can easily be thrown away
completely without having any effect on other projects.
If the projects were in the same depot you could of
course delete the relevant paths in the depot, but the
history of the deleted paths would remain, which may be
precisely what you are trying to remove.

Different purposes

You may want to use different depots for different
purposes. For example, you might have one depot for
mirrors, and another for your personal depot containing
your local repository that only you commit to.

Network sharing

If you are using the fsfs Subversion filesystem
for your depot, it is possible to host a depot on a
remote filesystem mounted via NFS. This allows you to
share the same depot with other developers.

Why not use multiple depots?

While using multiple depots has many advantages, there are
a few things that you should consider before using them.
Different depots really are completely separate entities:
you can't create a branch in one depot that is a copy of a
directory in another, and you can't do merging between them.

General depot manipulation

Most of the time depots just sit there and are used by the
other SVK commands that you use in general operation, but
occasionally depots needs to be operated on directly. This
section describes how to do the more general depot
administration operations.

For reference documentation on the
depotmap command that is used throughout this
section, see svk depotmap.

Listing depots

When dealing with depots it's often useful to be able to
find out what depots you have on your system. This is
accomplished using the depotmap command
with the --list option. For example:

The left column lists the depot path, while the right
column lists the actual path to the depot on your filesystem.
In this case we see that two of the depots this user has
mapped to are located in their home directory, while the other
is located in a shared place in the filesystem. The first
depot listed is the default depot.

Detaching depots

If you reach a point where you no longer want to treat
a depot as a depot (for example if you want to use it as a
repository or you want to delete it completely) you can
tell SVK to forget about it using the
--detach option. For example:

The --list command shows that the depot
is once again known about by SVK.

Relocating depots

Describe relocating depots.

Advanced depot administration

This is basically going to be about svk admin.

Appendix A. SVK for CVS Users

Not yet written

Appendix B. WebDAV and Autoversioning

Not yet written

Appendix C. Repository Administration

Not yet written

Appendix D. Copyright

Copyright (c) 2002-2005
Ben Collins-Sussman, Brian W. Fitzpatrick, C. Michael Pilato.
This work is licensed under the Creative Commons Attribution License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by/2.0/ or send a letter to
Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305,
USA.
A summary of the license is given below, followed by the full legal
text.
--------------------------------------------------------------------
You are free:
* to copy, distribute, display, and perform the work
* to make derivative works
* to make commercial use of the work
Under the following conditions:
Attribution. You must give the original author credit.
* For any reuse or distribution, you must make clear to others the
license terms of this work.
* Any of these conditions can be waived if you get permission from
the author.
Your fair use and other rights are in no way affected by the above.
The above is a summary of the full license below.
====================================================================
Creative Commons Legal Code
Attribution 2.0
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR
DAMAGES RESULTING FROM ITS USE.
License
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS
CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS
PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE
WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS
PROHIBITED.
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND
AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS
YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF
SUCH TERMS AND CONDITIONS.
1. Definitions
a. "Collective Work" means a work, such as a periodical issue,
anthology or encyclopedia, in which the Work in its entirety in
unmodified form, along with a number of other contributions,
constituting separate and independent works in themselves, are
assembled into a collective whole. A work that constitutes a
Collective Work will not be considered a Derivative Work (as
defined below) for the purposes of this License.
b. "Derivative Work" means a work based upon the Work or upon the
Work and other pre-existing works, such as a translation,
musical arrangement, dramatization, fictionalization, motion
picture version, sound recording, art reproduction, abridgment,
condensation, or any other form in which the Work may be recast,
transformed, or adapted, except that a work that constitutes a
Collective Work will not be considered a Derivative Work for the
purpose of this License. For the avoidance of doubt, where the
Work is a musical composition or sound recording, the
synchronization of the Work in timed-relation with a moving
image ("synching") will be considered a Derivative Work for the
purpose of this License.
c. "Licensor" means the individual or entity that offers the Work
under the terms of this License.
d. "Original Author" means the individual or entity who created the Work.
e. "Work" means the copyrightable work of authorship offered under
the terms of this License.
f. "You" means an individual or entity exercising rights under this
License who has not previously violated the terms of this
License with respect to the Work, or who has received express
permission from the Licensor to exercise rights under this
License despite a previous violation.
2. Fair Use Rights. Nothing in this license is intended to reduce,
limit, or restrict any rights arising from fair use, first sale or
other limitations on the exclusive rights of the copyright owner
under copyright law or other applicable laws.
3. License Grant. Subject to the terms and conditions of this License,
Licensor hereby grants You a worldwide, royalty-free,
non-exclusive, perpetual (for the duration of the applicable
copyright) license to exercise the rights in the Work as stated
below:
a. to reproduce the Work, to incorporate the Work into one or more
Collective Works, and to reproduce the Work as incorporated in
the Collective Works;
b. to create and reproduce Derivative Works;
c. to distribute copies or phonorecords of, display publicly,
perform publicly, and perform publicly by means of a digital
audio transmission the Work including as incorporated in
Collective Works;
d. to distribute copies or phonorecords of, display publicly,
perform publicly, and perform publicly by means of a digital
audio transmission Derivative Works.
e.
For the avoidance of doubt, where the work is a musical composition:
i. Performance Royalties Under Blanket Licenses. Licensor
waives the exclusive right to collect, whether
individually or via a performance rights society
(e.g. ASCAP, BMI, SESAC), royalties for the public
performance or public digital performance (e.g. webcast)
of the Work.
ii. Mechanical Rights and Statutory Royalties. Licensor waives
the exclusive right to collect, whether individually or
via a music rights agency or designated agent (e.g. Harry
Fox Agency), royalties for any phonorecord You create from
the Work ("cover version") and distribute, subject to the
compulsory license created by 17 USC Section 115 of the US
Copyright Act (or the equivalent in other jurisdictions).
f. Webcasting Rights and Statutory Royalties. For the avoidance of
doubt, where the Work is a sound recording, Licensor waives the
exclusive right to collect, whether individually or via a
performance-rights society (e.g. SoundExchange), royalties for
the public digital performance (e.g. webcast) of the Work,
subject to the compulsory license created by 17 USC Section 114
of the US Copyright Act (or the equivalent in other
jurisdictions).
The above rights may be exercised in all media and formats whether now
known or hereafter devised. The above rights include the right to make
such modifications as are technically necessary to exercise the rights
in other media and formats. All rights not expressly granted by
Licensor are hereby reserved.
4. Restrictions.The license granted in Section 3 above is expressly
made subject to and limited by the following restrictions:
a. You may distribute, publicly display, publicly perform, or
publicly digitally perform the Work only under the terms of this
License, and You must include a copy of, or the Uniform Resource
Identifier for, this License with every copy or phonorecord of
the Work You distribute, publicly display, publicly perform, or
publicly digitally perform. You may not offer or impose any
terms on the Work that alter or restrict the terms of this
License or the recipients' exercise of the rights granted
hereunder. You may not sublicense the Work. You must keep intact
all notices that refer to this License and to the disclaimer of
warranties. You may not distribute, publicly display, publicly
perform, or publicly digitally perform the Work with any
technological measures that control access or use of the Work in
a manner inconsistent with the terms of this License
Agreement. The above applies to the Work as incorporated in a
Collective Work, but this does not require the Collective Work
apart from the Work itself to be made subject to the terms of
this License. If You create a Collective Work, upon notice from
any Licensor You must, to the extent practicable, remove from
the Collective Work any reference to such Licensor or the
Original Author, as requested. If You create a Derivative Work,
upon notice from any Licensor You must, to the extent
practicable, remove from the Derivative Work any reference to
such Licensor or the Original Author, as requested.
b. If you distribute, publicly display, publicly perform, or
publicly digitally perform the Work or any Derivative Works or
Collective Works, You must keep intact all copyright notices for
the Work and give the Original Author credit reasonable to the
medium or means You are utilizing by conveying the name (or
pseudonym if applicable) of the Original Author if supplied; the
title of the Work if supplied; to the extent reasonably
practicable, the Uniform Resource Identifier, if any, that
Licensor specifies to be associated with the Work, unless such
URI does not refer to the copyright notice or licensing
information for the Work; and in the case of a Derivative Work,
a credit identifying the use of the Work in the Derivative Work
(e.g., "French translation of the Work by Original Author," or
"Screenplay based on original Work by Original Author"). Such
credit may be implemented in any reasonable manner; provided,
however, that in the case of a Derivative Work or Collective
Work, at a minimum such credit will appear where any other
comparable authorship credit appears and in a manner at least as
prominent as such other comparable authorship credit.
5. Representations, Warranties and Disclaimer
UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING,
LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR
WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED,
STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF
TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE,
NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY,
OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT
DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED
WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY
APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY
LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE
OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE
WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
7. Termination
a. This License and the rights granted hereunder will terminate
automatically upon any breach by You of the terms of this
License. Individuals or entities who have received Derivative
Works or Collective Works from You under this License, however,
will not have their licenses terminated provided such
individuals or entities remain in full compliance with those
licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any
termination of this License.
b. Subject to the above terms and conditions, the license granted
here is perpetual (for the duration of the applicable copyright
in the Work). Notwithstanding the above, Licensor reserves the
right to release the Work under different license terms or to
stop distributing the Work at any time; provided, however that
any such election will not serve to withdraw this License (or
any other license that has been, or is required to be, granted
under the terms of this License), and this License will continue
in full force and effect unless terminated as stated above.
8. Miscellaneous
a. Each time You distribute or publicly digitally perform the Work
or a Collective Work, the Licensor offers to the recipient a
license to the Work on the same terms and conditions as the
license granted to You under this License.
b. Each time You distribute or publicly digitally perform a
Derivative Work, Licensor offers to the recipient a license to
the original Work on the same terms and conditions as the
license granted to You under this License.
c. If any provision of this License is invalid or unenforceable
under applicable law, it shall not affect the validity or
enforceability of the remainder of the terms of this License,
and without further action by the parties to this agreement,
such provision shall be reformed to the minimum extent necessary
to make such provision valid and enforceable.
d. No term or provision of this License shall be deemed waived and
no breach consented to unless such waiver or consent shall be in
writing and signed by the party to be charged with such waiver
or consent.
e. This License constitutes the entire agreement between the
parties with respect to the Work licensed here. There are no
understandings, agreements or representations with respect to
the Work not specified here. Licensor shall not be bound by any
additional provisions that may appear in any communication from
You. This License may not be modified without the mutual written
agreement of the Licensor and You.
Creative Commons is not a party to this License, and makes no warranty
whatsoever in connection with the Work. Creative Commons will not be
liable to You or any party on any legal theory for any damages
whatsoever, including without limitation any general, special,
incidental or consequential damages arising in connection to this
license. Notwithstanding the foregoing two (2) sentences, if Creative
Commons has expressly identified itself as the Licensor hereunder, it
shall have all rights and obligations of Licensor.
Except for the limited purpose of indicating to the public that the
Work is licensed under the CCPL, neither party will use the trademark
"Creative Commons" or any related trademark or logo of Creative
Commons without the prior written consent of Creative Commons. Any
permitted use will be in compliance with Creative Commons'
then-current trademark usage guidelines, as may be published on its
website or otherwise made available upon request from time to time.
Creative Commons may be contacted at http://creativecommons.org/.
====================================================================