Reply to comment

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:

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.
  1. cd /srv/gitosis/repositories
  2. 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:
  1. cd multilog-axfr.git
  2. git remote add origin git://github.com/Farzy/multilog-axfr.git
  3. 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:

  1. git fetch origin
  2. 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 gitosis user,
  • The server's cron version supports advanced functionalities like the /etc/cron.d/ folder.

We can then use the following configuration file, /etc/cron.d/synchronize-git-respositories:

  1. # One-way synchronization of a local and remote bare Git repository.
  2. # Repeat this line for each repository.
  3. */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:

  1. multilog-axfr.git % git reset refs/remotes/origin/master
  2. .gitignore: needs update
  3. LICENSE: needs update
  4. README.md: needs update
  5. Rakefile: needs update
  6. bin/multilog-axfr.rb: needs update
  7. multilog-axfr.conf-sample: needs update
  8. samples/root/slaves/farzy.org: needs update
  9. samples/root/slaves/linux.org: needs update
  10. samples/root/slaves/pragmatic-source.com: needs update
  11. test/slave_zones_spec.rb: needs update

Thanks to this system your code base can peacefully coexist on both Redmine and GitHub!

Reply

The content of this field is kept private and will not be shown publicly.