2016-05-06

Mirroring git repository and making it accessible via git://

I needed to make some existing git repository, where I can not change way it is served, accessible via git://... Took some googling, so here is the story:
First, install git-daemon package. For RHEL 7 package lives in RHEL Server Optional.

Second, start git daemon via systemd services. I was confused here, because git-daemon ships with git@.service file, which is template unit file, but it does not contain magic %i or %I placeholder.

# rpm -ql git-daemon | grep systemd
/usr/lib/systemd/system/git.socket
/usr/lib/systemd/system/git@.service

Fortunately I do not need to know things. Being able to find them is enough. Basically you have to start (and enable) git.socket and enable it in firewall.

Next, clone copy of the git repository. This one is easy, you just need to create RepoName.git directory in /var/lib/git/ (default - see git@.service file) owned by used nobody (as git daemon runs under that user by default - see service file):

# mkdir /var/lib/git/RepoName.git
# chown nobody:nobody /var/lib/git/RepoName.git
# runuser -u nobody /bin/bash
$ cd /var/lib/git/
$ git clone --bare https://gitservice.example.com/RepoName.git
$ touch RepoName.git/git-daemon-export-ok   # this marks repo as exportable by daemon

Optionally enable git's archive protocol to be used on a repo. Put following into RepoName.git/config:

[daemon]
        uploadarch = true

Last: make the bare repo updating itself periodically from the source. Looks like you can not do simple git fetch:

# runuser -u nobody -- crontab -e
@hourly cd /var/lib/git/RepoName.git; git fetch -q origin master:master

Update 2017-03-21: If it can happen that somebody could change past in the repo, it would be good add --force to the git fetch command you run in the cron so local branches are overwritten when there is some non-fast-forward change in the upstream repo.

$ git fetch origin master:master
From https://gitlab.cee.redhat.com/satellite5qe/RHN-Satellite
 ! [rejected]        master     -> master  (non-fast-forward)

Also added || echo "Fetch of RepoName.git failed" at the end of cron command so I'll be warned when repo fails to sync.

To test if it works, just clone that with git clone git://gitmirror.example.com/RepoName.git.