Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at
Mirroring Subversion from Windows

We’ve been using Unfuddle for hosting our Subversion repositories (for almost two years I think). We’re a consulting shop and we move from project to project. It’s wonderful not having to worry about where the source is physically located or how it’s being backed.

One of our current clients wanted to have the repository for their project physically located at their facility. They gave me access to a couple of Windows 2003 boxes and asked me to get everything setup. I used VisualSVN Server and TeamCity and I had things running smoothly in almost no time. By the way, if you are not familiar with these products, you should be. They are both free (mostly) and very low friction.

Even though the repositories weren’t hosted, we were still using Unfuddle for general project management (such as tracking tickets).

Earlier this week, I was talking to our team lead and explained how Unfuddle integrates with their hosted repositories. For example, if I make comment when committing, such as “fixes and closes #147”, Unfuddle will update the status of ticket #147 as well as associate the changeset with the ticket. I can quickly jump to the committed code directly from the ticket. (Unfuddle is certainly not the only tool that does this, it’s just the one I’ve been using). 

Anyway, the team lead was impressed and asked why we weren’t doing this. Well, because the customer wanted the source on site, and this feature of only works with the integrated repositories.

Mirroring a Repository

What we needed was a way to automatically propagate updates from an Unfuddle hosted repository to client’s onsite repository. The onsite repository could be read-only; that satisfies the client’s need. A couple of quick web searches revealed that Subversion includes a tool doing exactly this: svnsync.

Unfortunately, the directions that I found might be a little opaque to Windows users.

Here’s a step by step of what I did.

  1. I created a new repository to be my destination repository. You have to have a fresh repository to be the destination. With VisualSVN Server, this is merely a right click Create New Repository.
  2. Next, you have to edit the pre-revision property change hook for the destination repository. This hook allows you to execute some logic to determine if a revision property can be changed. By default, svn will say “no, sorry, you can’t change the revision property”. The hooks are located in the hooks directory in the actual folder for the repository. In our case, the hook will be a batch file named “pre-revprop-change.cmd”.

    You can (and maybe should) perform some logic here to verify what’s happening. For example, you could verify that the user performing the change is the user that you expect.

    In my case, I simply said “exit 0”. (If you want it to fail and not allow the change, then exit 1.)

    Update: Ivan Zhakov made a comment that you should avoid exit 0, and verify the user's identity with something like this:

    IF "%3" == "sync_user" exit 0 exit 1

    Once again, in VisualSVN Server this was very easy:

    • right-click Properties
    • switch to Hooks tab
    • select Pre-revision property change hook
    • click Edit
    • and type “exit 0”
  3. Next you need to initialize the destination. This is a one time process that prepares the destination repository for the synchronization process.

    Use the svnsync init command to do this. Mine looked something like this:

    svnsync init %dst_repo% %src_repo% 
    	--source-username buildserver --source-password 1234 
    	--sync-username sync_user --sync-password 1234

    I had the two repositories as environment variables

  4. Now you need to call svnsync sync each time you want to mirroring to take place. If you had sufficient access to the source repository you could actually use another hook or two to trigger the mirroring process. In my case, I didn’t have that access. (Though I think Unfuddle might provide a callback url on commits). Instead, I chose to schedule the sync to execute once an hour during the most active development hours of the day.
  5. My batch file that looked something like this:

    svnsync sync %dst_repo% 
    	--source-username buildserver --source-password 1234 
    	--sync-username user --sync-password 1234
  6. That’s all you need for your repository to be mirrored. However there is one more useful bit to know. It’s very easy to lock up the destination repository if you execute svnsync with bad arguements. In order to remove the bad locks, just run this

    svn pdel --revprop -r 0 svn:sync-lock %dst_repo%

Be sure to use svnsync help if you run into problems. Here’s is a guide that helped me out as well.

P.S. There is some stuff in TortoiseSVN to work with hooks as well, but I’ve never explored it. Honestly, I was able to get the mirroring setup in well under an hour and I only looked at TortoiseSVN as an afterthought.

Update May 18, 2009: Andy Pook added:

You should also check "svnlook uuid" and "svnadmin setuuid". Getting the uuid's in sync will make it _much_ easier to switch your working copy if you need to use the mirror.

Posted 03-11-2009 4:08 PM by Christopher Bennage


About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Google Reader or Homepage Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of
Red-Gate Tools For SQL and .NET


SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
NHibernate Profiler
Balsamiq Mockups
JetBrains - ReSharper
Web Sequence Diagrams
Ducksboard<-- NEW Friend!


Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers


Community Server (Commercial Edition)