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 $PROJECTTo 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 bygit 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.
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).
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)
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...
|



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?