Thursday Night

Paul Betts’s personal website / blog / what-have-you

Moving git repositories to SVN/TFS

Git is great!

At my job, I’ve been working on a project for several months now. Since I needed a cheap, easy VCS, and I wanted to learn the next cool thing, I decided to use Git, to shuffle files between computers and keep a history of commits. It turns out, Git is really, really awesome – beats the pants off of the customized Perforce we use at work. The individual pieces of our project are starting to come together, so one of my coworkers started the arduous project of setting up Team Foundation Server. I was interested because its integration with VS (especially being able to see the changes annotated in the code in the gutter – very cool), as well as the “Trac-like” stuff that I’ve never bothered with in my personal projects.

The plan from 10,000 feet

Unfortunately, getting my Git history into TFS hasn’t been the easiest thing, but it can be done. If you’re not familiar with TFS as a VCS, it’s pretty similar to Perforce (surprise!), but without a solid command-line client. Fortunately, via Scott Hanselman’s Blog, I found SVNBridge. Basically, you give it a TFS server, and it’ll pretend to be a local SVN server. This program is under really heavy development (aka “isn’t finished yet”), so you’re gonna run into some problems; run it under VS 2005/2008 debugger to see what goes wrong, it’s usually some dumb TFS rule.

Since Git has a really great tool called git-svn which allows us to pull and push to Subversion repositories, we’ll use this hacky structure to push our Git repository to a new blank TFS repository. Note that this method works for a regular Subversion repository too, just use your SVN URL instead of SVNBridge’s fake URL. We do some trickiness later because git-svn dcommit doesn’t seem to work as advertised, so we have to specifically commit each revision using git-svn set-tree (not manually, but it’s still hacky).

The guts – copying an example repo from Git to Subversion

Start up SVNBridge (under the debugger!), and point it to your TFS repository. Make sure this repository is blank (or at least doesn’t have any of your project files in it), or else TFS will have a fit. However, if the repo is completely empty, git-svn will have a fit, so make sure to commit some blank file to the TFS/SVN repository first. git-svn needs this to base its merge on.

In this case, our Subversion “repository” is mapped using SVNBridge to http://localhost:8081, and our git repo is at http://git.example.com. Now here’s the commandline magic – make sure to run this in a Bash(or zsh/ksh/whatever) shell, not under cmd – git doesn’t like non-sh shells.

# Set up a repository connected to SVN
mkdir tmpwc && cd tmpwc
git-svn clone http://localhost:8081/SomeProject .

# Merge in our source Git repo
git pull http://git.example.com

# Grab all of the commits and write them to a file, from first to last
# If you want to, you can manually edit this file first
git log –pretty=oneline –reverse > commits

# Commit them all, one by one
cat commits | cut -d ‘ ‘ -f 1 | xargs -l1 git-svn set-tree

If you’re lucky, that worked. If not, keep hacking at it and you’ll eventually get it to do your bidding.

Written by Paul Betts

December 2nd, 2007 at 11:30 pm