r7 - 12 Dec 2006 - 09:46:28 - GrantBaillieYou are here: OSAF >  Journal Web  >  ContributorNotes > GrantBaillieNotes > GrantBaillieSvkNotes

Grant’s SVK Notes

This isn’t supposed to be a comprehensive tutorial on SVK: See #External below for that, or run the svk intro command). Even though I often address the reader in the second person, it’s more a reminder to myself of my SVK habits and setup. If you read this, and find any of it useful, that’s grand, though.

Disclaimer: I’m pretty sure I got most of the example commands right, but you really should double-check things yourself. Most SVK commands accept the -C option, which is the “just tell me what you would have done” mode (à la -n in subversion).

What I like about SVK

Works well with svn: SVK reportedly works with other version control systems (Perforce, CVS, ...), but I’ve only tried it on (remote) subversion repositories. SVK’s commands are very similar to svn’s: There are extra commands that have no analog in svn (mirror/sync/push/pull/smerge), and some of the command-line switches differ, but the familiar svn commands (checkout, commit etc.) are all there. Under the covers, SVK uses a subversion repository (stored in ~/.svk) to maintain all its revisions, so it’s possibly not surprising that it uses a svn-like command syntax.

Offline use: SVK is built around “mirroring” a remote repository, or part of one, which you create using the svn mirror command. This means you get a local copy of the tree on your machine: you can browse and/or diff revisions, or copy/move parts of the tree without needing to be on the network. You do need to be connected to commit to a mirrored repository; the same is true when you run the svk sync command, allows you to pick up the changes made in a remote repository since your last sync.

Knows where your checkouts are: I tend to check out a lot of copies of Chandler, to try out fixes or improvements. It turns out this is a good way to pile up lots of checkouts: Occasionally I’ll thrash about on a few ideas in different checkouts, and then go on vacation for a week, and come back and have a lot of trouble figuring out where sets of changes went. In SVK, the command svk co --list will tell me where they went. A downside of this is that you can’t just move checked-out copies around in the filesystem — you need svk co --relocate if you want to do that — but for me the benefits way outweigh the cost.

Local branches: A common model in SVK is to make a local branch of a mirrored checkout. That means that the branch (i.e. copy of some part of a repository) exists only in your local repository, not on the server, so you can commit changes there without them going back to the server. However, SVK is aware where your branch came from, and there are commands that help you with local branches:

  • svk pull will update the mirror you created the branch from, and then merge in changes into your checkout of the branch.
  • svk push does the opposite: it allows you to commit your changes in the local branches back to the remote repository it was originally copied from.
  • svk smerge (smerge means “star merge”) is the remote-repository-and-local-branch-aware version of svn merge: it allows you to merge changes across different trees, possibly from different repositories.

Less backup headache: I tend to work in local branches, and commit often. That means that the only thing I need to back up is my ~/.svk directory in order to avoid losing any work.

Handy linkies

External

  • The SVK Home Page, http://svk.elixus.org/, has many useful links.
  • To get set up, I found the 3-part posts on Bieber Labs very illuminating: 1, 2, 3.
  • There’s an online reference manual (similar in spirit to the one for Subversion) at http://svkbook.elixus.org/. When I started out, this was still in a pretty rudimentary state, but it seems to have acquired a whole lot of interesting-looking content recently.
  • Vinu points out that the #svk channel on irc.freenode.net is good for getting your questions answered.

Other OSAF SVK Journal entries

Installation

I’m running Mac OS X 10.4, and have svn version 1.3.1 (I built it myself). I initially tried messing with Perl and CPAN, but that failed with some error I could’t understand. So, I found an OS X dmg containing an installer package on http://homepage.mac.com/hiirem/svkbuilds.html, and installed version 1.08. Easy nuff.

Mirrors

In the case of Chandler, where I’m interested in checking out and working on svn branches (e.g. now, we’re working on 0.7alpha4, and that has its own svn branch), so I mirrored the whole repository, via

bash$ svk mirror svn+ssh://svn.osafoundation.org/svn/chandler //mirror/chandler

What this command done is suck down every revision of chandler from the subversion repository on svn.osafoundation.org into SVK’s local database (stored in ~/.svk). For chandler, that’s around 12k revisions right now, so this took a while! The //mirror/chandler is what’s called a depot path: It’s how you refer to files stored in your local database (the depot).

You don’t have to mirror the whole repository, though. In the case of our docs repository, where I’m only interested in the specs folder, I did:

bash$ svk mirror svn+ssh://svn.osafoundation.org/svn/docs/trunk/docs/specs //mirror/specs

and similarly, with our sandbox repository, I only mirrored my personal subdirectory.

Also, you can mirror read-only repositories (http: URLs in our case); I don’t have any use for that right now (maybe I’ll mirror cosmo, or python, readonly some day, though).

Like many other commands in SVK, mirror accepts a --list argument, which in this case lists all the remote repositories you have mirrored:

bash$ svk mirror --list
Path                    Source
============================================================
//mirror/osaf/chandler  svn+ssh://svn.osafoundation.org/svn/chandler
//mirror/osaf/specs     svn+ssh://svn.osafoundation.org/svn/docs/trunk/docs/specs
//mirror/sandbox        svn+ssh://svn.osafoundation.org/svn/sandbox/grant
...

One final thing to note is that svk mirror is (in my usage) the only SVK command that refers to a URL-style remote repository path. The paths in other SVK commands are either depot paths, or disk paths. Presumably, the reason depot paths start with ‘//’ is so that SVK can tell which you mean when a command takes either kind (like svk merge).

Checkouts

You check things out in SVK in a similar way to svn, except you pass in a depot path instead a repository URL. So, for example, I checked out chandler via:

bash$ svk co //mirror/osaf/chandler/trunk/chandler

At this point, I can go and make changes inside chandler as usual, and commit them via svk commit. One thing that might trip you up is that

bash$ svk update

is a purely local operation: you don’t get more recent commits from svn.osafoundation.org. If you want those, either issue

bash$ svk sync //mirror/chandler

first to get those commits into your local depot. Or, to combine those two operations into one, do

bash$ svk pull

(but see the warning in #BranchPull below first!).

Revisions

SVK’s revisions number work pretty much the same as svn’s: each represents the state of all the files and metadata in your entire SVK depot (a.k.a. local repository), and they increment by 1 every time. This isn’t a coinkydink: really the depot is a local svn repository, with a few extra properties that SVK uses to track mirroring, syncing and merging.

When you mirror or sync a remote repository, each new remote revision SVK discovers gets its own local revision. This is the revision number that is used in SVK commands: It is almost always different from the remote revision number, and also varies from user to user.

Of course, you often want to know the “real” (remote) revision number: If someone else wants to know if they have picked up an important fix from you, telling them your depot revision isn’t so useful.

A handy trick here is that most SVK commands that take revision numbers understand that a revision number ending in ‘@’ means a remote revision. For example:

bash$ svk log -r12345@ //mirror/chandler

will give you the same commit log as

bash$ svn log -r12345 svn+ssh://svn.osafoundation.org/svn/chandler

except that it completes in a fraction of the time, and won’t hang if the svn server is down!

Local branches

The svk copy works pretty much like its svn counterpart, and is used to make tags or branches. However, since it copies between two depot paths, you can copy from a mirrored to a non-mirrored path, which creates a local branch.

For example, when I was working on stamping, which involved making pretty widespread changes to the codebase, I worked a lot on a local branch, created with

svk cp -p //mirror/chandler/trunk/chandler //local/stamping/chandler

(the -p tells SVK to create the intermediate depot paths //local and //local/stamping if necessary).

Then, after checking out //local/stamping/chandler, I could commit as often as I liked, which encourages a mode where your (local) commit logs make a record of the changes you’re making.

Of course, you can use svk cp to make the kind of branches familiar to svn users, by passing in two paths inside a mirrored repository. Or, you could copy trees from one remote repository to another (see Merging between repositories).

Merging

In a local branch, you still want to be able to pick up changes as necessary from the remote repository as necessary. Here, the smerge command comes to the rescue. In the above case, once I’d synced //mirror/chandler, I could get those changes using

svk smerge //mirror/chandler/trunk/chandler //local/stamping/chandler

This basically says: “Merge the changes that have occurred in the remote repository into my local branch”. SVK would proceed by prompting you for a commit message, pulling changes as necessary, and committing those to the local branch.

If conflicts arise, you get prompted on a per-file basis as to what to do. One option is to edit the file, where the text in the conflict appears in a form familiar to svn users, with yours, the original and the new text shown.

<<Grant: an example? or a link to one>>

I’m glossing over the procedure here a little. What I actually was doing was:

svk smerge -C -l --remoterev //mirror/chandler/trunk/chandler //local/stamping/chandler

where the options meant:

-C (check only) Show what files would change, which is handy to show conflicts.
-l Make the commit log (that you get to edit) be the concatenation of the logs of the changes being merged.
--remoterev In the above commit log, show the remote revision numbers instead of local

and then following up without the -C if I still felt it was a good idea to merge.

A few notes:

  1. You can also specify a local checkout as the destination of smerge; that way you can commit the files yourself afterwards.
  2. SVK uses a special property, svk:merge, to track what merges you have done on a given depot path. That way, if you reissue the above command at a later date, it’s not going to confuse itself trying to replay a bunch of changes you already have. The values of that property are a combination of UUID-like things and depot paths, and are called “merge tickets” (On completion, smerge prints out a message about creating a new merge ticket).
  3. I think that the svk pull command would combine svk sync and svk smerge here, but:
    • You don’t get the chance to edit the commit log in this case
    • I’m a little wary of pull because of #BranchPull below
    • At the time, I wasn’t aware of svk pull :).
  4. There’s nothing to stop you using smerge to run merge between two mirrored trees. In fact, I always found the svn merge command very confusing (every time I read the output of svn merge --help my eyes start to glaze over). For example, now that I’m doing some work on a branch chandler I do the following to do merges regularly (with a simple edit to change the commit log to be something like “merge in trunk rXXXXXX--YYYYYY”):

bash$ svk smerge --remoterev -l //mirror/chandler/trunk/chandler //mirror/chandler/branches/recurrence-0.7alpha5/chandler

Switching between branches

Ultimately, when it came to committing my stamping branch changes, I could have used smerge to merge the branch’s changes back into the trunk. Another option would be to use svk push, but see #PushCommand for why this probably wouldn’t have been a good idea without tweaking command-line arguments.

Instead, I used the following sequence of commands, after a sync and smerge to get the branch up-to-date:

bash$ svk checkout //local/stamping/chandler
bash$ cd chandler
bash$ svk status
(shows no changes)
bash$ svk switch //mirror/chandler/trunk/chandler
bash$ svk status
(shows all the changes in my branch compared to the trunk)
(run unit tests, make last-minute comment changes, etc)
bash$ svk commit
(commits to the trunk)

Hmm.... Does this actually work? I might be misremembering the command — Grant

The switch command basically let you change the depot path out from underneath a checked-out tree. It’s very handy in cases like this.

Merging between repositories

One other case I ran into when working on my local stamping branch was that at some point I wanted to have other people try out the code. One way would have been to create a branch in the Chandler svn repository, but in the end I made copies over to a separate repository at OSAF, the sandbox, which isn’t tracked as rigorously: I didn’t really want to use the main Chandler one, because that would have involved sending relatively frequent large commit notices to the (fairly large) commits list.

So, to create the copy, I did:

bash$ svk cp -p //local/stamping/chandler //sandbox/stamping/chandler

which allowed svn users to check that chandler out of my sandbox. For subsequent pushes to the sandbox, smerge was the ticket:

bash$ svk smerge //local/stamping/chandler //sandbox/stamping/chandler

Patches

The smerge and commit commands both take a --patch, which means that a patch in your depot will be created out of the new changes, instead of making new revisions. You can then use the patch command to manipulate that patch.

I haven’t used this command much, except to upload patches to Bugzilla. Someday, when I’m feeling enthusiastic, I’ll write an SVKZilla script, like subzilla, which would automate this process.

My SVK dashboard

At some point I was thinking about triage status and how it relates to my development process. I really work with code checkouts in two ways:

  1. For longer features (the stamping changes I’ve alluded to earlier are an example), I tend to check out a copy of the tree, and work on it on and off. For example, I might have an idea for fixing some performance problem, but then have to wait a while for someone else to implement a feature or fix a bug till I can make progress.
  2. For smaller fixes, I sometimes still work from a clean Chandler checkout, just because my usual checkout has a bunch of uncommitted changes.

It’s not unheard of for the second case to morph into the first, e.g. when what I thought was a simple fix turns out to have unexpected quincequonces.

So, inspired by the Chandler dashboard design, I decided to lay out the non-mirrored part of my SVK repository like this:

//work/now
//work/later
//work/done

In //work/now, I’ll have the local branches I’m actually working on at the moment. On disk, I have a checkout of //work/now, which is where I edit, test and commit changes.

If I work on something that doesn’t pan out, I’ll check in my changes (to the local branch, not the remote repository, of course), and then use svk mv to stash it away in //work/later.

Once I’m ready to commit back into the Chandler trunk, I’ll typically do that and then svk mv over into //work/done (actually, into a release-specific subfolder).

In GTD style, my weekly review (so far as code is concerned) starts off with:

bash$ svk ls //work/now //work/later

followed possibly by shuffling branches around, creating new ones, and finally a

bash$ svk update ~/now # where //work/now is mirrored

Don’ts

svk pull in a mirrored branch

I’m still not entirely sure of why this happened (it might have something to do with a Chandler merge I had done in the past), but what I did was:

bash$ # Check out the 0.7alpha4 chandler branch
bash$ svk co //mirror/chandler/branches/0.7alpha4/chandler chandler-0.7alpha4
      ... time elapses ...

bash$ # Try to get the branch’s changes from the remote repository via:
bash$ cd chandler-0.7alpha4
bash$ svk pull

At this point, svk applied all the mainline changes to Chandler, and committed them back to the 0.7alpha4 branch, without asking for confirmation. This seems like counter-intuitive behaviour, and led to the following mondo commit: 12207, which had to be backed out.

svk push

Without arguments, this command will send out all commits in the branch, including merges from the mirror, one by one, without asking you for any commit message.

If you’re using the “commit and pull often” model, like me, you end up with a lovely sequence of commits like the following: 12161, 12162, 12163, 12164, 12165, 12166, 12167, 12168, 12169, 12170.

This may not be what you wanted :).

-- GrantBaillie - 02 Nov 2006

Edit | WYSIWYG | Attach | Printable | Raw View | Backlinks: Web, All Webs | History: r7 < r6 < r5 < r4 < r3 | More topic actions
 
Open Source Applications Foundation
Except where otherwise noted, this site and its content are licensed by OSAF under an Creative Commons License, Attribution Only 3.0.
See list of page contributors for attributions.