How to Update an Outdated Subversion Repository from a Working Copy

Last week the hard drive on my Subversion server failed and I had to rely on my backups to bring up a new server.  My most recent backup was not 100% current, so I ended up with a Subversion repository at revision 935, but a working copy at revision 953.  This is the story of how to reconcile the working copy with the backup so that your latest work is once again in your repository, on a Mac.

First, I looked for a way to simply import my working copy, along with any version info that it might have, but that doesn’t seem to exist.  Then, I tried just committing a new revision to the repository, (it had the same URL as the one on the failed hard drive), but that lead to subversion errors.  It turns out, that if your working copy has a revision number that is higher than that in the repository, you need to check out a new working copy, then copy changes from your old working copy into your new one, the commit your changes to the new working copy.  It sounds easy enough, but there are a couple of gotchas to watch out for, like those pesky .svn folders, so here is a recipe for merging a working copy with an outdated repository, so that the repository is brought up to date:

  1. In your existing working copy, (I’ll call this the “old working copy” from now on), make sure that you’ve done an svn add for any files that are not yet under version control but you want to make the transfer.
  2. Check out a new working copy from the outdated repository, (I’ll call this the “new working copy”).
  3. On the old working copy, do an svn export.  This gets you all of your most recent files, but without any .svn folders in the mix.
  4. In Terminal copy the exported files into the new working copy by running the command cp -R exported_folder/* new-working-copy-folder
  5. [optional] Do an svn infosvn status on the new working copy.  It should show that you need to check in all of the changes you made since the repository was last updated, (or since your last backup).
  6. Commit the changes in your new working copy.   You are finished, (you might want to archive the old working copy at this point in case something didn’t work right).

Your new repository should now have the latest work in it from your working copy.  You will have lost the revision history between your latest backup and whatever you had in your working copy, but you won’t have lost it all, and you will once again be up and running and ready to code, (or write, or whatever).

Of course, you could avoid this whole hassle by making sure your backups are always up to date.

Coding in a Vacuum: Subversion Hooks

A month ago I wrote about setting up an in-house subversion server on the cheap. After a month of using my setup it’s been pretty successful, and I’ve learned even more about subversion.

One of the things I had to do was set up a post-commit hook to publish changes to a webserver.  The site I did this for is still in development, and every commit needed to be pushed to the webserver for testing.  I did this using rsync, (or, since the SVN server is in Windows, cwRsync), and it’s a pretty basic rsync/openSSH setup, but that’s for another day.

What I am talking about today is actually creating the hook script.  What a pain in the ass.  It’s not actually hard to create the script and run it.  On Windows you just write a batch file, debug it, call it post_commit.bat, and drop it in the hooks folder of the repository you want to use.  Sounds simple, doesn’t it?  Why then, when you commit a revision, does Subversion hang, and the script not execute?  Because subversion runs hooks in a near-null environment. This means that nothing is set.  In Windows, not PATH variable.  In everything, pretty much no environment variables of any kind.  So, when you tested your script yourself it ran great because it had lots of support, but now Subversion is running it entirely alone.  Poor, lonely script.

It gets even more frustrating.  Since Subversion is running the script, there’s nothing being printed to the screen to tell you what’s going on, so debugging is like shooting bugs in the dark.

There are a couple of things you can do, however, to make your script work.  First, use an absolute, full, path for everything.  For Windows this means start with the drive letter.  For *nix this means start with a slash.  If that doesn’t work, there’s a trick that allows you to see what’s going on.  You can log the hook’s output to a file.  This way you can find out what’s going on, read the errors, and fix them.  Thanks to Dan Switzer for posting about it. His blog showed up in a Google search and ended my frustration.  In my case, it was some more environment that had to be set up for cwrsync to work properly.

Frugal Subversion Setup

SubversionA while ago I read about, and downloaded the new Versions subversion client.  I had never used subversion before except for grabbing a bit of code once in a while and was excited to try it out.  Even though I usually work alone the idea of versioning is very appealing – that way if anything goes wrong I can revert quickly to a previous working version.

Versions is great, but thats a topic for another post.  The problem I ran into was the 1-repository and 20 MB limit on the free Beanstalk account is too low for me, and the entry-level price of $15 a month is higher than I want to pay.  Maybe if I become a svn-a-holic I’ll pay it, but not right now. I looked at some other free subversion hosts, but decided to set up my own, without paying for anything.  First, the components:

  1. The PC that is now my Subversion server.
  2. VisualSVN Server, (it’s free, and I don’t have to deal with the command-line).
  3. A WRT54G running dd-wrt firmware.
  4. A DynDNS.org account, (so I can access the repository from the outside world – if you have a static IP you shouldn’t need this).
  5. Your own domain name, (optional – just to make the DynDNS.org URL look nicer).

The basic setup is really simple.  Download VisualSVN Server and run the installer.  Choose where you want the program and the repositories to live.  It works like any other Windows installer and only takes a few clicks.  Once installed, the VisualSVN Server Manager provides a GUI to manage the server and you can set up a repository and a user with just a few more clicks.  It’s super easy. 

Once the VisualSVN server is set up you should be able to easily access the repositories from your LAN, but what if you want to work from a coffee shop?  

This is where DynDNS.org comes in.  If you don’t have a static IP address, and it changes all of the time, you will need an update service to make yourself findable from the outside internet.  I looked at several services, but ended up going with DynDNS.org because of its long history, it is free, and it allows enough requests per month that I don’t think I’ll ever hit the limit.   Go ahead and set up a DynDNS.org, (or your provider of choice), account and chose a domain, it’s Pretty simple.

Next, you will have to configure an update client for DynDNS.org.  This is a program that tells DynDNS.org when my IP changes.  Luckily, there is one built into dd-wrt.  In order for the router to know my WAN IP I had to set up the router to connect by PPPoE, (instead of the default DHCP setup, where it gets an IP address from the modem).  Luckily on dd-wrt this is very simple.  Under the setup tab there’s a drop-down for PPPoE, then you find your connection username & password and enter them in the boxes. Hopefully it will be just as easy for you. Once PPPoE is set up, go to DDNS, (a sub-tab of Setup), and enter your DynDNS.org info.  Remember to hit “Apply Settings” each time.

That’s all great, but what happens when you’re at a coffee shop and try to connect? Nothing.  DD-wrt has a pretty strong firewall.  There’s a little more setup still to do.  First, the computer with the SVN server needs to have a static IP within the LAN.  Since I don’t enjoy messing with windows network settings, I do this with the router.  Under the Services tab, in the DHCP server box, there is a place for static leases.  Enter your Subversion Server’s MAC address, hostname, (the computer name), and desired IP address there, then scroll to the bottom of the page and click “Apply Settings.” Now that we’ve got the static IP address, we can go to the NAT/QoS tab forward the the port that your Subversion Server uses to the static IP address you just set up.

Finally, to make things a little nicer, if you have a domain name, and your DNS provider allows you to add records, you can add a CNAME record to point a subdomain do your DynDNS.org domain, giving you access to your Subversion repositories via the URL subdomain.yourdomain.com.  Fancy!

One note on testing:  dd-wrt seems to be smart and knows if a request is coming from the LAN or the internet, so it’s kind of hard to test your remote access from within your LAN.   I was able to get around this by logging in to a remote desktop session of another windows computer that is far, far, away from my LAN.

That’s it, now you should have a fully-function SVN server of your own, without paying a penny. Have fun, and feel free to experiment with your code – you always have the previous version to roll back to!