All things evolve, and if you don’t keep up you will fall behind.
The new hotness in version control systems are distributed systems like Git and Mercurial. I have used Subversion for many years and have been mostly satisfied with it. I’ve known about Git and Hg but just didn’t have reason to delve into them. But over the past some months I’ve been exploring Git and really like it. It’s time to move Hsoi Enterprises’ source control from svn to git.
Here’s the kink.
About a month ago I obtained new server hardware, which also brought about a major OS change. I brought my svn repository over, but for whatever reason it refuses to work. I’ve pounded endlessly upon apache, but it refuses to allow me access to my repository. Yes, I am giving up. In the end it doesn’t matter if I can get svn serving, because I’m abandoning it. All I really want is to move my existing svn repositories in git, just let me have my data and all my history.
Thankfully my Google searching for ways to beat apache turned up some pages that reminded me about svnadmin dump and load.
It’s been a manual process, but it works something like this (using the PracticeDeck repository as example):
1. Dump the old svn repository
Navigate to the physical svn repository on the server.
$ svnadmin dump PracticeDeck > PracticeDeck.dump
2. Import the svn repository
Since git works locally, I copied the PracticeDeck.dump file to my main dev machine (via AFP file sharing). Fired up the Terminal, cd’d to the place I wanted the git repository, and started work in there.
Yes, you will have to create a local svn repository to import the dump into, which is then used for the git import. This local svn repo is just a temporary artifact.
$ svnadmin create PracticeDeckSVN
$ svnadmin load PracticeDeckSVN < PracticeDeck.dump
3. Create a file to map the authors.
Creating an authors.txt file is useful since git likes to track each commit by the author and their email address, which is slightly different from svn. The file is simple, merely using a “svn-name = git-name” mapping. But I had a problem! In my case my svn repository had no user information! So how to map this?
(no author) = John C. Daub <firstname.lastname@example.org>
The “(no author)” is the magic apparently.
4. Create the git repository
$ mkdir PracticeDeck
$ git init PracticeDeck
$ git svn clone file://$(pwd)/PracticeDeckSVN ./PracticeDeck -A authors.txt --stdlayout
There are numerous ways you can format this command. Some people use the “-no-metadata” option, but I see no harm in doing that and keeping it around. Some Google searching turned up that lacking this created problems down the line, but others just don’t want the clutter. It’s up to you. I opted to keep metadata because there’s no harm (that I’m aware of). I’d rather have it and not need it than need it and not have it.
I’ve also seen some others use different options than –stdlayout, but since my stuff was mostly standard, I just used that to keep it simple.
For the most part, this handled things fine. I’ve seen some folks go in and do some other manual fetching and branching and tagging to migrate their stuff better, but my stuff was simple enough and colored within existing lines for the most part, that the basic clone worked out fine for me.
6. Add other files
I have a habit of keeping some other files around. For example, I’d keep the built binary, the .dSYM file, and other artifacts of release builds. Granted, this is less important to do manually now with Xcode 4’s Archiving, but it’s a holdover habit and even if I don’t do it in the future, certainly I’d like to maintain what I already have.
In my case, my svn repository broke from standard convention and had a layout like this:
/root /archives /branches /tags /trunk /vendor
In this case, it’s the “archives” directory that mattered. Git doesn’t quite work like svn in this regard, in that there isn’t some separate folder structure you can have (e.g. typically all you work with locally is the “trunk”). I must admit, as soon as I ran into this, I felt like gee, this is one vote for Subversion over Git! But you can deal with it easily enough. For example, I just created an “archives” folder in my normal source code (git) working copy and exported the svn “archives” contents into that folder. Yes, I had to fire up my svn client (svnX), create a file-based repository entry that pointed to my “PracticeDeckSVN” folder, and then I could browse around and do as I needed to. Worked fine. I’m not sure this “archives” folder will make for a good long-term solution… maybe I’ll have another repository somewhere else, or just a simple file structure somewhere because it doesn’t necessarily need to be in git. But for right now, this is fine.
7. Clean up
Delete the “PracticeDeckSVN” folder.
I opted to keep the .dump files in a folder, just in case I need to come back to them later (I can always trash them later)
And then one thing I liked I read about here. When you use “git svn” it keeps a connection to the svn archive as a remote. Well, I don’t want that because svn is going away. So what to do?
$ git config --remove-section svn-remote.svn $ rm -Rf .git/svn/
And life is good.
If you want, you could go in and delete git branches:
$ git branch -d trunk
In this case, “trunk” will be redundant with “master”, and trunk is an svn-ism that we can get away from.
Of course, any other cleanups and changes you want to do to your new git repository is up to you. Me, I don’t really care. Small team, and I really just want to have all the old history. If the tags and branches and whatever aren’t perfect, that’s alright. It’s good enough for me to get by and move forward in the land of Git.