master TOC | chapter TOC | support
The previous section is sufficient for most common needs, but gitolite can go a lot further than that.
Here's a hopefully self-explanatory example. Assume the project has the following contents at the top level: a README, a "doc/" directory, and an "src/" directory.
repo foo
RW+ = lead_dev # rule 1
RW = dev1 dev2 dev3 dev4 # rule 2
RW NAME/ = lead_dev # rule 3
RW NAME/doc/ = dev1 dev2 # rule 4
RW NAME/src/ = dev1 dev2 dev3 dev4 # rule 5
Notes:
the "NAME/" is part of the syntax; think of it as a keyword if you like. The rest of it is treated as a refex to match against each file being touched (see "SPECIFYING AND USING A REFEX" above for details)
file/dir NAME-based restrictions are in addition to normal (branch-name based) restrictions; they are not a replacement for them. This is why rule #2 (or something like it, maybe with a more specific branch-name) is needed; without it, dev1/2/3/4 cannot push any branches.
if a repo has any NAME/ rules, then NAME-based restrictions are checked for all users. This is why rule 3 is needed, even though we don't actually have any NAME-based restrictions on lead_dev. Notice the pattern on rule 3.
each file touched by the commits being pushed is checked against those rules. So, lead_dev can push changes to any files, dev1/2 can push changes to files in "doc/" and "src/" (but not the top level README), and dev3/4 can only push changes to files in "src/".
Gitolite performs access checks at 2 levels. The first check is performed for both read and write operations, while the second one happens only for write operations.
Required reading: this section of the documentation.
Warning: When using deny rules, the order of your rules matters, where earlier it did not. If you're just starting to add a deny rule to an existing ruleset, it's a good idea to review the entire ruleset once, to make sure you're doing it right.
You can use "deny" rules for the second check, to prevent people pushing branches or tags that they should not be allowed to.
Take a look at the following snippet, which seems to say that "bruce" can
write versioned tags (anything containing refs/tags/v[0-9]), but the other
staffers can't:
@staff = bruce whitfield martin
[... and later ...]
RW refs/tags/v[0-9] = bruce
RW refs/tags = @staff
But that's not how the matching works. As long as any refex matches the
refname being updated, it's a "yes". Since the second refex (which says
"anything containing refs/tags") is a superset of the first one, it lets
anyone on @staff create versioned tags, not just Bruce.
So how do we say "these people can create any tags except tags that look like this pattern"?
One way to fix this is to allow "deny" rules. We make a small addition to the permissions syntax, and define a more rigorous, ordered, interpretation.
Let's recap the existing semantics:
The first matching refex that has the permission you're looking for (
Wor+), results in success. A fallthrough results in failure.
Here are the new semantics, with changes from the "main" one in bold:
The first matching refex that has the permission you're looking for (
Wor+) or a minus (-), results in success or failure, respectively. A fallthrough also results in failure.
So the example we started with becomes, if you use "deny" rules:
RW refs/tags/v[0-9] = bruce
- refs/tags/v[0-9] = @staff
RW refs/tags = @staff
And here's how it works:
- as the permission, so the push
failsThe previous section described deny rules for the second check, which is a fairly common need. However, gitolite does not process deny rules for the first check -- it's usually simple enough to make sure your config file does not allow the particular user/repo combindation at all.
But there's one case where this becomes cumbersome: when you want to create
exceptions to uses of @all.
For example, if you want gitweb to show @all repos except the special
'gitolite-admin' repo, you must manually (and laboriously) maintain a list of
all your repos (except gitolite-admin) and use that in place of @all. Oh
joy...
But now you can do this:
repo gitolite-admin
- = gitweb daemon
[... other access rules ...]
config gitolite-options.deny-repo = 1
repo @all
R = gitweb daemon
Here are some notes on how/why this works:
The order is important -- the deny rule must come first.
The 'config' line is what tells git to behave differently, i.e., apply deny rules for the first check also.
Since there is no "ref" to match against the refexes in the rules, gitolite just ignores the refexes, and simply looks at the permission (R, RW, "-", etc) and the user list.
Since the beginning of gitolite, RW gave the ability, not only to update,
but to create a branch (that matched the refex). Similarly, RW+ meant
being able to not only rewind, but also delete a ref. Conceptually, a rewind
is almost the same as a delete+push (the only difference I can see is if you
had core.logAllRefUpdates set, which is not a default setting).
However, there seem to be cases where it is useful to distinguish these cases. Arguments can be made on all sides if you're dealing with new users, so gitolite now supports that (in a backward compatible way).
We'll look at the delete/rewind case in detail first:
if the rules for a repo do not contain a D anywhere, then RW+ will
allow both rewind and delete operations. Apart from being more convenient
if you don't need this separation, this also ensures backward
compatibility for setups created before this separation feature was added
to gitolite).
if, however, any of the rules for a repo contains a D (example: RWD,
RW+D, etc) then RW+ by itself will permit only a rewind, not a delete
The same thing applies to create/push, where if you have permissions like
RWC or RW+C anywhere in that repo, a simple RW or RW+ can no longer
create a new ref.
You can combine the C and D also. Thus, the set of permissions you now
know about are, in regex syntax: R|RW+?C?D?. See a later section for the
full set of permissions possible.
Some usage hints:
if you find that RW+ no longer allows creation/deletion but you can't
see a C/D permission in the rules, remember that gitolite allows a
repo config to be specified in multiple places for convenience, included
delegated or included files. Be sure to search everywhere :)
a quick way to make this the default for all your repos is:
repo @all
RWCD dummy-branch = foo
where foo can be either the administrator, or if you can ignore the warning message when you push, a non-existant user.
Some people want to enforce a no-merges policy for various reasons. This
behaviour can be enabled by suffixing an "M" to the end of any permission
starting with RW (i.e., all of them except R). So for instance, RW
becomes RWM, and RW+ becomes RW+M, etc.
The rules are exactly the same as for "C" and "D": once a repo has an "M" qualifier tied to any access rule, all rules for that repo are subject to merge checking, and merge commits will only be allowed when the rule has the "M" qualifier.