You are fond of GitHub, the decentralized source control management site?
You are a happy user of Redmine as a project management tool?
But at the same time you are facing a difficult choice: putting your Git code repository on GitHub to benefit from its ergonomic web interface and team cooperation capabilities or putting it on Redmine to interface source control management and ticket tracking?
Then this article is for you! It explains how to automatically synchronize your Git repositories between GitHub and Redmine!
This technical tip is for the Git Distributed Source Control Management tool. It explains how to configure a read-only copy of a remote Git repository on a local
server in bare mode and automatically synchronize its contents (one way only, from the remote repository to the local copy).
Lets suppose I use GitHub to store some of my projects but at the same time I want to have a local repository copy at hand in order for Redmine to link source code revisions and tickets together in the « Activity » tab, like in this example.
Redmine can only index a local Git repository, as opposed to Subversion whose repository can be accessed remotely, it is therefore necessary to maintain a local repository on the Redmine server.
Let's suppose that:
Creating a local bare repository
On the Redmine / Git server:
- We clone the GitHub repository locally in bare mode. In this example the URL of the remote repository is:
git clone --bare git://github.com/Farzy/multilog-axfr.git multilog-axfr.git
Initialized empty Git repository in /srv/gitosis/repositories/multilog-axfr.git/
remote: Counting objects: 76, done.
remote: Compressing objects: 100% (67/67), done.
remote: Total 76 (delta 31), reused 0 (delta 0)
Receiving objects: 100% (76/76), 25.33 KiB, done.
Resolving deltas: 100% (31/31), done.
- We must now manually configure the remote branch tracking and then synchronize the repositories:
git remote add origin git://github.com/Farzy/multilog-axfr.git
git fetch -v
* [new branch] master -> origin/master
Automatic repository synchronization
Usually, a working copy is updated with the following commands:
git fetch origin
git merge origin
But merging does not work with a bare repository. We have to cheat. We're going to use the following commands, that we will launch automatically using the cron task scheduler.
Let's suppose that:
- The local git repositories belong to the
- The server's
cron version supports advanced functionalities like the
We can then use the following configuration file, /etc/cron.d/synchronize-git-respositories:
# One-way synchronization of a local and remote bare Git repository.
# Repeat this line for each repository.
*/30 * * * * gitosis cd /srv/gitosis/repositories/multilog-axfr.git && git fetch origin && git reset refs/remotes/origin/master > /dev/null
The local repository will automatically be updated every half hour.
git fetch updates the refs/remotes/origin/master reference without touching the HEAD branch.
git reset refs/remotes/origin/master make the HEAD branch point to the same commit as the remote branch.
A word of caution
You must not commit in the local repository or you'll loose all your changes after the automatic synchronization: the local repository is read-only, for Redmine's use only for example.
The cron script does not check all potential errors. The «
> /dev/null » redirection is necessary because the «
git reset » command, when executed on a bare repository, displays some messages (see below) that we always want to ignore:
multilog-axfr.git % git reset refs/remotes/origin/master
.gitignore: needs update
LICENSE: needs update
README.md: needs update
Rakefile: needs update
bin/multilog-axfr.rb: needs update
multilog-axfr.conf-sample: needs update
samples/root/slaves/farzy.org: needs update
samples/root/slaves/linux.org: needs update
samples/root/slaves/pragmatic-source.com: needs update
test/slave_zones_spec.rb: needs update
Thanks to this system your code base can peacefully coexist on both Redmine and GitHub!