Notes on serving Git with Debian

Some time ago I started using Git. First for fetching the latest versions of drivers (radeon and radeonhd) and now also for storing my own stuff in it. I won't tell you, why git is so good and so sexy, and why all the other systems suck (well, some really do, some not), but just how to setup a repository and publish it to everyone.

Imagine you have two computers, one called client, and one called server. On the client you will create a repository, push it to the server and from there anyone will be able to fetch it via git or http (or view it via gitweb).
For easier reading, I will mark shell-commands on the server with a s, and on the client with a c. Additionally I will add an $ for user-run commands, and # for root-run. So a command run as root on the server would look like:
s# command

The first step is (as usual) installing some packages. On the client-side git-core should be enough, but don't miss the completion of zsh - you'll love it. On the server-side you need git-core, git-daemon-run and gitweb, you also need an cgi-enabled webserver (I use Apache here, but won't talk about it largely).

Now we can create a repository on the client:
c$ mkdir ~/gittest
c$ cd ~/gittest
c$ git-init-db (or git-init when you use something never than Etch)
put some files into ~/gittest and read the nice git cheat sheet
c$ git-add .
c$ git-commit

You now have a git-repository on your computer. This repository can be pushed to the server.

On the server we need a directory where the stuff will go, e.g. ~/gittest/.
s$ mkdir ~/gittest
s$ cd ~/gittest
s$ git-init-db (or git-init when you use something never than Etch)

The server-side is ready for receiving the data, so on the client we do:
c$ git-push ssh://server/~/gittest master
<type in your ssh password>
The repo should be synced now and ready for going public.

For gitweb, just login as root on your server and do the following:
s# cd /var/cache/git
s# ln -s ~user/gittest/.git/ gittest (note the .git folder!)

http://server/cgi-bin/gitweb.cgi/ should now list the gittest repository and you are done.

So gitweb is done, git:// and http:// fetching to go.

Let's start with git:// one, this is done by git-daemon. It is already running, as you have installed git-daemon-run.
But the repository is not exported by default, you need to do a
s$ touch ~/gittest/.git/git-daemon-export-ok[/b]
And ready, git-daemon exports the repository to git://server/git/gittest/

What comes after git://? Right, http://!
This looks easy, but has a nice possibility to fail, so read on.
The webserver should be configured to follow symlinks, then (on the server):
s# mkdir /var/www/git
s# cd /var/www/git
s# ln -s ~user/gittest/.git/ gittest (note the .git folder!)
From now, you can access the gittest folder by http://server/git/gittest, but git cannot. git clone fails with something like:

Initialized empty Git repository in /home/zhenech/gittest/.git/
cat: /home/zhenech/gittest/.git/refs/remotes/origin/master: Datei oder Verzeichnis nicht gefunden
cd: 464: can't cd to /home/zhenech/gittest/.git/refs/remotes/origin
fatal: : not a valid SHA1
fatal: Not a valid object name HEAD

The solution is easy, but I needed about an hour to find it. Just run the following command on the server:
s$ git-update-server-info

As you will need to run it, after each git push, just enable the post-update hook of the repository, by doing:
s$ chmod +x ~gittest/.git/hooks/post-update

Now you're done, and your repository is available via gitweb, git:// and http://
But you probably want to have a look at .git/description and .git/cloneurl. The first one contains the description (really!) of the repository, this will be shown by gitweb, and the second contains urls, one per line, those will also be shown by gitweb, so your users will know where actually to fetch the stuff.