Exporting a Git repo with 'git daemon'

Categories: Git

Exporting a Git Repo

While my work environment has a ‘central’ Git repository for approved code, I recently wanted to directly share just one branch of my local repo with work colleagues on the local lan. Although there is a vast amount of information about Git on the internet, documentation on a simple procedure to achieve this was surprisingly hard to find. So here is a simple way for a Linux system to provide a read-only view of a branch in a local repo, based on the git daemon command that is part of git-core.

This assumes you are running a recent Ubuntu release (12.10 in my case), and have a recent version of Git installed.

Setting up git daemon and xinetd

First, create a directory to hold a set of ‘bare repositories’. You could just point the daemon directly at the root dir of a single repo to export, but having the option of multiple repos is nice. You could also point it directly at a directory under your $HOME, but having the repo somewhere common (ie not under $HOME) seems right for a system service. I’ve named my repo for-review. I’m also going to make the directory owned by me, as I’ll git push directly to the directory rather than configure git daemon to handle writes too.

sudo mkdir -p /var/git/for-review
sudo chown muyser:myuser /var/git/for-review
cd /var/git/for-review
git init --bare

Now, set up git as an xinetd service; this isn’t absolutely necessary (you can just run git daemon by hand when needed) but generally having a permanent way to share a repo is a convenient thing to have.

Ubuntu doesn’t install xinetd by default (it prefers an ‘upstart’ rule); Fedora doesn’t install xinetd by default either (it prefers a ‘systemd’ rule). However xinetd is available for many platforms, so the config below can be used regardless of OS once xinetd has been installed.

For Ubuntu/Debian systems, installing xinetd is simply a matter of:

sudo apt-get install xinetd
sudo -e /etc/xinetd.d/git  # or 'cat | sudo dd of=/etc/xinetd.d/git' then paste and ctrl-d

The contents of the /xinetd.d/git file should be:

# default: on
# description: An xinetd internal service which serves GIT repo requests
service git
{
  disable         = no
  type            = UNLISTED
  port            = 9418
  socket_type     = stream
  wait            = no
  user            = nobody
  server          = /usr/bin/git
  server_args     = daemon --inetd --export-all --base-path=/var/git
  log_on_failure  += USERID
}                                                                          

And restart xinetd (if you have any problems connecting to git later, check the end of /var/log/syslog for error messages from xinetd)..

sudo service xinetd restart

Now to populate this new repo with some data..

cd ~/my-git-repo
git remote add for-review file:///var/git/for-review
git push for-review topic1  # topic1 is the name of a branch

And at the other end, my colleagues just need to do this to pull my patches into their repo (which was cloned from the same original source as mine)..

git remote add simon-review git://somehost/for-review
git fetch simon-review
git branch --track simon-topic1 simon-review/topic1
git checkout simon-topic1

I can push more patches to the for-review repo as desired, and my colleages can use git pull to see those patches. I can also set up more repos as needed under /var/git.

Alternatives

A simpler option is to point git daemon directly at the main git repo. This does work, and saves the work needed to git push to the bare repository. However when others use git fetch they will see every experimental branch and every rough patch in my local repo, which is a little pointless.

Of course, git daemon can be run directly without xinetd. However it is so little extra effort to set xinetd up.

Pushing via file:// urls of course only works when the bare repo is on the same machine, which is not always desirable, but works for my use-case. And of course nobody else can push to this repo; it only supports me publishing things, but again that’s fine for this use-case.

There are more sophisticated solutions out there that allow fine-grained control of access-rights, pushing by multiple people, pushing from remote hosts etc. See 8 ways to share your git repository for more ideas.

Notes

If you forget what remote mappings you have, git remote is your friend.

Once you have pushed a branch to the bare repo, don’t rebase it!

I have seen a lot of documentation out there referring to git-daemon, but this appears to be obsolete (or at least not supported on my Ubuntu system). There is no separate git-daemon program; daemon is just a parameter to git.