Mirroring SourceForge Git repositories to GitHub

SemanticScuttle, your self-hosted social bookmark manager, uses SourceForge as project hosting space. We're utilizing its Git hosting facilities to coordinate development between several developers. Apart from that, we host file releases there, use the bug tracker and have the demo installation on the SourceForge servers.

GitHub on the other hand is a verrry popular Git repository hosting service that offers some unique features with strong social components.

To attract more developers and make our development progress more visible, I wanted to mirror the SemanticScuttle main Git repository on GitHub. Other people had the same idea but unfortunately failed because the SourceForge Git servers don't allow outgoing connections.

A bit of searching led me to a small bash script that - instead of a post-receive hook - uses a cronjob on a third server (server-in-the-middle) to do the mirroring. Since I have my own server anyway, this solution was chosen.


At first, you need to prepare the server-in-the-middle and equip it with a passwordless SSH key. This key needs to be added to your GitHub account. Using deployment keys does not work since they allow pulling only and are meant for private repos. The alternative is to create a second account on GitHub and add it as collaborator in your project.

The next step is mirroring the SourceForge Git repository on your middle server:

$ git clone --bare --mirror git://semanticscuttle.git.sourceforge.net/gitroot/semanticscuttle/sc SemanticScuttle.git
$ cd SemanticScuttle.git
$ git remote add github git@github.com:cweiske/SemanticScuttle.git
$ git config remote.github.mirror true


After everything is setup, we're going to write our mirror script:

cd /home/cweiske/git/SemanticScuttle.git
git fetch --quiet origin
git push --quiet github

Make it executable, add it to your personal crontab (i.e. every 30 minutes) and you're set. Run it manually once - you need to accept GitHub's remote SSH key.

Using a git alias

Instead of using a shell script, one can use a git alias to keep the configuration in one place:

$ git config alias.update-mirror '!git fetch -q origin && git push -q github'

The ! before the commands tells git that the command to follow is a shell command. Now the cronjob:

10,40 * * * *  cd /home/cweiske/git/SemanticScuttle.git && git update-mirror

I'm looking for a new job. If you can recommend a company in Leipzig/Germany that's looking for a PHP developer, please drop me a mail.

Written by Christian Weiske.

Comments? Please send an e-mail.