My blog has been moved to ariya.ofilabs.com.

Wednesday, April 16, 2008

dancing between github and subversion repository

As the next logical step after I wrote about easily using git to work with the subversion repository in Google Code Project Hosting, here is an idea to make your git repository available and still keep it synchronized (in both directions). The use case for my previous blog post is when your partners in crime still stick with subversion but you prefer to use git. Here it is extended further: some (not all) of your contributors start to realize how beautiful git is, try to use it, can't get rid of it and finally decide it to use only git from now on. It would be a crime to ask them to sync to the subversion repository themselves, hence the following dancing. Basically it works like this. In a Unix/Windows machine, do the usual cloning of a remote subversion repository and then push it to github. Your new git fans then clone the fresh git repository. It is amazingly simple, obvious and fast to do it this way.

First of all, register at github. You don't need anything except an email address.

Next, prepare your SSH key which will be used for authentication, this can be carried out in one minute, just follow the instructions. Go back to your account page, copy your public key and paste it there in the SSH Public Keys area. Then, use ssh-agent trick to skip typing your password every single time.

Tip: if you are on a Windows box and your msysgit does not come with the ssh-keygen tool, use the famous PuTTY (known as the terminal emulation with SSH support). In the package, there is a tool called PuTTYgen (PuTTY Key Generator). Simply launch this tool. Click on Generate button and move your mouse randomly for a few second. After that, type in a secret password in the Key passphrase and Confirm passphrase fields. Click the button Save public key and name the file as id_rsa.pub. Choose menu Conversion, Export OpenSSH key and name the file as id_rsa (without any extension). After that, navigate to your user directory, this is typically C:\Document and Settings\Username. Create a new directory named .ssh, if it does not exist yet. Move both id_rsa and id_rsa.pub to this .ssh directory. Now you are set. File id_rsa.pub contains your public key, so copy and paste it into your SSH Key in the github account page.

Now here comes the fun part: create a new repository. Just fill out a few fields and it is ready. Couldn't be simpler, could it?

At this stage, go to your local git working directory (i.e. the one cloned from a subversion repository) and do the following:

git remote add origin git@github.com:joesixpack/coolproject.git
git push origin master

by substituting joesixpack and coolproject with your github login name and the freshly created git repository. Wait a couple of seconds (or minutes), then basically your git repository, which is a clone of the remote subversion repository, is successfully pushed to github. Well done!

To keep both repositories synchronized, you can run a cron job that does the following:

git checkout master
git svn rebase
git svn dcommit
git push origin master

If you have branch(es) in the subversion repository, you still can do that. Just add few more commands and substitute master with your branch(es) name.

Tip: If accidently you push your local branch to github and now you want to remove it, use:

git push repository :heads/branchname

OK. So far so good. Now of course you do not work on a single machine, e.g. you may do the above steps in a Linux server but you would like to work on your Windows laptop. At this moment, you need to prepare another SSH key or just use the same key (e.g. copy the previous id_rsa and id_rsa.pub). Then it is a no-brainer to clone your repository:

git clone git@github.com:joesixpack/coolproject.git

Note: don't be surprised with the amazing speed of doing a git clone. Essentially, you get the whole repository (which contains the full history of the project) in a short period time, probably comparable to the time needed to check out from the subversion repository (which however gives you only some part of the changes history).

Awesome. In just few minutes, you have a git repository which can be synchronized with a remote repository (e.g. in Google Code project hosting). In addition, you can push this repository to github. And still, you can clone the repository in another machine for your pleasure. Now if you want other people to clone your repository, just tell them to do:

git clone git://github.com/joesixpack/coolproject.git
cd coolproject

Once they send patches to you or push their branches, you can do the merge into your git repository and push it to github. Due to the said cron job, the subversion repository (e.g. in Google Code) will get the changes as well. Every now and then, when other contributors commit some changes to the subversion repository, the changes will be also propagated to github. Both parties are happy.

Happy gitting!

2 comments:

Chris Ortman said...

I have been doing this for a while (haven't gotten to the automated part yet though) with the http://castleproject.org code and repo.or.cz

The thing I found tricky was that on my local box when I setup the svn stuff all the svn branches are remotes so when you got to push to the public repo those branches don't get pushed by default.

I wound up always forcing it via git push public +refs/remotes/svn/*:refs/heads/svn/*

Am I missing something, or are you doing this somehow?

Ariya Hidayat said...

@Chris: I create a local branch to track the subversion branch (that becomes a git remote branch). This way, I can do the 'git svn rebase' that also does the merge to the local git branch, if some changes have been committed there.