The Move From Subversion to Git
Developer — 28 Feb 2009 12:48 — 1071 days ago

I converted my personal Subversion repository to Git and collected a few notes.

My repository contains the source code of my Mac OS X projects, but also a lot of one-off test programs and experiments. It is a very basic repository; there are no branches at all (maybe I'll use them more with Git) and very few of my projects used tags, so the conversion was straightforward. Because there was so little information to preserve, this is not representative of an SVN -> Git conversion in general, but the notes might still be useful for other people converting their personal repos.

I had about 50 projects in Subversion, some big and some with just one or two files. Each project was in its own subdirectory below the repository root. They were unrelated, so I wanted to separate the projects into their own Git repositories during the conversion.

Converting Projects With Tags

I converted each of the few projects that did use tags manually, like this:

SVN_BASE=svn+ssh://host/path/to/svnroot
PROJECT=album-artwork-assistant
git svn clone --trunk="$SVN_BASE/trunk/$PROJECT" --tags="$SVN_BASE/tags/$PROJECT/versions" "$SVN_BASE/trunk/$PROJECT"
cd $PROJECT
To convert the SVN tags to real Git tags I ran a modified version of a script by Frank S. Thomas:
#!/bin/bash
GIT=/opt/local/bin/git
for branch in $($GIT branch -r); do
    if [ $(echo $branch | egrep "tags/.+$") ]; then
        version=v$(basename $branch)
        subject=$($GIT log -1 --pretty=format:"%s" $branch)
        export GIT_COMMITTER_DATE=$($GIT log -1 --pretty=format:"%ci" $branch)

        echo "Tag $version [Y/n]?"
        read yesno
        if [ -z $yesno ] || [ $yesno = "Y" ]; then
            $GIT tag -a -f -m "$subject" "$version" "$branch^"
            $GIT branch -d -r $branch
        fi
    fi
done

This next step converts svn:ignore properties to .gitignore files

git svn create-ignore
git commit -m 'added .gitignore converted from svn:ignore'
cd ..

All of this gave me a working copy repository in $PROJECT. I converted it to a bare repository like this:

git clone --bare $PROJECT

The bare repo was now in $PROJECT.git

Converting Simple Projects Without Tags

For all the other simple projects without any tags I used this script:

#!/bin/bash

WD="$PWD"
GIT="/opt/local/bin/git"
SVN_TRUNK=svn+ssh://host/path/to/svnroot/trunk
PROJECTS=$(svn list "$SVN_TRUNK" | sed -e 's#/$##')
[ -d logs ] || mkdir logs

for project in $PROJECTS; do
	cd "$WD"
	[ -d "$project.git" ] && continue

	LOG="$WD/logs/$project.log"
	echo "\nconverting $project\n"

	$GIT svn clone "$SVN_TRUNK/$project" > "$LOG"
	cd "$project"
	$GIT svn create-ignore >> "$LOG"
	$GIT commit -m 'added .gitignore converted from svn:ignore' >> "$LOG"
	cd ..
	$GIT clone --bare "$project" "$project.git" >> "$LOG"
	rm -rf "./$project"
done

Move to Server and Checkout Local Repositories

Together with the manually converted ones, this resulted in about 50 bare Git repositories, one per project. I moved them all to a server into a common project root directory and then cloned them back to my computer as local working copies:

for project in $(ssh myserver ls /path/to/git/projectroot); do
    git clone -v ssh://myserver/path/to/git/projectroot/$i
done

Setting up gitweb

I got Git for Mac OS X via MacPorts, both on my client and on the server. It comes with the gitweb web viewer so I activated that on my server with the following Apache configuration:

Alias /git /opt/local/share/git-core/gitweb
<Location /git>
    DirectoryIndex gitweb.cgi
    AddHandler cgi-script cgi
    Options +ExecCGI
</Location>

I had to configure the project root directory in gitweb.cgi:

our $projectroot = "/path/to/git/projectroot";

Now it’s visible externally at http://www.entropy.ch/git/

Rewriting History

After the conversion, the old commits generated by git svn had auto-generated committer e-mail address and name information which differed from my Git configuration values. To clean up and unify this information in the old commits I ran these commands in each working copy:
git filter-branch --env-filter \
    "export GIT_AUTHOR_NAME='Marc Liyanage' \
    GIT_AUTHOR_EMAIL='email@example.com' \
    GIT_COMMITTER_NAME='Marc Liyanage' \
    GIT_COMMITTER_EMAIL='email@example.com'"
git push --force

github

One nice benefit of using Git is that I get to host code on github for free. I push some of my more recent projects there from time to time.


Comments
Posted by Sev on 3 Mar 2009 09:25

Out of pure interest: What's been the reason for you to switch from SVN to GIT? And: Are there equivalents for svn:externals and hooks?

Posted by Marc on 3 Mar 2009 10:41

One reason was to learn something new. My personal repository is a perfect test project for that. No big deal if I screw it up or the tool isn’t that hot after all.

I want to see why so many people like Git so much. The branching and merging features sound promising and I’m already using them. It’s easy to get started with a new feature in a separate branch and then later merge it back to the master when it's stable enough (and especially merge back repeatedly after that). I like some of the little things, for example the ability to add files or messages to the last commit. But of course I just got started so I'm only scratching the surface :-)

I don't know if there's a direct replacement for svn:externals, maybe Git submodules could replace it. I had only one svn:externals property, to a public read-only SVN repository, and I replaced it with a shell one-liner that does the checkout as part of the project build.

Hooks work, and they work well. My server runs the standard “post-update” hook script whenever I push there. That hook runs “git-update-server-info”, which is required to enable the plain HTTP clone URLs I offer (visible in the “URL” field in the gitweb pages).

Posted by Yann Esposito on 18 Mar 2009 10:40

If you want to try something new and like OS X you should prefer bazaar (http://bazaar-vcs.org).

Easier, more intuitive, in brief more the mac way.

It is my two cents.

And may be you also know this post entry from betterexplained wich rocks : (http://snurl.com/e25f6)

Posted by Marc on 18 Mar 2009 14:00

Yann, that betterexplained post looks good, I'll read it when I have a minute.

Regarding Bazaar, I've heard about it and had to use it once to check out a copy of Sparkle. I guess it would work well too for me, but another reason I am more interested in Git is that I see it used and mentioned more often these days. A *lot* more...

Powered By blojsom