master TOC | chapter TOC | support

advanced access control

The previous section is sufficient for most common needs, but gitolite can go a lot further than that.

restricting pushes by dir/file name using NAME/

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:

"deny" rules

warnings and required reading

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.

"deny" rules for refs in a repo

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 (W or +), 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 (W or +) 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:

"deny" rules for the entire repo

The 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:

creating and deleting branches

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:

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:

enforcing a no-merges policy

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.