In this document:
adding repositories/
at the start of the repo name in the git clone
.
This error is typically made by the admin himself -- because he knows
what $REPO_BASE
is set to and thinks he has to provide that prefix on
the client side also :-) In fact gitolite prepends $REPO_BASE
internally, so you shouldn't also do the same thing!
being able to clone but getting errors on push. Most likely caused by a combination of:
you already have shell access to the server, not just "gitolite" access, and
you cloned using git clone git@server:repositories/repo.git
(notice
there's an extra "repositories/" in there?)
In other words, you used a key that completely bypassed gitolite and went straight to the shell to do the clone.
Please see doc/ssh-troubleshooting.mkd for what all this means.
Cloning an empty repo is only possible with clients greater than 1.6.2. So at least one of your clients needs to have a recent git. Once at least one commit has been made, older clients can also use it
When you clone an empty repo, git seems to complain about fatal: The remote
end hung up unexpectedly
. However, you can ignore this, since it doesn't
seem to hurt anything. [Update 2009-09-14; this has been fixed in git
1.6.4.3]
@all
syntax for reposThere is a way to use the @all
syntax for repos also, as described in
doc/gitolite.conf.mkd
. However, there are a couple of minor cautions:
NAME/
or such restrictions on the special @all
repo. Due to
the potential for defeating a crucial optimisation and slowing down all
access, we do not support this.Apart from the big ones listed in the top level README, and subjective ones like "better config file format", gitolite has evolved to have many useful features than the original goal of branch-level access control.
I have a laptop and a desktop I need to access the server from. I have different private keys on them, but as far as gitolite is concerned both of them should be treated as "sitaram". How does this work?
The way it works is that you copy one pubkey as "sitaram@laptop.pub" and the other as "sitaram@desktop.pub". The part before the "@" is the username, so gitolite knows these two keys belong to the same person. The part after the "@" can be anything you like, of course; gitolite doesn't care.
Note that you don't say "sitaram@laptop" and so on in the config file -- as far as the config file is concerned there's just one user called "sitaram" -- so you only say "sitaram" there.
I think this is easier to maintain if you have to delete or change one of those keys.
However, now that sitaramc@gmail.com
is also a valid username, we need to
distinguish between sitaramc@gmail.com.pub
and sitaramc@desktop.pub
. We
do that by requiring that the multi-key suffix you use (like "desktop" and
"laptop") should not have a "."
in it. If it does, it looks like an email
address. The following table lists sample pubkey filenames and the
corresponding derived usernames (which is what goes into the
conf/gitolite.conf
file):
old style multikeys; not mistaken for emails because there is no "." in hostname part
sitaramc.pub sitaramc
sitaramc@laptop.pub sitaramc
sitaramc@desktop.pub sitaramc
new style, email keys; there is a "." in hostname part; so it's an email address
sitaramc@gmail.com.pub sitaramc@gmail.com
multikeys with email address
sitaramc@gmail.com@laptop.pub sitaramc@gmail.com
sitaramc@gmail.com@desktop.pub sitaramc@gmail.com
Gitolite has two levels of access checks. The first check is what I will
call the pre-git level. At this stage, the gl-auth-command
has been
invoked by sshd
, and it knows just three things:
Note that at this point no git program has entered the picture, and we have no way of knowing what ref (branch, tag, etc) he is trying to update, even if it is a "write" operation.
For a "read" operation to pass this check, the username (or @all
) must have
read permission (i.e., R, RW, or RW+) on at least one branch of the repo.
For a "write" operation, there is an additional restriction: lines specifying
only R
(read access) don't count. The user must have write access to
some ref in the repo in order to pass this stage!
The second check is via a git update hook
. This check only happens for
write operations. By this time we know what "ref" he is trying to update, as
well as the old and the new SHAs of that ref (by which we can also deduce
whether it's a rewind or not). This is where the "per-branch" permissions
come into play.
Each refex that allows W
access (or +
if this is a rewind) for this
user, on this repo, is matched against the actual refname being updated. If
any of the refexes match, the push succeeds. If none of them match, it fails.
Gitolite also allows "exclude" or "deny" rules. See later in this document for details.
If you have been too liberal with the permission to rewind, it has built-in
logging as an emergency fallback if someone goes too far, or for audit
purposes [*
]. The logfile names and location are configurable, and can
include the year/month/day etc in the filename for easy archival or further
processing. The log file even tells you which pattern in the config file
matched to allow that specific access to proceed.
[
*
] settingcore.logAllRefUpdates true
does provide a safety net against over-zealous rewinds, but it does not tell you "who". And strangely, management does not seem to share the view that "blame" is just a synonym for "annotate" ;-)]
The log lines look like this:
2009-09-19.10:24:37 + b4e76569659939 4fb16f2a88d8b5 myrepo refs/heads/master user2 refs/heads/master
The "+" at the start indicates a non-fast forward update, in this case from b4e76569659939 to 4fb16f2a88d8b5. So b4e76569659939 is the one to restore! Can it get easier?
The other parts of the log line are the name of the repo, the refname being updated, the user updating it, and the refex pattern (from the config file) that matched, in case you need to debug the config file itself.
You can now split up the config file and delegate the authority to specify access control for their own pieces. See delegation for details.
Sometimes there are too many repos, maybe even named similarly, or with the potential for typos, confusion about hyphens/underscores or upper/lower case, etc. You'd just like a simple way to know what repos you have access to.
Gitolite provides two commands (info
and expand
) to help you find this
information; please check doc/report-output.mkd for details.
The normal solution is to add to the system default PATH somehow, either by
munging /etc/profile
or by enabling PermitUserEnvironment
in
/etc/ssh/sshd_config
and then setting the PATH in ~/.ssh/.environment
.
All these are security risks because they allow a lot more than just you and
your git install :-)
And if you don't have root, you can't do this anyway.
The only solution till now has been to ask every client to set the config
parameters remote.<name>.receivepack
and remote.<name>.uploadpack
. But
telling every client to do so is a pain...
Gitolite lets you specify the directory in which git binaries are to be found,
via a new variable ($GIT_PATH
) in the "rc" file. If this variable is
non-empty, it will be appended to the PATH environment variable before
attempting to run git stuff.
Very easy, very simple, and completely transparent to the users :-)
Note: sometimes you have a system that already has an older "git"
installed in one of the system PATHs, but you've installed a newer git in some
non-standard location and want that picked up. Because of security reasons,
gitolite will not prepend GIT_PATH
to the PATH variable, so the older git
comes first and it gets kinda frustrating!
Here's a simple workaround. Ignore the GIT_PATH
variable, and directly set
the full PATH in the rc file, like so:
$ENV{PATH} = "/home/sitaram/bin:$ENV{PATH}";
"personal" branches are great for corporate environments, where unauthenticated pull/clone is a no-no. Since a dev workstation cannot do authentication, even work shared just between 2 devs has to go via the server. This causes the same branch name clutter as in a centralised VCS, plus setting up permissions for this becomes a chore for the admin.
gitolite lets you define a "personal" or "scratch" namespace prefix for each
developer (e.g., refs/personal/<devname>/*
). Just add a line like:
RW+ personal/USER/ = @userlist
This means I (user "sitaram") can do anything to any branch whose name starts
with personal/sitaram/
assuming I'm in "userlist".
You can have any number of such lines with different prefixes (for example,
using topic names instead of "personal") or even suffixes if you like. The
important thing is that the "branch" name should contain /USER/
(including
the slashes). At runtime this will match whoever is the current user. Access
is still determined by the right hand side of course.
You can specify hooks that you want to propagate to all repos, as well as
per-repo "gitconfig" settings. Please see doc/2-admin.mkd
and
doc/gitolite.conf.mkd
for details.
Sometimes you'll need to access one of the gitolite-managed repos directly on the server, without going through gitolite. Reasons may be some automatic updates or some other ad hoc purposes you can dream up.
Cloning a gitolite-controlled repo is easy enough -- just use the full path
(typically ~/repositories/reponame.git
) instead of just reponame
, to
compensate for gitolite not sitting in between and adding those things to the
repo path.
But when you push, the update hook (which git will invoke anyway) will fail because it needs all sorts of access control info that it now doesn't have, because the push was invoked without going through gitolite.
In order to bypass the update hook, just set the GL_BYPASS_UPDATE_HOOK
environment variable to "1" or something, export it, and push. I prefer not
to set that variable permanently, preferring this mode instead:
GL_BYPASS_UPDATE_HOOK=1 git push
The method described in the previous section (setting GL_BYPASS_UPDATE_HOOK
)
will work for all the repos managed by gitolite, except for the special
gitolite-admin
repo. For that you will need some extra magic, because there
is also a post-update
hook that runs here, and this needs additional
information which is NOT available if you bypass gitolite.
Use the gl-admin-push
program to make changes to the admin repo directly on
the server. Here's how:
clone the repo to some safe location and cd to it:
cd /tmp
git clone ~/repositories/gitolite-admin.git
cd gitolite-admin
make whatever changes you want to that clone and commit. You can add new keys, change the conf file, or anything at all that needs fixing up. You can even reset to an older commit (rewind) if that is the simplest way to fix up some config problem that may have lost you your access.
when done, instead of git push <push arguments>
, use this program
instead, like so:
gl-admin-push <push arguments>
Note that this method will work for any repo, not just the special admin repo.
If you want to take normal, OS-level, backups of the system, you might want git to be quiescent during that time, so that the backup is clean. The best way to do this is to disable write-access to the server for the duration of the backup.
Here's how:
cd $HOME # if running as "git" user, else "cd ~git" or whatever
echo writes disabled during backup window > .gitolite.down
# << RUN YOUR BACKUP COMMAND(s) HERE >>
rm .gitolite.down
I leave it to you to
.gitolite.down
file is
still removed (or not; maybe your policy is that if the backup failed, no
further writes are allowed. Whatever...)git-receive-pack
processes in a ps
output.By design, there is no code in gitolite to delete a repo if the repo was specified by name in the config file. (Wildcard repos can be deleted by the user; see here for details).
If you do want to permanently delete a non-wildcard repo, here's what you do:
remove the repo from the gitolite-admin repo clone's conf/gitolite.conf
file. "add" the change, commit, and push.
then remove the repo from ~/repositories
on the server (or whatever
you set $GL_REPO_BASE
to in the ~/.gitolite.rc
)
This is similar; there's no code to do this in gitolite. What you do is:
cd $REPO_BASE
(default: cd ~/repositories
), and
mv old-name.git new-name.git
conf/gitolite.conf
and replace
all occurrences of old-name
with new-name
. Then add, commit, and push
as usual.The order of these 2 steps is important; do not reverse them :-)
Although gitweb is a completely separate program, gitolite can do quite a lot to help you manage gitweb access as well; once the initial setup is complete, you can do it all from within the gitolite config file!
If you just want gitweb to show some repositories, see gwd for how to specify which repos to show. Other advanced uses are described here.
Over and above whether a repo is even shown by gitweb, you may want to further restrict people, allowing them to view only those repos for which they have been given read access by gitolite.
This requires that:
Normally a superuser sets up passwords for users using the "htpasswd" command, but this is an administrative chore.
Robin Smidsrød had the great idea that, since each user already has pubkey
access to git@server
, this gives us a very neat way of using gitolite to let
the users manage their own HTTP passwords. Here's how:
~/.gitolite.rc
file, look for the variable $HTPASSWD_FILE
and
point it to this filessh git@server htpasswd
to set or change
their HTTP passwordsOf course some other authentication method can be used (e.g. mod_ldap
) as
long as the usernames match.
Gitweb allows you to specify a subroutine to decide on access. We use that
feature and tie it to gitolite. Configuration example can be found in
contrib/gitweb/
.
Gitweb not able to read your repos? You can change the umask for newly
created repos to something more relaxed -- see the REPO_UMASK
setting in the ~/.gitolite.rc
file.
Please see doc/wildcard-repositories.mkd
for all the details.
This requires the wildcards feature to be enabled, but is then an extremely
powerful feature. See doc/admin-defined-commands.mkd
.
Gitolite now has a mechanism for allowing access control for arbitrary external commands, as long as they are invoked via ssh and present a server-side command that contains enough information to make an access control decision.
Note that this is incompatible with giving people shell access as described in
doc/ssh-troubleshooting.mkd
-- people who have shell access are not
subject to this mechanism (it wouldn't make sense to try and control someone
who has shell access anyway).
In general, external commands require changes in one or both the config files;
the sample files in conf/
double as documentation, so you should look there
for examples and usage.
Commands implemented so far are:
If you are transitioning from SVN to gitolite, and have a lot of users using
public-key authentication with SVN, this feature may be useful to you. Once
you migrate all users' public keys into gitolite, you can set the $SVNSERVE
variable in ~/.gitolite.rc
to tie svnserve
with gitolite's authentication
system. Assuming you installed gitolite to the same user as the one you used
for SVN, SVN connectivity will be retained, and users will be able to use
both SVN and git using the same SSH configuration.
There are two programs concerned with access control:
gl-auth-command
, the program that is run via ~/.ssh/authorized_keys
;
this decides whether git should even be allowed to run (basic R/W/no
access). (This one cannot decide on the branch-level access; it is not
known at this point what branch is being accessed)I have chosen to keep the relatively complex task of parsing the config file
out of them to keep them simpler (and faster). So any changes to the config
have to be first "compiled", and the access control programs use this
"compiled" version of the config. (The compile step also refreshes
~/.ssh/authorized_keys
).
If you choose the "easy install" method, all this is quite transparent to you anyway. If you cannot use the easy install and must install manually, I have clear instructions on how to set it up.