How to setup a server that will automatically receive and save anything you git push to it.

I wanted to host my git repositories on a private server but didn’t want to setup something big like Gitlab or Gitorious to do it. I also wanted to be able to git push anything and have the server automatically create a new git repository and store the data.

The easiest way I found to do this was to use gitreceive by Jeff Lindsay who created Dokku.

I followed the instructions for setting up gitreceive but ran into a small hangup when trying to push a repository:

$ gp home master
Counting objects: 1032, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (1020/1020), done.
Writing objects: 100% (1032/1032), 5.04 MiB | 1.20 MiB/s, done.
Total 1032 (delta 82), reused 0 (delta 0)
To git@foo.co:bar
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'git@foo.co:bar'

The error pre-receive hook declined means that the receiver script that gitreceive installs to /home/git was crashing. However, the default receiver script does nothing which makes it odd that it would crash. The cause of the problem is that gitreceive is piping the output of git archive to the receiver script. The receiver script does nothing so exits before cat cat finish. This causes cat, then gitreceive to crash with a non-zero exit status causing the pre-receive hook declined error.

The solution to this is simple. Add the following line to the receiver script:

cat /dev/stdin > /dev/null

This will wait for gitreceive to finish piping the archived repository before exiting. Now you can push a new repository and gitreceive will automatically create and receive it.

$ git push home master
Counting objects: 1032, done.  Delta compression using up to 4 threads.
Compressing objects: 100% (1020/1020), done.
Writing objects: 100% (1032/1032), 5.04 MiB | 1.20 MiB/s, done.
Total 1032 (delta 82), reused 0 (delta 0)
 __________________
< Have a nice day! >
 ------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
To git@foo.co:bar
* [new branch]      master -> master

Note: you do not need to save a copy of the archive that gitreceive is piping into the receiver script. The repository’s data is still being saved in /home/git/<reponame>. You can verify this by running git clone.