Setting up your own git repository

Setup a bare repository

The first thing you'll need to do is create a new bare repository. A bare repository is one that does not contain a working directory, essentially it just contains everything in your standard .git directory. I'll be serving all my repositories from /srv/git, and assuming all the users you want to give access to this repository are in the git group.

# mkdir /srv/git
# git init --bare --shared=group /srv/git/my-awesome-application.git
# chgrp -R git /srv/git/my-awesome-application.git

If you're not going to be sharing this with multiple users, you won't need the --shared=group. Later down the road, if you forgot to specify this option, all it really does is the following:

# chmod -R g+rws /srv/git/my-awesome-application.git

Then, you either need to change the default umask of each user to 002, or you can make /srv/git/my-awesome-application.git/config look like this:

        repositoryformatversion = 0
        filemode = true
        bare = true
        sharedrepository = 1

The key is the sharedrepository = 1 directive. This can be changed to a variety of options, but when set to true or group it ensures all file pushes will use a sane umask of 002. You can find more information about this setting in the git-config(1) man page.

Configuring user access

I personally never setup a git repository without using ssh keys. So have your committers send your their public keys and create users for them. Add these keys to their authorized_keys file, and have them confirm they can ssh in without any issues. Once this is done, you can have them add a new remote repository to git as follows:

# git remote add origin

That's it, they're ready to start pushing code in the normal ways:

# git push origin master

Allowing read only access

Sometimes it's necessary to allow read only access to your repositories, such as for use with Capistrano or performing continuous integration. In this case, using git-daemon is easy and provides faster cloning/pulls than using HTTP or SSH. On Ubuntu, you can install the following package, which sets you up with a runit configuration:

# apt-get install -y git-daemon-run

There's one thing you'll likely want to change in this daemon's arguments, and that is the --base-path option. I use the following in /etc/sv/git-daemon/run:

exec 2>&1
echo 'git-daemon starting.'
exec chpst -ugitdaemon \
  /usr/lib/git-core/git-daemon --verbose --base-path=/srv/git /srv/git

If you took a look at the git-daemon(1) man page, you will see that the base path essentially changes the root for git requests. So, in reality your application lives at /srv/git/my-awesome-application.git, but when pulling over the git protocol, it's as easy as this:

# git clone git://

However, before you can even do that, there is one magic step that makes this all work.

# touch /srv/git/my-awesome-application.git/git-daemon-export-ok

Touching this file tells the git-daemon that you meant for this repository to be publicly accessible (assuming you have the proper ports open, tcp/9418).

Providing a web front end

So your boss wants to see what you've been doing, but has no idea what git is. Why not give him a simple web interface? Luckily, Ubuntu again has a package for this:

# apt-get install gitweb

Gitweb is a simple web interface written in Perl and used as a CGI script. There may be better interfaces out there, but if it's good enough for, it's good enough for me. To get this working, there is one simple change to the configuration file /etc/gitweb.conf:

# path to git projects (<project>.git)
$projectroot = "/srv/git";

The Ubuntu package comes with a simple Apache configuration to get this working at

Alias /gitweb /usr/share/gitweb

<Directory /usr/share/gitweb>
  Options FollowSymLinks +ExecCGI
  AddHandler cgi-script .cgi
root@ip-10-117-65-141:~# vi /etc/gitweb.conf
root@ip-10-117-65-141:~# cat /etc/apache2/conf.d/gitweb 
Alias /gitweb /usr/share/gitweb

<Directory /usr/share/gitweb>
  Options FollowSymLinks +ExecCGI
  AddHandler cgi-script .cgi

That's it, you now have a private repository that can be shared amongst multiple users, as well as a web interface and read-only access to those that need it.