Your Private Git-Svn Gateway

Posted by mb0 on November 6th, 2008
Acting like a git, enduring the subversion.

No, this entry is for programmers and about version control systems. If you are still reading, I guess you do work with svn and maybe heard of Git.

I heard of git some time ago watching the google tech talk where Linus bashes cvs and svn, but did not consider a switch back then. Eclipse support is bad and it is yet another thing you need the time for to grok.

Well times change and with every new project started you have a new project to maintain. When you do web stuff, things get even more complicated. You will find yourself using overcomplicated directory structures to manage different settings and building a mess of scripts to make deployment and staging bearable.

Recently i heard more and more about people and projects switching to git and the benefits of it. Once hooked on git you will even consider to install the Eclipse plug-in eGit and think you can do without the synchronize perspective.

You probably want to switch you private projects to git because it is easier to maintain. But what is with all other svn repositories? There is git-svn which lets you import from svn. Ok, now you have a bunch of local git repositories, which is nice because you don't have to work on the svn trunk directly and thus have very fast diffs, logs, switching etc. But wait, if you work on your laptop all gains are lost. You can off course sync them locally all the time, but who does that, right? You are usually connected to the internet and have a server anyway? You think of your private git-svn gateway already? Fine, follow these instructions to install gitosis and setup a secure git repository.

However you will soon run into problems. Public git repositories are usually bare , that means they have no working directory and thus git svn and merging is not easy. I ran into those problems too but found some resources explaining how to use git svn with bare repositories.

At this point i have to inform you, that i don't know whether or not this git-svn-gateway idea makes any sense at all, that there might be mistakes or misconceptions on my part and that better solutions might be out there. The example uses Ubuntu 8.04 as root. My advice is to use a small svn repository for testing first.

# goto the repositories dir of your gitosis setup (might vary)
cd /var/git/repositories
# create a repository named project
mkdir project.git; cd project.git
git --bare init
git --bare svn init -s http://yourserv.er/svn/project
git config svn-remote.svn.fetch project/trunk:refs/remotes/trunk # project might vary
# grab the whole svn repo may take long
git --bare svn fetch
# make things small, try du -m . before and after
git repack -d
# add some options so you can fetch from svn
git config remote.origin.url .
git config remote.origin.fetch +refs/remotes/tags/*:refs/tags/*
git config --add remote.origin.fetch +refs/remotes/*:refs/heads/*
# add update hooks and change ownership to your git user
chmod +x hooks/post-update
chown -R git:git ../server.git
Now that the server side is all set up you can clone to your local desktop and start the work.
git clone git@yourserv.er:project.git
# edit something
git commit -a -m "commit from git client"
git push
After you pushed some changes to your git server you might want to commit them to the svn repo form there.
# fetch svn data
git --bare svn fetch
# make sure there are no conflicts
git diff trunk master
# be careful this overrides any conflicts and unfetched changes
git --bare svn --id trunk commit-diff -rHEAD trunk master
Now you want to update your git server
# fetch the svn data again
git --bare svn fetch
# inspect the changes
git diff master trunk
# and fetch to your master
git fetch
To update your client run
git fetch
git rebase origin
if a git user and a svn user have both committed changes we want the git user to handle the problem.
# on the server update svn data
git --bare svn fetch
# see the conflicting changes
git diff master trunk
# and just fetch the svn repo into master
# which will reset the HEAD and add the commits from svn
git fetch
# you probably get unreachable/dangling commits
git fsck --unreachable
# you can prune them sometime
git prune
Now that the git server reverted our change we need to rebase it locally and push it up again.
git fetch
# take a look at the diff
git diff master origin/master
# rebase and resolve conflicts
git rebase origin
# push changes back to the server
git push
As i said above i am very new to git and have not tested this stuff with actual work or real life problems. But there is not much about it on the net and i would be happy about any suggestion.

Have fun!


edits

  • remote trunk should use refs/remotes/trunk not refs/remotes/master to avoid unambiguous naming

Comments