Kerry Buckley

What’s the simplest thing that could possibly go wrong?

Maintaining a Read-Only svn Mirror of a git Repository

8 comments

Our team been using git at work for the past couple of years, but there’s now a corporate push to keep everything in a centrally-managed subversion repository. We lost the battle to get corporate approval for git (apparently we’re happy to employ people to write our code that we wouldn’t trust to be able to use a DVCS), but at least we have agreement that we can continue using git as long as we mirror the code into subversion.

This isn’t entirely trivial to do using git-svn (which is really intended for use with subversion acting as the master), but I found a few sets of instructions on the web. The simplest one was this Nano Rails blog post, which is what the steps below are based on.

The end result should be a subversion trunk which is a mirror of the git repository’s master branch. This is only intended to be a one-way mirror – I wouldn’t recommend also trying to commit into subversion and merge those commits back upstream into git.

You need to have git-svn installed (this comes with the default installation, or you can use the +svn option when installing via MacPorts).

Create subversion repository

Create the subversion repository in the usual way, using svnadmin.

Once you’ve got an empty repository to point to (we’ll imagine it’s at http://svn.example.com/foo), you also need to commit an initial version (I also created a trunk directory in this step, in case we later decide to mirror branches too):

svn co http://svn.example.com/foo
cd myproj
svn mkdir trunk
svn commit -m'Created trunk directory'

Once this is done, you can throw away the directory you checked out of subversion.

Set up the subversion remote

This step, and subsequent ones, need to be performed on whichever git repository you want to mirror from.

In our case, we have a central repository running on a local installation of Gitorious. This is a bare repository, which makes things a little tricker, as git-svn requires a working copy. To get round this, we create a clone, which we’ll use as an intermediate step in the mirroring process. If you’re not mirroring a bare repository, you can omit this step.

The repositories we want to mirror are in ~git/repositories, and we’ve created a directory ~git/repositories/svn-mirror where we’ll put the clones. For this example, we’ll use a repository called foo/mainline.git.

Create the clone:

git clone ~git/repositories/foo/mainline.git ~git/repositories/svn-mirror/foo
cd ~git/repositories/svn-mirror/foo

Now add the following to .git/config (with the correct svn URI, of course):

[svn-remote "svn"]
	url = http://svn.example.com/foo/trunk
	fetch = :refs/remotes/git-svn

Now do an initial fetch of the empty subversion remote, and check it out as a new git branch (called svn):

git svn fetch svn
git checkout -b svn git-svn

You can now merge in all your commits from master, and push them to subversion. You’ll probably want to go and make a coffee or something while the dcommit runs – if you haven’t used subversion for a while you’ve probably forgotten just how much slower it is than git.

git merge master
git svn dcommit

To allow pushing to svn from master, rebase master to the svn branch (which can then be deleted):

git checkout master
git rebase svn
git branch -d svn

At this point you should be able to manually update subversion at any time by running git svn dcommit from the master branch.

Automating subversion updates

In theory it should be possible to set up post-receive hooks to push from the gitorious repository to the clone and from there to subversion, but I decided to separate the two by just periodically polling for changes, as we don’t really care about subversion being right up-to-the-minute. To poll hourly, add something like this to the git user’s crontab:

0 * * * * (cd /usr/local/git/repositories/svn-mirror/foo;/usr/local/bin/git pull origin master;/usr/local/bin/git svn dcommit) >>/usr/local/git/gitorious/log/svn-mirror.log 2>&1

Technorati Tags: , , ,

Written by Kerry

October 6th, 2009 at 10:17 am

Posted in git,Software

8 Responses to 'Maintaining a Read-Only svn Mirror of a git Repository'

Subscribe to comments with RSS or TrackBack to 'Maintaining a Read-Only svn Mirror of a git Repository'.

  1. Thanks for the article, I used this with some modifications to get my svn mirrors. I had slightly different starting circumstances, plus some merge issues that I worked out — but you got me on the right track. I cited this article in my post here.

    Christopher

    23 Mar 10 at 8:23 pm

  2. Thanks for your tips. But I have a question: what if there is a conflict when you run git pull origin master with cron? You could not do git svn dcommit, then. Right? Or it isn’t possible?

  3. Vítor, you’re right. In our case we just needed to back the git repo up to subversion, with no-one committing directly to the svn repo.

    Kerry

    16 Apr 10 at 9:06 pm

  4. One thing to note: this will probably work a lot more smoothly if you keep master’s history linear, ie rebase other branches onto master before merging them in, so merges into master are always simple fast-forwards.

    Kerry

    14 Dec 10 at 11:36 am

  5. git-svn is not the best too to import Git history to SVN, as it supports only linear history, doesn’t convert ignores and so on. You should consider trying SubGit (http://subgit.com) project for that purpose.

    http://stackoverflow.com/questions/10014054/git-2-svn-migration/10564836#10564836

    And as additional feature: the mirror can be not read-only but even writable (and yes, pushing to SVN and Git at the same time is safe).

    Dmitry Pavlenko

    24 Jun 12 at 3:46 pm

  6. Kerry: nice writeup, thanks.

    A quick question: when you do a “svn log http://svn.example.com/foo/trunk“, all the commit log messages are like:

    Merge branch ‘master’ of …

    Is there a simple way (or script out there somewhere) to consolidate all pertinent Git commit message in the mirrored Git master?

    ming

    23 Jun 14 at 7:40 pm

  7. @ming Sorry, not sure (it’s a long time since I’ve used svn now!)

    I’m surprised the commit messages all look like that though – from what I remember when I used git-svn it kept them intact.

    Kerry

    26 Jun 14 at 10:39 am

  8. […] Clone your git repo somwhere on your machine. Open .git/config and add the following(from http://www.kerrybuckley.org/2009/10/06/maintaining-a-read-only-svn-mirror-of-a-git-repository/): […]

Leave a Reply

You must be logged in to post a comment.