NOTE: this page is out of date!  I wrote it in December 2006, 14 months before GitHub was launched.  Definitely use GitHub if you can.

This page describes how to host your own repository using gitweb.

How to Publish your Repository

This document describes various techniques for you to publish a git repository, and how both anonymous and authenticated users can access your repository and contribute to it.

The easiest way to publish your repo is to just use Petr Baudis's public site, http://repo.or.cz/. This offers a full git daemon, gitweb, and http support.  It's not very pleasant to use but it's reliable and easy.

If you're sure you want to host your repository yourself, there are 4 ways to publish it: http/https, rsync, gitweb, and the local filesystem (easily publish via file shares or NFS).

Export your Repository

All of these techniques require you to first place your bare repository on the server. "bare" means it has no working directory -- it's only packed objects. In other words, instead of containing a .git/ directory, a bare repository is itself a .git directory (with a few changes, see git-update-server-info).

$ git repack -d                                # compress
 $ git clone --bare -l . /tmp/your-proj.git     # export project in current dir
 $ git --bare --git-dir=/tmp/your-proj.git update-server-info

Now, place the /tmp/proj.git directory on the server using scp, rsync, tar, whatever you want. For example:

$ cd ..
 $ scp -r your-proj.git example.com:public_html/projects

Downloading with HTTP

Once you export to a public HTTP server, users can immediately start working with it.

$ git clone http://u32.net/projects/your-proj.git

HTTP is light on server CPU and memory because the repository is just static files. However, git operations over HTTP tend to require a lot of round-trips and become very wasteful. If you're working with large archives or slow links, you'll probably want to use gitweb.

Of course, users will not be able to push via HTTP. They should publish their tree, and then ask you to pull from it. It's also very common to send patchsets via email.

gitweb

gitweb provides a nice front-end for the browser. It also provides RSS feeds of changes to the tree.

To run gitweb, your server must have Perl, cgi support, and a working git executable.

Install git on the server

Probably easiest to just grab it from the dailies.

There is no need to build with libcurl because you will never execute a git push or git pull on this machine. Yes, the repositories on the server will be pulled and pushed, but it is always initiated by another machine -- we only listen.

$ wget http://www.codemonkey.org.uk/projects/git-snapshots/git/git-latest.tar.gz
 $ tar zxvf git-latest.tar.gz
 $ cd git-DATE
 $ make prefix=/your/bindir NO_CURL=1 install

Configure the web server

This section describes a technique that works well in a shared hosting environment (I'm running http://git.u32.net on dreamhost). If you are running a dedicated server, you might prefer the instructions in gitweb/README.

If 'which perl' doesn't return /usr/bin/perl, you'll need to change the executable on the first line of gitweb.cgi.

$ cp gitweb/gitweb.cgi ~/git.u32.net/htdocs/cgi-bin
 $ cp gitweb/gitweb.css ~/git.u32.net/htdocs
 $ cp gitweb/git-* ~/git.u32.net/htdocs       (copy logo and favicon)

Also in the ~/git.u32.net/htdocs document root, create a file named .htaccess:

DirectoryIndex /cgi-bin/gitweb.cgi

Now your website's document directory should look like:

./htdocs/gitweb.css
 ./htdocs/cgi-bin/gitweb.cgi
 ./htdocs/.htaccess
 ./htdocs/git-favicon.png
 ./htdocs/git-logo.png
 ./htdocs/gitweb_config.perl   (created in the next step)

Configure gitweb

Set up ~/git.u32.net/htdocs/gitweb_config.perl. Here's an example:

$projectroot = "/home/bronson/u32.net/git";
  $GIT = "/home/bronson/lib/bin/git";
  # $home_link_str = "projects";  # what to call the root link in the path
  
  $site_name = "git.u32.net";     # Appears first in the window title
  # $site_header = "header.html"; # file that contains header for all pages
  # $home_text = "intro.html";    # intro on home page above list of projects
  # $site_footer = "footer.html"; # file that includes footer for all pages
  # $stylesheet = "mystyles.css"; # stylesheet to override default styles
  # $logo = FILE;                 # a logo to replace gitweb logo in upper-right
  # $ favicon = FILE;             # replace the default ---/+++ favicon
  
  # $projects_list = "./" # source of projects list
  # $export_ok = "";      # show repository only if set AND this file exists
  # $strict_export = "";  # only allow viewing of repos also on overview page

Now gitweb should just work.

If not, you can scatter 'print "\n\nDEBUG: $var\n"; exit(0);' statements through the perl script to try to figure out what's going wrong. Unfortunately, error checking in this script is fairly nonexistant.

git daemon

cloning via http is heavy on network bandwidth. The git daemon was written to trade a little extra processing time for a marked decrease in upload and download times. It runs as a daemon on port 9418..

You use the git protocol to interact with the git daemon:

$ git clone git://u32.net/projects/your-proj.git

Setting Up the git daemon

TODO

RSync

rsync greatly reduces the bandwidth required for a typical pull. However, it has a number of problems, the biggest of which is locking. (TODO: describe more) The git developers have hinted that the rsync protocol will be disabled in the future.

To allow anonymous downloads via rsync, first you must set up an rsync server. After you've done that, just publish your exported repository on the server as you would any other set of files. Users can clone it with:

$ git clone rsync://u32.net/projects/your-proj.git

Uploading via rsync

Don't upload via rsync. It's too labor intensive. However, if the only alternative is uploading via scp every time, you can use rsync to greatly speed up your uploads.

If you can't install git binaries on the server, you can't call git push. That's because post-update hook can't be called, meaning git-update-server-info won't be called, meaning your repository will not be clonable. This just means you'll have to do a little more work when you want to publish your changes.

If your repository is small, could just delete the repository on the server, then export and re-upload your local repository. Instead of deleting and re-uploading, though, it's easier to use rsync to save bandwidth (this requires the rsync executable to be on your webserver, but not the rsync daemon)

# follow all the steps in Export your Repository but upload the bare repo with:
 $ rsync -av --delete --rsh=ssh my-proj.git example.com:u32.net/projects/

garbage:

TODO: edit .git/remotes/origin to edit the ssh URL you'll use to update the repo. Then run git update-server-info. Now you can use the push and pull commands to move changesets to and from your published repository.

There are 3 ways to push changes to an online repository: ssh, rsync, gitweb

TODO: need to talk about branching related to pulling. For instance, when you clone a repository, you will by default only see what's on the master branch. How do you pull from another repo's master branch, while maintaining your own?

(upstream's changes arrive in origin, then you rebase to slide your changes on top of theirs.)