how gitolite uses ssh

Although other forms of authentications exist (see the section on authentication versus authorisation), ssh is the one that most git users use.

Therefore, gitolite is (usually) heavily dependent on ssh.

Most people didn't realise this, and even if they did they don't know ssh well enough to help themselves. If you don't understand how ssh public key authentication works, or how the ~/.ssh/authorized_keys file can be used to restrict users, etc., you will have endless amounts of trouble getting gitolite to work, because you'll be attacking the wrong problem.

So please please please understand this before tearing your hair out and blaming git/gitolite for whatever is going wrong with your setup :-)

ssh basics

Let's start with some basics, focusing only on the pieces relevant to gitolite. If this is not detailed enough, please use google and learn more from somewhere, or maybe buy the OReilly ssh book.

how does gitolite use all this ssh magic?

These are two different questions you ought to be having by now:

restricting shell access/distinguishing one user from another

The answer to the first question is the command= we talked about before. If you look in the authorized_keys file, you'll see entries like this (I chopped off the ends of course; they're pretty long lines):

command="[path]/gitolite-shell sitaram",[more options] ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA18S2t...
command="[path]/gitolite-shell usertwo",[more options] ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEArXtCT...

First, it finds out which of the public keys in this file match the incoming login. That's crypto stuff, and I won't go into it. Once the match has been found, it will run the command given on that line; e.g., if I logged in, it would run [path]/gitolite-shell sitaram. So the first thing to note is that such users do not get "shell access", which is good!

Before running the command, however, sshd sets up an environment variable called SSH_ORIGINAL_COMMAND which contains the actual git command that your workstation sent out. This is the command that would have run if you did not have the command= part in the authorised keys file.

When gitolite-shell gets control, it looks at the first argument ("sitaram", "usertwo", etc) to determine who you are. It then looks at the SSH_ORIGINAL_COMMAND variable to find out which repository you want to access, and whether you're reading or writing.

Now that it has a user, repository, and access requested (read/write), gitolite looks at its config file, and either allows or rejects the request.

But this cannot differentiate between different branches within a repo; that has to be done separately.

restricting branch level actions

[If you look inside the git source tree, there's a file among the "howto"s in there called update-hook-example.txt, which was the inspiration for this part of gitolite.]

Git allows you to specify many "hooks", which get control as various events happen -- see git help hooks for details. One of those hooks is the update hook, which, if it is present, is invoked just before a branch or a tag is about to be updated. The hook is passed the name of the branch or tag, the old SHA1 value, and the new SHA1 value, as arguments. Hooks that are called before an action happens are allowed to prevent that action from happening by returning an error code.

When gitolite is told to create a new repository (by the admin), it installs a special update hook. This hook takes all the information presented, looks at the config file, and decides to allow or reject the update.

And that's basically it.