[IMPORTANT: There is now an "upgrade" document in the "doc" directory; please read if upgrading gitolite]
[Update 2009-10-10: apart from all the nifty new features, there's now an "easy install" script in the src directory. Please see the INSTALL document in the doc directory for details]
Gitolite is the bare essentials of gitosis, with a completely different config file that allows (at last!) access control down to the branch level, including specifying who can and cannot rewind a given branch. It is released under GPL v2. See COPYING for details.
In this document:
- what's gone
- what's new
- the workflow
I have been using gitosis for a while, and have learnt a lot from it. But in a typical $DAYJOB setting, there are some issues:
- it's not always Linux; you can't just "urpmi gitosis" (or yum or apt-get) and be done
- often, "python-setuptools" isn't installed (and on a Solaris9 I was trying to help remotely, we never did manage to install it eventually)
- or you don't have root access, or the ability to add users
- the most requested feature (see "what's new?") had to be written anyway
While I was pondering the need to finally learn python , I also realised that:
no one in $DAYJOB type environments will use or approve access methods that work without any authentication, so I didn't need gitweb/daemon support in the tool or in the config file.
Update 2009-09-24: I don't use this feature but someone wanted it, so I added it... see the "faq, tips, etc" document for more
the idea that you admin it by pushing to a special repo is nice, but not really necessary because of how rarely these changes are made, especially considering how much code is involved in that piece
All of this pointed to a rewrite. In perl, naturally :-)
Per-branch permissions. You will not believe how often I am asked this at $DAYJOB. This is almost the single reason I started thinking about rolling my own gitosis in the first place.
It's not just "read-only" versus "read-write". Rewinding a branch (aka "non
fast forward push") is potentially dangerous, but sometimes needed. So is
deleting a branch (which is really just an extreme form of rewind). I needed
something in between allowing anyone to do it (the default) and disabling it
Take a look at the example config file in the repo to see how I do this. I
copied the basic idea from
update-hook-example.txt (it's one of the "howto"s
that come with the git source tree). However, please note the difference in
the size and complexity of the operational code between the update hook in
that example, and in mine :-) The reason is in the next section.
In order to get per-branch access, you must use an update hook. However, that only gets invoked on a push; "read" access still has to be controlled right at the beginning, before git even enters the scene (just the way gitosis currently works).
So: either split the access control into two config files, or have two completely different programs both parse the same one and pick what they want. Crap... I definitely don't want the hook doing any parsing, (and it would be nice if the auth-control program didn't have to either).
So I changed the workflow completely:
- all admin changes happen on the server, in a special directory that contains the config and the users' pubkeys. But there's no commit and push afterward
- instead, after making changes, you "compile" the configuration. This
~/.ssh/authorized_keys, as well as puts a parsed form of the access list in a file for the other two pieces to use.
The pre-parsed form is basically a huge perl variable. It's human readable too (never mind what the python guys say!)
So the admin knows immediately if the config file had any problems, which is good. Also, the relatively complex parse code is not part of the actual access control points, which are:
- the program that is run via
~/.ssh/authorized_keys(I call it
gl-auth-command, equivalent to
gitosis-serve); this decides whether git should even be allowed to run (basic R/W/no access)
- the update-hook on each repo, which decides the per-branch permissions
 I hate whitespace to mean anything significant except for text; this is a personal opinion only, so pythonistas please back off :-)