Two way git mirror: Difference between revisions

Jump to navigation Jump to search
Content deleted Content added
imported>Hendrik Brummermann
Created page with "== Motivation == == Setup == == Mirror == We use the following script to do the actually mirroring. It can be invoked with the name of a known repository as parameter or wi..."
imported>Hendrik Brummermann
added support for tags
 
(28 intermediate revisions by the same user not shown)
Line 1: Line 1:
This articles describes how to setup a two way mirror of git repositories. I hope this article will be helpful as it works around a number of caveats for two way git mirrors.
== Motivation ==


== Setup ==
== Setup ==


We create a clone from either of the upstream repositories. It is important that the repository is bare.
== Mirror ==

<source lang="bash">
cd /srv/gitsync
git clone --bare git@github.com:[account]/[repository].git
mv [repository].git [repository]
</source>

Now we delete remote "origin" and configure a remote setting for each upstream repository instead:
<source lang="bash">
cd [repository]
git remote remove origin
git remote add github git@github.com:[account]/[repository].git
git remote add sourceforge ssh://[account]@git.code.sf.net/p/[repository]/code
</source>

The mirroring should happen right after changes have been pushed to one of the repositories. Therefore a webhook is required to trigger the mirror script.

On Sourceforge a project admin needs to enable it at Admin -> Tools -> Repository -> Webhooks. On Github it is at Settings -> Webhooks &amp; Services -> Add Webhook.

== Mirror scripts ==


We use the following script to do the actually mirroring. It can be invoked with the name of a known repository as parameter or with the "--all" flag.
We use the following script to do the actually mirroring. It can be invoked with the name of a known repository as parameter or with the "--all" flag.
Line 17: Line 37:
git fetch --all -p
git fetch --all -p
# push branches from sourceforge to github and via versa.
# push branches from sourceforge to github and via versa.
git push github "refs/remotes/sourceforge/*:refs/heads/*"
git push github "refs/remotes/sourceforge/*:refs/heads/*" "refs/tags/*:refs/tags/*"
git push sourceforge "refs/remotes/github/*:refs/heads/*"
git push sourceforge "refs/remotes/github/*:refs/heads/*" "refs/tags/*:refs/tags/*"
}
}


Line 56: Line 76:
// validate repository name to prevent injection and traversing attacks
// validate repository name to prevent injection and traversing attacks
$repo = $_REQUEST['repository'];
$repo = $_REQUEST['repository'];
if (!preg_match('/^[a-zA-Z0-9]$/', $repo)) {
if (!preg_match('/^[a-zA-Z0-9]+$/', $repo)) {
die('invalid repository name');
die('invalid repository name');
}
}
Line 63: Line 83:
system('sudo -Hu gitsync /usr/local/bin/gitsync '.$repo);
system('sudo -Hu gitsync /usr/local/bin/gitsync '.$repo);
</source>
</source>



== Security ==
== Security ==
Line 72: Line 91:


== Deleting branches ==
== Deleting branches ==

There is one caveat: Deletion of branches is not mirrored, but deleted branches are resurrected by the mirror script.

To delete a branch for good, the following commands need to be executed in quick succession.

<source lang="bash">
git branch -d [branchName]
git push github --delete [branchName]
git push sourceforge --delete [branchName]
</source>