- Notifications
You must be signed in to change notification settings - Fork14
Keep git repositories on multiple servers in sync
License
BSD-2-Clause, BSD-2-Clause licenses found
Licenses found
RalfJung/git-mirror
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
git-mirror is a tool to keepmultiple git repositories of the same project in sync. Whenever something ispushed to any repository, the commits will immediately be forwarded to all theothers. The tool assumes to run on a server hosting one of these repositories -so there has to be at least one you can control. A typical use-case would beyour owngitolite installation, thatyou want to keep in sync withGitHub.
This describes how you set up git-mirror on a server running gitolite. For othergit hosting software, please consult the respective documentation on adding githooks. I will assume that gitolite is installed to/home/git/gitolite
, thatthe repositories are sitting in/home/git/repositories
, and that git-mirrorhas been cloned to/home/git/git-mirror
.
First of all, you need to create a file calledgit-mirror.conf
in thegit-mirror
directory. For now, it only needs to contain a single line:
mail-sender = git@example.com
We will also need to add hooks to the git repositories you want to sync. Theeasiest way to manage these hooks is to put them into yourgitolite-admin
repository, so enable the following line in/home/git/.gitolite.rc
:
LOCAL_CODE => "$rc{GL_ADMIN_BASE}/local",
Make sure you read thesecurity noteconcerning this configuration.
Furthermore, uncomment therepo-specific-hooks
line in the rc file or add itto theENABLE
list if it doesn't exist.
Now add a file calledlocal/hooks/repo-specific/git-mirror
to yourgitolite-admin
repository, make it executable, and give it the followingcontent:
#!/bin/shexec ~/git-mirror/githook.py
For every repository you want to be synced, you can enable the hook by addingthe following line to its configuration inconf/gitolite.conf
:
option hook.post-receive = git-mirror
(If you need multiple hooks here, you can separate them by spaces.)
Finally, you need to tell git-mirror where to sync incoming changes to thisrepository to. Add a block like the following togit-mirror.conf
:
[repo-name]owner = email@example.comlocal = /home/git/repositories/repo-name.gitdeploy-key = ssh-keymirror-a = git@server2.example.com:repo-name.gitmirror-b = git@server2.example.org:the-repo.git
Here,local
has to be set to the path where the repository is storedlocally.deploy-key
is the name of the SSH key used for pushing the changesto other repositories.owner
is the e-mail-address that errors occurringduring synchronization are sent to. And finally, the URLs to push to are givenbymirror-<something>
. If these other servers also run gitolite and have asymmetric setup, then no matter where a change is pushed, git-mirror willforward it to all the other repositories.
If one of the to-be-synced repositories is on GitHub, you can obviously not usethe procedure above to sync changes that are arriving at GitHub, to the otherrepositories. Instead, we will use a webhook, such that GitHub tells your serverthat a change happened, and then your server can pull the changes to its localrepository and synchronize all the others. This assumes that the server runningthe webhook also hosts one of the copies of the git repository.
First of all, you will have to configure your webserver to runwebhook.py
asCGI script. Consult the webserver documentation for more details.
Secondly,webhook.py
needs to be able to find the main git-mirror scripts,and it needs to be able to execute them as thegit
user. For the firstpoint, openwebhook.py
and changewebhook_core
to point to the filewebhook-core.py
in your git-mirror clone. If your installation matches thepaths I used above, that should already be the case. For the second point,webhook.py
is usingsudo
to elevate its privileges. You need to tellsudo
that this is all right, by creating a file/etc/sudoers.d/git-mirror
with content:
www-data ALL=(git) NOPASSWD: /home/git/git-mirror/webhook-core.py
Now, if you visithttps://example.com/git-mirror/webhook.py
(replace withyour URL), the script should run and tell youRepository missing or not found.
.
The next step is to add this as a webhook to the GitHub repository you want tosync with, to create a fresh SSH key and configure it as deployment key for therepository, and to configure git-mirror accordingly. For additional security,one should also configure a shared HMAC secret, such that the webhook can verifythat the data indeed comes from GitHub. On the git-mirror side, the HMAC secretis configured with thehmac-secret
repository option.
To make your job easier, there is a scriptgithub-add-hooks.py
that can doall this for you. It assumes that the repository exists on the GitHub side, buthas not yet been configured for git-mirror at all.
To give the script access to your repositories, you need to create an accesstoken for it. Go to "Personal Access Tokens" in your GitHub configuration, andcreate a new token with the permissionsadmin:repo_hook
andpublic_repo
.Add the token and the webhook URL to the top part ofgit-mirror.conf
(rightbelowmail-sender
):
github-token = pastethetokenherewebhook-url = https://example.com/git-mirror/webhook.py
Now you can call the automatic setup script as follows:
./github-add-hooks.py -o UserName -e email@example.com \ -l ~/repositories/repo-name.git/ -n github-repo-name
Notice that the username is case-sensitive! This will do all the setupon the GitHub side, and it will add an appropriate configuration blockto your localgit-mirror.conf
. You still have to manually add thelocal git hook to gitolite. Once you are done, any push happening toeither gitolite or GitHub will be visible on the other sideimmediately. This applies even to pull requests that you merge in theGitHub web interface.
The script will only sync branches when they get pushed to. To initialize theGitHub repository with all the branches that already exist, you can dogit push --all git@github.com:user/repo
.
You can find the sources in thegitrepository (also availableon GitHub). Guess what, thetwo are synced with this tool ;-) . They are provided under a2-clause BSDlicense. See the fileLICENSE-BSD
for more details.
If you found a bug, or want to leave a comment, pleasesend me amail. I'm also happy about pull requests:)
About
Keep git repositories on multiple servers in sync