Répondre au commentaire
Automatic synchronization of 2 git repositories
-
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!
Description
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).
Use case
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.
Configuration
Let's suppose that:
- We host a project on GitHub, for example http://github.com/Farzy/multilog-axfr
- We have a local Redmine instance, for example http://opensource.pragmatic-source.com/projects/show/multilog-axfr
- The local Git repository on the server hosting Redmine is:
/srv/gitosis/repositories
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://github.com/Farzy/multilog-axfr.git.
cd /srv/gitosis/repositories git clone --bare git://github.com/Farzy/multilog-axfr.git multilog-axfr.git
Output:
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:
cd multilog-axfr.git git remote add origin git://github.com/Farzy/multilog-axfr.git git fetch -v
Output:
From git://github.com/Farzy/multilog-axfr
* [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
gitosisuser, - The server's
cronversion supports advanced functionalities like the/etc/cron.d/folder.
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.
Explanations
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.
It's done!
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!
