Syntax of CODEOWNERS file
- Tier: Premium, Ultimate
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
The CODEOWNERS file uses a syntax to define ownership rules.
Each line in the file represents a rule, and specifies a file path pattern and one or more owners.
The key elements are:
- File paths: Specific files, directories, or wildcards.
- Code Owners: Use
@mentionsfor users, groups, or roles. - Comments: Lines starting with
#are ignored. Inline comments are unsupported. Any Code Owners listed in a comment are parsed. - Sections: Optional groupings of rules, defined using
[Section name].
If an entry is duplicated in a section, the last entry is used. Rules defined later in the file take precedence over earlier rules.
Here are some examples:
# Specify a default Code Owner for all files with a wildcard:
* @default-owner
# Specify multiple Code Owners to a specific file:
README.md @doc-team @tech-lead
# Specify a Code Owner to all files with a specific extension:
*.rb @ruby-owner
# Specify Code Owners with usernames or email addresses:
LICENSE @legal janedoe@gitlab.com
# Use group names to match groups and nested groups:
README @group @group/with-nested/subgroup
# Specify a Code Owner to a directory and all its contents:
/docs/ @all-docs
/docs/* @root-docs
/docs/**/*.md @markdown-docs # Match specific file types in any subdirectory
/db/**/index.md @index-docs # Match a specific file name in any subdirectory
# Use a section to group related rules:
[Documentation]
ee/docs @docs
docs @docs
# Assign a role as a Code Owner:
/config/ @@maintainerSections
In a CODEOWNERS file, sections are named areas that are analyzed separately,
and always enforced. Until you define a section, GitLab treats your entire CODEOWNERS file
as a single section.
Adding more sections changes how GitLab evaluates the file:
- GitLab treats entries without sections, including rules defined before the first section header, as if they were another, unnamed section.
- Each section enforces its rules separately.
- Only one Code Owner pattern per section is matched to a file path.
- Rules defined later in the file take precedence over earlier rules.
For example, in a CODEOWNERS file with sections that define the Code Owners of a README file:
* @admin
[README Owners]
README.md @user1 @user2
internal/README.md @user4
[README other owners]
README.md @user3- The Code Owners for the
README.mdin the root directory are:@admin, from the unnamed section.@user1and@user2, from[README Owners].@user3, from[README other owners].
- The Code Owners for
internal/README.mdare:@admin, from the unnamed section.@user4, from the last entry in[README Owners].@user3from[README other owners]. (Both lines in[README Owners]match this file’s name, but only the last line in the section is kept.)
To add a section to the CODEOWNERS file, enter a section name in square brackets,
followed by the files or directories, and users, groups, or subgroups:
[README Owners]
README.md @user1 @user2
internal/README.md @user2Each Code Owner in the merge request widget is listed under a label.
The following image shows Default, Frontend, and Technical Writing sections:
For more section configuration options, see:
Section headings and names
Section headings must have a name. Section names are case-insensitive, and sections with duplicate names are combined. For protected branches only, they can:
- Require approval (default).
- Be optional (prefixed with
^). - Require a specific number of approvals. For more information, see Group inheritance and eligibility and Approvals shown as optional.
- Include default owners.
Examples:
# Required section
[Section name]
# Optional section
^[Section name]
# Section requiring 5 approvals
[Section name][5]
# Section with @username as default owner
[Section name] @username
# Section with @group and @subgroup as default owners and requiring 2 approvals
[Section name][2] @group @subgroupSet default Code Owner for a section
If multiple file paths inside a section share the same ownership, define default Code Owners for the section. All paths in that section inherit this default, unless you override the section default on a specific line.
Default owners are applied when specific owners are not specified for file paths. Specific owners defined beside the file path override default owners.
For example:
[Documentation] @docs-team
docs/
README.md
[Database] @database-team @agarcia
model/db/
config/db/database-setup.md @docs-teamIn this example:
@docs-teamowns all items in theDocumentationsection.@database-teamand@agarciaown all items in theDatabasesection exceptconfig/db/database-setup.md, which has an override assigning it to@docs-team.
Compare this behavior to when you use regular entries and sections together, when entries in sections don’t override entries without sections.
Optional sections
You can designate optional sections in your Code Owners file. Optional sections enable you to designate responsible parties for various parts of your codebase, but not require approval from them. This approach provides a more relaxed policy for parts of your project that are frequently updated, but don’t require stringent reviews.
To treat the entire section as optional, prepend the section name with the caret ^ character.
In this example, the [Go] section is optional:
[Documentation]
*.md @root
[Ruby]
*.rb @root
^[Go]
*.go @rootThe optional Code Owners section displays in merge requests under the description:
If a section is duplicated in the file, and one of them is marked as optional and the other isn’t, the section is required.
Optional sections in the CODEOWNERS file are treated as optional only
when changes are submitted by using merge requests. If a change is submitted directly
to the protected branch, approval from Code Owners is still required, even if the
section is marked as optional.
Eligible code owners
Eligibility rules determine who can be a valid code owner. Specific rules apply depending on the
reference method in the CODEOWNERS file: username, group, or role.
User eligibility
To be eligible as code owners, users referenced by their username (@username) must be authorized
for the project. The following rules apply:
- Project and group visibility settings do not affect eligibility.
- Users banned from a group cannot be Code Owners.
- Eligible users include those with:
- Direct membership in the project with at least the Developer role.
- Membership in the project’s group (direct or inherited).
- Membership in any of the project’s group’s ancestors.
- Direct or inherited membership in a group that has been invited to the project.
- Direct membership (but not inherited) in a group that has been invited to the project’s group.
- Direct membership (but not inherited) in a group that has been invited to the project’s group’s ancestor.
Group eligibility
When referencing a group with group name (@group_name) or nested group name (@nested/group/names),
the following rules apply:
- Group visibility settings do not affect eligibility.
- Only direct members of the referenced group are eligible. Inherited members are not included.
- Eligible groups include:
- The project’s group.
- The project’s group’s ancestors.
- Groups that are invited to the project with at least the Developer role.
Role eligibility
When referencing a role (@@role), the following rules apply:
- Only Developer, Maintainer, and Owner roles can be used as Code Owners.
- Only direct project members with the specified role are eligible.
- Roles are not inclusive of higher roles. For example, specifying
@@developerdoes not include users with Maintainer or Owner roles.
For more complex scenarios involving group inheritance and eligibility, see Group inheritance and eligibility.
Add a role as a Code Owner
You can add or set a role for direct project members as Code Owners:
- Use the
@@prefix to set a role. - Only Developer, Maintainer, and Owner roles are available.
- Roles are not inclusive of higher roles. For example, specifying
@@developerdoes not include users with Maintainer or Owner roles. - Only direct project members with the specified roles are eligible Code Owners.
- It is possible to specify plural roles. For example,
@@developersis accepted.
The following example sets all direct project members with the Developer or Maintainer
role as Code Owners for file.md:
Open the
CODEOWNERSfile.Add a line using the following pattern:
file.md @@developer @@maintainerSave the file.
Commit and merge the changes.
Add a group as a Code Owner
You can set direct members of a group or subgroup as a Code Owner. For more information about group membership, see Membership types.
Prerequisites:
- The group must be invited to the project.
To set direct members of a group or subgroup as a Code Owner:
Open the
CODEOWNERSfile.Enter text that follows one of these patterns:
# All direct group members as Code Owners for a file file.md @group-x # All direct subgroup members as Code Owners for a file file.md @group-x/subgroup-y # All direct group and direct subgroup members as Code Owners for a file file.md @group-x @group-x/subgroup-ySave the file.
Commit and merge the changes.
Example configuration
[Maintainers]
* @gitlab-org/maintainers/group-nameIn this example:
The group
group-nameis listed under the[Maintainers]section.The
group-namecontains the following direct members:In the merge request approval widget, the same direct members are listed as
Maintainers:
When Global SAML group memberships lock is enabled, you cannot set a group or subgroup as a Code Owner. For more information, see Incompatibility with Global SAML group memberships lock.
If you encounter issues, refer to User not shown as possible approver.
Path matching
Paths can be absolute, relative, directory, wildcard, or globstar, and are matched against the repository root.
Absolute paths
Paths starting with / match from the repository root:
# Matches only README.md in the root.
/README.md
# Matches only README.md inside the /docs directory.
/docs/README.mdRelative paths
Paths without a leading / are treated as globstar paths:
# Matches /README.md, /internal/README.md, /app/lib/README.md
README.md @username
# Matches /internal/README.md, /docs/internal/README.md, /docs/api/internal/README.md
internal/README.mdWhen using globstar paths, be cautious of unintended matches.
For example, README.md without a leading / matches any README.md
file in any directory or subdirectory of the repository.
Directory paths
End a path with / to match all files in the directory and its subdirectories:
# Matches all files in /docs/ and its subdirectories
/docs/Wildcard paths
Use * to match multiple characters:
# Any markdown files in the docs directory
/docs/*.md @username
# /docs/index file of any filetype
# For example: /docs/index.md, /docs/index.html, /docs/index.xml
/docs/index.* @username
# Any file in the docs directory with 'spec' in the name.
# For example: /docs/qa_specs.rb, /docs/spec_helpers.rb, /docs/runtime.spec
/docs/*spec* @username
# README.md files one level deep within the docs directory
# For example: /docs/api/README.md
/docs/*/README.md @usernameGlobstar paths
Use ** to match files or patterns across multiple directory levels:
# For example: /docs/index.md, /docs/api/index.md, and /docs/api/graphql/index.md.
/docs/**/index.mdTo match all files in a directory,
use directory paths with a trailing slash (/).
Exclusion patterns
Prefix files or paths with ! to exempt or exclude them from requiring code owner approval.
Exclusions apply in their section. In the following example:
- The
pom.xmlexclusion applies to the default section. - The
/config/**/*.rbexclusion only affects Ruby files in the Ruby section.
# All files require approval from @username
* @username
# Except pom.xml which needs no approval
!pom.xml
[Ruby]
# All ruby files require approval from @ruby-team
*.rb @ruby-team
# Except Ruby files in the config directory
!/config/**/*.rbThe following guidelines explain how exclusion patterns behave:
Exclusions are evaluated in order in their section. For example:
* @default-owner !*.rb # Excludes all Ruby files. /special/*.rb @ruby-owner # This won't take effect as *.rb is already excluded.After a pattern is excluded, it cannot be included again in the same section:
[Ruby] *.rb @ruby-team # All Ruby files need Ruby team approval. !/config/**/*.rb # Ruby files in config don't need Ruby team approval. /config/routes.rb @ops # This won't take effect as config Ruby files are excluded.Files matching an exclusion pattern do not require code owner approval for that section. If you need different exclusions for different owners, use multiple sections:
[Ruby] *.rb @ruby-team !/config/**/*.rb # Config Ruby files don't need Ruby team approval. [Config] /config/ @ops-team # Config files still require ops-team approval.Use exclusions for files that are automatically updated:
* @default-owner # Files updated by automation don't need approval. !package-lock.json !yarn.lock !**/generated/ # Any files in generated directories. !.gitlab-ci.yml
Entry owners
Entries must have one or more owners These can be groups, subgroups, and users.
/path/to/entry.rb @group
/path/to/entry.rb @group/subgroup
/path/to/entry.rb @user
/path/to/entry.rb @group @group/subgroup @userFor more information on adding groups as Code Owners, see Add a group as a Code Owner.



