Blog
GitHub CODEOWNERS: syntax, examples and required reviews
How a CODEOWNERS file picks reviewers on GitHub, how its patterns match, how to require code owner approval, and the mistakes that quietly break it.
Alex Mercer
A GitHub CODEOWNERS file maps paths in a repository to the people or teams responsible for them. When someone opens a pull request that changes those paths, GitHub requests a review from their owners automatically, and with branch protection or a ruleset you can require a code owner's approval before it merges.
For how review fits into the wider flow, see what a pull request is and how it gets merged.
What a CODEOWNERS file does
It does three things (About code owners):
Requests reviews. When someone opens a pull request that modifies code you own, GitHub requests your review. Draft pull requests don't trigger requests; owners are notified when the draft is marked ready for review.
Shows ownership. On a file's page, hover over the shield icon in the header to see who owns the file and which CODEOWNERS line made them owner.
Gates merging, if you turn that on. With "Require review from Code Owners" enabled in branch protection or a ruleset, a pull request that changes owned code needs code owner approval before it can merge.
You can define code owners in public repositories on GitHub Free and GitHub Free for organizations, and in public and private repositories on GitHub Pro, GitHub Team, GitHub Enterprise Cloud and GitHub Enterprise Server.
Every owner needs write access to the repository. A team must also be visible, and it needs write access itself, even if all its members already have write access some other way.
Where the CODEOWNERS file goes
Create a file named CODEOWNERS in .github/, the repository root or docs/. If there's one in more than one of those places, GitHub searches them in that order and uses the first it finds. Use .github/CODEOWNERS: GitHub's docs describe that location, with an owner on the file itself, as the most secure setup.
Two branch rules matter:
The base branch's file decides. Each CODEOWNERS file sets owners for the branch it's on, and review requests come from the file on the pull request's base branch. A pull request into
releaseuses the CODEOWNERS file onrelease, so an edit merged intomaindoesn't apply there untilreleasehas it too.Forks use the upstream file. A pull request from a fork into the upstream repository uses CODEOWNERS from the upstream base branch. If the base branch is in your fork, your fork's file applies, and owners are only requested if they have write access to your fork.
CODEOWNERS syntax
Each line is a file pattern followed by one or more owners. Patterns follow most of the rules of gitignore patterns. Lines starting with # are comments, and GitHub's own example also puts a comment at the end of a line.
Patterns
These examples come from GitHub's docs:
Pattern | Matches |
|---|---|
| Every file in the repository |
| Every |
|
|
|
|
| Files directly in |
| Any directory named |
| Any |
The last matching pattern wins
When several patterns match a file, the last one in the file takes precedence. Put the catch-all first and the specific rules after it:
A pull request that only changes JavaScript files requests @acme/frontend, not @acme/platform. Swap the two lines and * becomes the last match for every file, so the platform team owns the JavaScript too.
A pattern with no owners removes ownership for that path. Changes there can then be approved by anyone with write access:
Owners: users, teams and email addresses
A user:
@usernameA team:
@org/team-nameAn email address added to a user's GitHub account, such as
user@example.com. This works in most cases, but not for managed user accounts.
If you name a user or team that doesn't exist or doesn't have enough access, no code owner is assigned.
All owners for a pattern go on one line. If the same pattern appears on two lines, only the last line's owners count:
Syntax that doesn't work
Three gitignore features don't work in CODEOWNERS:
!to negate a pattern[ ]to define a character range\to escape a pattern that starts with#
Paths are also case sensitive, because GitHub evaluates the file on a case-sensitive file system. That holds even if you work on a case-insensitive system such as macOS: /Docs/ doesn't match docs/.
A commented example CODEOWNERS file
This one is for a fictional organization, acme. Replace the team names with your own.
What a few changed files resolve to:
Changed file | Owner | Why |
|---|---|---|
|
|
|
|
|
|
| None | The last match has no owner |
|
|
|
If payments should review migrations too, list both teams on the **/migrations line. An approval from either team then meets the requirement, and approvals from both aren't required. To require approval from both teams, use required reviewers in a ruleset.
How to require code owner approval
Review requests alone don't block anything. To require an owner's approval before merging, use a branch protection rule or a ruleset.
With a branch protection rule
In the repository, open Settings, then Branches.
Under "Branch protection rules", click Add classic branch protection rule.
Under "Branch name pattern", enter the branch, for example
main.Select Require a pull request before merging, then Require review from Code Owners.
These steps come from Managing a branch protection rule. Protected branches are available on the same plans as code owners, and only one branch protection rule can apply to a branch at a time (About protected branches).
With a ruleset
Rulesets are GitHub's alternative to branch protection rules. In a branch ruleset, the Require a pull request before merging rule has an option to require review from code owners (Available rules for rulesets). Their advantages over branch protection rules include statuses, better discoverability for people without admin access, and the ability to apply several at once. Rulesets are available in public repositories on GitHub Free and GitHub Free for organizations, and in public and private repositories on GitHub Pro, GitHub Team and GitHub Enterprise Cloud (About rulesets).
What counts as code owner approval
Once you require reviews from code owners, GitHub's protected branches docs say that any pull request that affects code with a code owner must be approved by that code owner before it can merge into the protected branch.
When code has several owners, an approval from any one of them is enough. With *.js @global-owner1 @global-owner2, either owner can approve changes to JavaScript files, and approvals from both aren't required.
Required reviewers in rulesets
Rulesets can also require approval from specific teams when a pull request changes certain files, set in the ruleset instead of in CODEOWNERS. For each of up to 15 teams, you give file patterns in .gitignore format (where ! negation does work) and a number of required approvals from 0 to 10. Zero adds the team for visibility without requiring approval. Teams need write access for their approvals to count, and the rule isn't available on user-owned repositories, which have no teams.
Team review assignment
When a team owns a path, the whole team is requested. In the team's code review settings you can turn on auto assignment, which replaces the team with a chosen number of members, picked by round robin (who had a request least recently) or load balance (based on each member's recent review requests and open reviews). If branch protection requires code owner review, the team request stays, the chosen member is added next to it, and the team is removed once that member reviews (Managing code review settings for your team).
Keep ownership realistic. If two senior engineers own half the repository, pull requests touching those paths wait on them; how your best developers become your biggest bottleneck covers that pattern.
Protect the CODEOWNERS file itself
To fully protect a repository against unauthorized changes, the CODEOWNERS file needs an owner too. The most secure setup in GitHub's docs is a file in .github/ owned by the repository owner, either the file alone or the whole directory:
CODEOWNERS file size and syntax limits
Size: the file must be under 3 MB. Over that, GitHub doesn't load it, so no owners are shown and nobody is requested for review. Wildcard patterns can shrink a long file.
Invalid lines are skipped. Open the file on GitHub to see errors highlighted, or list them with the REST API, which takes an optional
reffor a branch, tag or commit (REST API docs):
Unknown owners aren't assigned. If a user or team doesn't exist or lacks access, that line assigns no code owner. Recheck owners when people leave or team permissions change.
Common CODEOWNERS mistakes
Catch-all at the bottom.
*on the last line overrides every rule above it.Owners split across lines. Only the last line for a pattern counts.
Owners without write access. Users and teams need explicit write access, and teams must be visible.
gitignore habits.
!,[ ]and\#don't work. To carve out a path, give it a line with no owners.Wrong case.
/Docs/and/docs/are different paths to GitHub.The file is on the wrong branch. Requests come from the CODEOWNERS file on the pull request's base branch, so update it on every long-lived branch that takes pull requests.
Two CODEOWNERS files. GitHub uses the first it finds in
.github/, the root anddocs/, so edits to the other one do nothing.Expecting every listed owner to approve. When a line lists several owners, an approval from any one of them is enough.
Expecting requests on drafts. Owners are notified when a draft is marked ready for review, not before.
No owner for CODEOWNERS itself. GitHub's docs say full protection needs an owner for the file, ideally the repository owner.
Code owners and AI-written pull requests
CODEOWNERS rules match file paths, not authors. The file has no way to tell agent-written changes from hand-written ones, so the same owners are requested for both. If coding agents open some of your pull requests, these are the people asked to sign off on that code.
AI code review can work next to the code owner's review: cubic reviews pull requests on GitHub, finds bugs and learns a team's rules, while the owner's approval stays the one your branch rules require. For what an owner should check once requested, see how to review a pull request on GitHub, and use a pull request template to ask authors which parts an agent wrote and how they checked them.
GitLab code owners
GitLab has its own CODEOWNERS file, on the Premium and Ultimate tiers (GitLab Docs). The basics match GitHub's: path patterns followed by owners, and the last matching entry wins. The differences (CODEOWNERS syntax):
Locations, in a different order. GitLab checks the root, then
docs/, then.gitlab/, and uses the firstCODEOWNERSfile it finds.Approval needs a protected branch. To require code owner approval, the merge request's target branch must be protected with Code Owner approval turned on. GitLab compares the changed files with the CODEOWNERS file in the target branch.
Sections.
[Section name]groups rules, and each section is enforced separately.^[Section name]makes a section optional, and[Section name][2]requires two approvals.More kinds of owner. Users, groups and subgroups, email addresses, and roles such as
@@maintainer(Developer, Maintainer and Owner roles only).Exclusions. A
!prefix exempts a path from code owner approval within its section (generally available since GitLab 17.11).No inline comments. Comments go on their own lines.
GitHub | GitLab | |
|---|---|---|
Plans | Public repositories on Free; public and private on Pro, Team, Enterprise Cloud and Enterprise Server | Premium and Ultimate |
Locations (first found is used) |
| root, |
Owners | Users, teams, email addresses | Users, groups and subgroups, email addresses, roles |
Precedence | Last matching pattern wins | Last matching entry wins within each section |
Exclusions | No |
|
Approvals | Any one of a line's owners can approve | Per section, with optional sections and approval counts |
Enforcement | Branch protection or ruleset | Protected branch with Code Owner approval |
Inline comments | Supported | Not supported |
For more on how GitHub and GitLab review flows differ, see pull request vs merge request.
FAQ
What is a CODEOWNERS file in GitHub?
A CODEOWNERS file is a plain text file, usually .github/CODEOWNERS, that lists path patterns and the users or teams who own them. GitHub uses it to request reviews from those owners automatically when a pull request changes their files. With branch protection or a ruleset, it can also require an owner's approval before merging.
How do I add code owners in GitHub?
Create a file named CODEOWNERS in .github/, the root or docs/, add lines such as /docs/ @org/docs-team, and merge it into the branch your pull requests target. Make sure every owner has write access to the repository. To require their approval, turn on "Require review from Code Owners" in a branch protection rule or ruleset.
Are code owners notified automatically?
Yes. GitHub requests a review from code owners when someone opens a pull request that modifies their files, and notifies them when a draft pull request that touches their files is marked ready for review. Drafts don't trigger requests on their own.
Do all code owners have to approve a pull request?
No. When code owner review is required and code has several owners, an approval from any one of them is enough, and approvals from all of them aren't required. To require approvals from more than one team, or several approvals from one team, use required reviewers in a ruleset.
Does Bitbucket support CODEOWNERS?
Yes. Bitbucket Cloud reads a CODEOWNERS file from a .bitbucket directory at the repository root, uses gitignore-style patterns where the last matching pattern has the highest precedence, and always reads the file from the pull request's destination branch (Bitbucket Cloud docs). New pull requests get the matching owners as suggested reviewers. When a group owns a path, Bitbucket picks one member at random unless the line sets a strategy, as in *.py @workspace-slug/backenders:least_busy(2), which picks the two members already reviewing the fewest open pull requests.
