This page explains the storage format of Gerrit’s project configuration and access control models.

The web UI access control panel is a front end for human-readable configuration files under the refs/meta/config namespace in the affected project. Direct manipulation of these files is mainly relevant in an automation scenario of the access controls.

The refs/meta/config namespace

The namespace contains three different files that play different roles in the permission model. With read permission to that reference, it is possible to fetch the refs/meta/config reference to a local repository. A nice side effect is that you can also upload changes to project permissions and review them just like with regular code changes. The preview changes option is also provided on the UI. Please note that you will have to configure push rights for the refs/meta/config name space if you’d like to use the possibility to automate permission updates.

Property inheritance

If a property is set to INHERIT, then the value from the parent project is used. If the property is not set in any parent project, the default value is FALSE.

The file project.config

The project.config file contains the link between groups and their permitted actions on reference patterns in this project and any projects that inherit its permissions.

The format in this file corresponds to the Git config file format, so if you want to automate your permissions it is a good idea to use the git config command when writing to the file. This way you know you don’t accidentally break the format of the file.

Here follows a git config command example:

$ git config -f project.config project.description "Rights inherited by all other projects"

Below you will find an example of the project.config file format:

[project]
       description = Rights inherited by all other projects
[access "refs/*"]
       read = group Administrators
[access "refs/heads/*"]
        label-Your-Label-Here = -1..+1 group Administrators
[capability]
       administrateServer = group Administrators
[receive]
       requireContributorAgreement = false
[label "Your-Label-Here"]
        function = MaxWithBlock
        value = -1 Your -1 Description
        value =  0 Your No score Description
        value = +1 Your +1 Description

As you can see, there are several sections.

The project section appears once per project.

The access section appears once per reference pattern, such as refs/* or refs/heads/*. Only one access section per pattern is allowed.

The receive section appears once per project.

The submit section appears once per project.

The capability section only appears once, and only in the All-Projects repository. It controls core features that are configured on a global level.

The label section can appear multiple times. You can also redefine the text and behavior of the built in label types Code-Review and Verified.

Optionally a commentlink section can be added to define project-specific comment links. The commentlink section has the same format as the commentlink section in gerrit.config which is used to define global comment links.

Project section

The project section includes configuration of project settings.

These are the keys:

description

A description for the project.

state

This setting defines the state of the project. A project can have the following states:

  • Active:

    The project is active and users can see and modify the project according to their access rights on the project.

  • Read Only:

    The project is read only and all modifying operations on it are disabled. E.g. this means that pushing to this project fails for all users even if they have push permissions assigned on it.

    Setting a project to this state is an easy way to temporary close a project, as you can keep all write access rights in place and they will become active again as soon as the project state is set back to Active.

    This state also makes sense if a project was moved to another location. In this case all new development should happen in the new project and you want to prevent that somebody accidentally works on the old project, while keeping the old project around for old references.

  • Hidden:

    The project is hidden; It will not appear in any searches and is only visible to project owners by going directly to the repository admin page. Other users are not able to see the project even if they have read permissions granted on the project.

Receive section

The receive section includes configuration of project-specific receive settings:

receive.requireContributorAgreement

Controls whether or not a user must complete a contributor agreement before they can upload changes. Default is INHERIT. If All-Projects enables this option then the dependent project must set it to false if users are not required to sign a contributor agreement prior to submitting changes for that specific project. To use that feature the global option in gerrit.config must be enabled: auth.contributorAgreements.

receive.requireSignedOffBy

Sign-off can be a requirement for some projects (for example Linux kernel uses it). Sign-off is a line at the end of the commit message which certifies who is the author of the commit. Its main purpose is to improve tracking of who did what, especially with patches. Default is INHERIT, which means that this property is inherited from the parent project.

receive.requireChangeId

The Require Change-Id in commit message option defines whether a Change-Id in the commit message is required for pushing a commit for review. If this option is set, trying to push a commit for review that doesn’t contain a Change-Id in the commit message fails with missing Change-Id in commit message footer.

It is recommended to set this option and use a commit-msg hook (or other client side tooling like EGit) to automatically generate Change-Id’s for new commits. This way the Change-Id is automatically in place when changes are reworked or rebased and uploading new patch sets gets easy.

If this option is not set, commits can be uploaded without a Change-Id, but then users have to remember to copy the assigned Change-Id from the change screen and insert it manually into the commit message when they want to upload a second patch set.

Default is INHERIT, which means that this property is inherited from the parent project. The global default for new hosts is true

This option is deprecated and future releases will behave as if this is always true.

receive.maxObjectSizeLimit

Maximum allowed Git object size that receive-pack will accept. If an object is larger than the given size the pack-parsing will abort and the push operation will fail. If set to zero then there is no limit.

Project owners can use this setting to prevent developers from pushing objects which are too large to Gerrit. This setting can also be set in gerrit.config globally ( receive.maxObjectSizeLimit).

The project specific setting in project.config may not set a value higher than the global limit (if configured). In other words, it is only honored when it further reduces the global limit.

When receive.inheritProjectmaxObjectSizeLimit is enabled in the global config, the value is inherited from the parent project. Otherwise, it is not inherited and must be explicitly set per project.

Default is zero.

Common unit suffixes of k, m, or g are supported.

receive.checkReceivedObjects

Controls whether or not the JGit functionality for checking received objects is enabled.

By default Gerrit checks the validity of git objects. Setting this variable to false should not be used unless a project with history containing invalid objects needs to be pushed into a Gerrit repository.

This functionality is provided as some other git implementations have allowed bad history to be written into git repositories. If these repositories need pushing up to Gerrit then the JGit checks need to be disabled.

The default value for this is true, false disables the checks.

receive.enableSignedPush

Controls whether server-side signed push validation is enabled on the project. Only has an effect if signed push validation is enabled on the server; see the global configuration for details.

Default is INHERIT, which means that this property is inherited from the parent project.

receive.requireSignedPush

Controls whether server-side signed push validation is required on the project. Only has an effect if signed push validation is enabled on the server, and receive.enableSignedPush is set on the project. See the global configuration for details.

Default is INHERIT, which means that this property is inherited from the parent project.

receive.rejectImplicitMerges

Controls whether a check for implicit merges will be performed when changes are pushed for review. An implicit merge is a case where merging an open change would implicitly merge another branch into the target branch. Typically, this happens when a change is done on master and, by mistake, pushed to a stable branch for review. When submitting such change, master would be implicitly merged into stable without anyone noticing that. When this option is set to 'true' Gerrit will reject the push if an implicit merge is detected.

This check is only done for non-merge commits, merge commits are not subject of the implicit merge check.

Default is INHERIT, which means that this property is inherited from the parent project.

receive.createNewChangeForAllNotInTarget

This option provides a convenience for selecting the merge base by setting it automatically to the target branch’s tip so you can create new changes for all commits not in the target branch.

This option is disabled if the tip of the push is a merge commit.

This option also only works if there are no merge commits in the commit chain, in such cases it fails warning the user that such pushes can only be performed by manually specifying bases

This option is useful if you want to push a change to your personal branch first and for review to another branch for example. Or in cases where a commit is already merged into a branch and you want to create a new open change for that commit on another branch.

Change section

The change section includes configuration for project-specific change settings:

change.privateByDefault

Controls whether all new changes in the project are set as private by default.

Note that a new change will be public if the is_private field in ChangeInput is set to false explicitly when calling the CreateChange REST API or the remove-private PushOption is used during the Git push.

Default is INHERIT, which means that this property is inherited from the parent project.

change.workInProgressByDefault

Controls whether all new changes in the project are set as WIP by default.

Note that a new change will be ready if the workInProgress field in ChangeInput is set to false explicitly when calling the CreateChange REST API or the ready PushOption is used during the Git push.

Default is INHERIT, which means that this property is inherited from the parent project.

Submit section

The submit section includes configuration of project-specific submit settings:

submit.mergeContent

Defines whether Gerrit will try to do a content merge when a path conflict occurs while submitting a change.

A path conflict occurs when the same file has been changed on both sides of a merge, e.g. when the same file has been touched in a change and concurrently in the target branch.

Doing a content merge means that Gerrit attempts to merge the conflicting file contents from both sides of the merge. This is successful if the touched lines (plus some surrounding context lines) do not overlap (i.e. both sides touch distinct lines).

Note
The content merge setting is not relevant when fast forward only is configured as the submit action because in this case Gerrit will never perform a merge, rebase or cherry-pick on submit.

If content merges are disabled, the submit button in the Gerrit web UI is disabled, if any path conflict would occur on submitting the change. Users then need to rebase the change manually to resolve the path conflict and then get the change re-approved so that they can submit it.

Note
If only distinct lines have been touched on both sides, rebasing the change from the Gerrit UI is sufficient to resolve the path conflict, since the rebase action always does the rebase with content merge enabled.

The advantage of enabling content merges on submit is that it makes it less likely that change submissions are rejected due to conflicts. Each change submission that goes through with content merge, but would be rejected otherwise, saves the user from needing to do extra work to get the change submitted (rebase the change, get it re-approved and then submit it again).

On the other hand, disabling content merges decreases the chance of breaking branches by submitting content merges of incompatible modifications in the same file, e.g. a function is removed on one side and a new usage of that function is added on the other side. Note, that the chance of breaking a branch by incompatible modifications is only reduced, but not eliminated, e.g. even with content merges disabled it’s possible that a function is removed in one file and a new usage of that function is added in another file.

The huge drawback of disabling content merge is that users need to do extra work when a change isn’t submittable due to a path conflict which could be avoided if content merge was enabled (see above). In addition to this, it also confuses and frustrates users if a change submission is rejected by Gerrit due to a path conflict, but then when they rebase the change manually they do not see any conflict (because manual rebases are always done with content merge enabled).

In general, the stability gain of disabling content merges is not worth the overhead and confusion that this adds for users, which is why disabling content merges is highly discouraged.

Valid values are true, false, or INHERIT.

The default is INHERIT.

Note
Project owners can also set this option in the Gerrit UI: Browse > Repositories > my/repository > Allow content merges.
submit.action

Defines the submit action aka submit type aka submit strategy that Gerrit should use to integrate changes into the target branch when they are submitted.

In general, submitting a change only merges the change if all its dependencies are also submitted. The only exception is the cherry pick submit action which ignores dependencies and hence is not recommended to be used (see below).

The following submit actions are supported:

  • 'merge if necessary':

    With this action, when a change is being submitted, Gerrit fast-forwards the target branch if possible, and otherwise creates a merge commit automatically.

    A fast-forward is possible if the commit that represents the current patch set of the change has the current head of the target branch in its parent lineage.

    If a fast-forward is not possible, Gerrit automatically creates a merge commit that merges the current patch set of the change into the target branch and then the target branch is fast-forwarded to the merge commit.

    The behavior of this submit action is identical with the classical git merge behavior, or git merge --ff.

    With this submit action the commits that have been reviewed and approved are retained in the git history of the target branch. This means, by looking at the history of the target branch, you can see for all commits when they were originally committed and on which parent commit they were originally based.

  • 'merge always':

    With this action, when a change is being submitted, Gerrit always creates a merge commit, even if a fast-forward is possible.

    This is identical to the behavior of git merge --no-ff.

    With this submit action the commits that have been reviewed and approved are retained in the git history of the target branch. This means, by looking at the history of the target branch, you can see for all commits when they were originally committed and on which parent commit they were originally based. In addition, from the merge commits you can see when the changes were submitted and it’s possible to follow submissions with git log --first-parent.

  • 'rebase if necessary':

    With this action, when a change is being submitted, Gerrit fast-forwards the target branch if possible, and otherwise does a rebase automatically.

    A fast-forward is possible if the commit that represents the current patch set of the change has the current head of the target branch in its parent lineage.

    If a fast-forward is not possible, Gerrit automatically rebases the current patch set of the change on top of the current head of the target branch and then the target branch is fast-forwarded to the rebased commit.

    With this submit action, when a rebase is performed, the original commits that have been reviewed and approved do not become part of the target branch’s history. This means the information on when the original commits were committed and on which parent they were based is not retained in the branch history.

    Using this submit action results in a linear history of the target branch, unless merge commits are being submitted. For some people this is an advantage since they find the linear history easier to read.

    Note
    Rebasing merge commits is not supported. If a change with a merge commit is submitted the merge if necessary submit action is applied.
  • 'rebase always':

    With this action, when a change is being submitted, Gerrit always does a rebase, even if a fast-forward is possible.

    With this submit action, the original commits that have been reviewed and approved do not become part of the target branch’s history. This means the information on when the original commits were committed and on which parent they were based is not retained in the branch history.

    Using this submit action results in a linear history of the target branch, unless merge commits are being submitted. For some people this is an advantage since they find the linear history easier to read.

    Note
    Rebasing merge commits is not supported. If a change with a merge commit is submitted the merge if necessary submit action is applied.

    When rebasing the patchset, Gerrit automatically appends onto the end of the commit message a short summary of the change’s approvals, and a URL link back to the change in the web UI (see below).

    The footers that are added are exactly the same footers that are also added by the cherry pick action. Thus, the rebase always action can be considered similar to the cherry pick action, but with the important distinction that rebase always does not ignore dependencies, which is why using the rebase always action should be preferred over the cherry pick submit action.

  • 'fast forward only' (usage generally not recommended):

    With this action a change can only be submitted if at submit time the target branch can be fast-forwarded to the commit that represents the current patch set of the change. This means in order for a change to be submittable its current patch set must have the current head of the target branch in its parent lineage.

    The advantage of using this action is that the target branch is always updated to the exact commit that has been reviewed and approved. In particular, if CI verification is configured, this means that the CI verified the exact commit to which the target branch is being fast-forwarded on submit (assuming no approval copying is configured for CI votes).

    The huge drawback of using this action is that whenever one change is submitted all other open changes for the same branch, that are not successors of the submitted change, become non-submittable, since the target branch can no longer be fast-forwarded to their current patch sets. Making these changes submittable again requires rebasing and re-approving/re-verifying them. For most projects this causes an unreasonable amount of overhead that doesn’t justify the stability gain by verifying exact commits so that using this submit action is generally discouraged. Using this action should only be considered for projects that have a low frequency of changes and that have special requirements to never break any target branch.

    Note
    With this submit action Gerrit does not create merge commits on submitting a change, but merge commits that are created on the client, prior to uploading to Gerrit for review, may still be submitted.
  • 'cherry pick' (usage not recommended, use rebase always instead):

    With this submit action Gerrit always performs a cherry pick of the current patch set when a change is submitted. This ignores the parent lineage and instead creates a brand new commit on top of the current head of the target branch. The submitter becomes the committer of the new commit and the original commit author is retained.

    Ignoring change dependencies on submit is often confusing for users. For users that stack changes on top of each other, it’s unexpected that these dependencies are ignored on submit. Ignoring dependencies also means that submitters need to submit the changes individually in the correct order. Otherwise it’s likely that submissions fail due to conflicts or that the target branch gets broken (because it contains the submitted change, but not its predecessors which may be required for the submitted change to work correctly).

    If change.submitWholeTopic is enabled changes that have the same topic are submitted together, the same as with all other submit actions. This means by setting the same topic on all dependent changes it’s possible to submit a stack of changes together and overcome the limitation that change dependencies are ignored.

    When cherry picking the patchset, Gerrit automatically appends onto the end of the commit message a short summary of the change’s approvals, and a URL link back to the change in the web UI (see below).

    Using this submit action is not recommended because it ignores change dependencies, instead rebase always should be used which behaves the same way except that it respects change dependencies (in particular rebase always adds the same kind of footers to the merged commit as cherry pick).

In addition the submit action can be set to Inherit, which means that the value that is configured in the parent project applies. For new projects Inherit is the default, unless the default is overridden by the global defaultSubmitType configuration. Configuring Inherit for the All-Projects root project is equivalent to configuring merge if necessary.

If submit.action is not set, the default is 'merge if necessary'.

Note
The different submit actions are also described in the Gerrit - Concepts and Workflows presentation, where their behavior is visualized by git commit graphs.
Note
If Gerrit performs a merge, rebase or cherry-pick as part of the change submission (true for all submit actions, except for fast forward only), it is controlled by the mergeContent setting whether a content merge is performed when there is a path conflict.
Note
If Gerrit performs a merge, rebase or cherry-pick as part of the change submission (true for all submit actions, except for fast forward only), it can be that trying to submit a change would fail due to Git conflicts (if the same lines were modified concurrently, or if mergeContent is disabled also if the same files were modified concurrently). In this case the submit button in the Gerrit web UI is disabled and a tooltip on the disabled submit button informs about the change being non-mergeable.
Note
If Gerrit performs a rebase or cherry-pick as part of the change submission (true for rebase if necessary, rebase always and cherry pick) Gerrit inserts additional footers into the commit message of the newly created commit:

* Change-Id: <change-id> (only if this footer is not already present, see Change-Id)
* Reviewed-on: <change-url> (links to the change in Gerrit where this commit was reviewed)
* Reviewed-by: <reviewer> (once for every reviewer with a positive Code-Review vote)
* Tested-by: <reviewer> (once for every reviewer with a positive Verified vote)
* <label-name>: <reviewer> (once for every reviewer with a positive vote on any other label)

In addition, plugins that implement a Change Message Modifier may add additional custom footers.
Note
For the value of submit.action in project.config use the exact spelling as given above, e.g. 'merge if necessary' (without the single quotes, but with the spaces).
Note
Project owners can also set the submit action in the Gerrit UI: Browse > Repositories > my/repository > Submit type
submit.matchAuthorToCommitterDate

Defines whether the author date will be changed to match the submitter date upon submit, so that git log shows when the change was submitted instead of when the author last committed. Valid values are 'true', 'false', or 'INHERIT'. The default is 'INHERIT'. This option only takes effect in submit strategies which already modify the commit, i.e. Cherry Pick, Rebase Always, and (when rebase is necessary) Rebase If Necessary.

submit.rejectEmptyCommit

Defines whether empty commits should be rejected when a change is merged. When using submit action Cherry Pick, Rebase If Necessary or Rebase Always changes may become empty upon submit, since the rebase|cherry-pick can lead to an empty commit. If this option is set to 'true' the merge would fail in such a case. An empty commit is still allowed as the initial commit on a branch.

Access section

Each access section includes a reference and access rights connected to groups. Each group listed must exist in the groups file.

Please refer to the Access Categories documentation for a full list of available access rights.

MIME Types section

The mimetype section may be configured to force the web code reviewer to return certain MIME types by file path. MIME types may be used to activate syntax highlighting.

[mimetype "text/x-c"]
  path = *.pkt
[mimetype "text/x-java"]
  path = api/current.txt

Capability section

The capability section only appears once, and only in the All-Projects repository. It controls Gerrit administration capabilities that are configured on a global level.

Please refer to the Global Capabilities documentation for a full list of available capabilities.

Label section

Please refer to Custom Labels documentation.

Submit Requirement section

Please refer to Configuring Submit Requirements documentation.

branchOrder section

Defines a branch ordering which is used for backporting of changes. Backporting will be offered for a change (in the Gerrit UI) for all more stable branches where the change can merge cleanly.

branchOrder.branch

A branch name, typically multiple values will be defined. The order of branch names in this section defines the branch order. The topmost is considered to be the least stable branch (typically the master branch) and the last one the most stable (typically the last maintained release branch).

Example:

[branchOrder]
  branch = master
  branch = stable-2.9
  branch = stable-2.8
  branch = stable-2.7

The branchOrder section is inheritable. This is useful when multiple or all projects follow the same branch rules. A branchOrder section in a child project completely overrides any branchOrder section from a parent i.e. there is no merging of branchOrder sections. A present but empty branchOrder section removes all inherited branch order.

Branches not listed in this section will not be included in the mergeability check. If the branchOrder section is not defined then the mergeability of a change into other branches will not be done.

reviewer section

Defines config options to adjust a project’s reviewer workflow such as enabling reviewers and CCs by email.

reviewer.enableByEmail

A boolean indicating if reviewers and CCs that do not currently have a Gerrit account can be added to a change by providing their email address.

This setting only takes effect for changes that are readable by anonymous users.

Default is INHERIT, which means that this property is inherited from the parent project. If the property is not set in any parent project, the default value is FALSE.

reviewer.skipAddingAuthorAndCommitterAsReviewers

Whether to skip adding the Git commit author and committer as reviewers for a new change.

Default is INHERIT, which means that this property is inherited from the parent project. If the property is not set in any parent project, the default value is FALSE.

The file groups

Each group in this list is linked with its UUID so that renaming of groups is possible without having to rewrite every groups file in every repository where it’s used.

This is what the default groups file for All-Projects.git looks like:

# UUID                                         Group Name
#
3d6da7dc4e99e6f6e5b5196e21b6f504fc530bba       Administrators
global:Anonymous-Users                         Anonymous Users
global:Change-Owner                            Change Owner
global:Project-Owners                          Project Owners
global:Registered-Users                        Registered Users

This file can’t be written to by the git config command.

In order to reference a group in project.config, it must be listed in the groups file. When editing permissions through the web UI this file is maintained automatically, but when pushing updates to refs/meta/config this must be dealt with by hand. Gerrit will refuse project.config files that refer to groups not listed in groups.

The UUID of a group can be found on the General tab of the group’s page in the web UI or via the -v option to the ls-groups SSH command.

The file rules.pl

The rules.pl files allows you to replace or amend the default Prolog rules that control e.g. what conditions need to be fulfilled for a change to be submittable. This file content should be interpretable by the 'Prolog Cafe' interpreter.

You can read more about the rules.pl file and the prolog rules on the Prolog cookbook page.