One of the most common questions in Azure DevOps code reviews is surprisingly simple:
“Why can this person review a pull request but not merge it?”
Or the opposite:
“Why was someone able to merge a PR without approval?”
The answer almost always comes down to permissions.
In Azure DevOps, pull request workflows are controlled by three layers working together:
Access levels (Stakeholder, Basic, Visual Studio Enterprise)
Security groups (Readers, Contributors, Administrators)
Repository-level permissions and branch policies
If any one of these layers blocks an action, the user cannot perform it, even if the other layers allow it.
This means a developer might be able to:
view a pull request
comment on the code
approve the changes
…but still cannot merge the PR.
In this guide, we’ll break down exactly how Azure DevOps permissions control the pull request workflow, including:
Who can create pull requests
Who can review and approve code changes
Who can merge or bypass policies
How security groups affect reviewer permissions
How to grant reviewer-only access or restrict merge rights
By the end, you’ll understand exactly how Azure DevOps decides who can review, approve, and merge pull requests.
How Permissions Work for Pull Requests in Azure DevOps
Permissions in Azure DevOps control who can create, view, review, approve, and complete pull requests. They operate at three levels that work together: access levels (what the user’s license allows), security group membership (what the project grants), and repository-level permissions (what the repo-specific settings allow).
If any one of these three levels blocks an action, the user can’t perform it, even if the other two levels allow it. A user with Basic access who belongs to the Contributors group but has “Contribute” set to Deny on a specific repository still can’t create PRs in that repo.
So, let's decode on how every permission affects the pull request workflow in Azure DevOps, from creating a branch to merging the final PR.
Access Levels: Stakeholder vs Basic vs Visual Studio Enterprise
Azure DevOps has three access levels that gate what features a user can access across the platform. For code review, the access level determines whether a user can even open the Repos section.
Access Level | Can View Repos / PRs? | Can Create PRs? | Can Review / Comment? | Can Vote (Approve/Reject)? | Can Complete (Merge)? | Can Configure Policies? |
|---|---|---|---|---|---|---|
Stakeholder | No, Repos section is not available (private projects). Yes for public projects. | No (private). Yes (public). | No (private). Yes (public). | No (private). Yes (public). | No | No |
Basic | Yes | Yes (with repo permissions) | Yes | Yes | Yes (with repo permissions) | No (needs admin) |
Visual Studio Enterprise | Yes | Yes (with repo permissions) | Yes | Yes | Yes (with repo permissions) | No (needs admin) |
Key takeaway: Stakeholder access cannot interact with Azure Repos in private projects at all. Every developer who participates in code review, creating PRs, reviewing code, or approving merges, needs at least Basic access. Visual Studio Enterprise and Basic have identical Repos permissions; the difference is in other Azure DevOps services (Test Plans, Artifacts, etc.).
Security Groups and Their Default Permissions
Azure DevOps projects come with built-in security groups. Each group has default permissions that apply to all repositories in the project unless overridden at the repo level.
Default Security Groups: Repository Permissions
Permission | Readers | Contributors | Build Administrators | Project Administrators |
|---|---|---|---|---|
Read (view code, PRs, branches) | ✅ Allow | ✅ Allow | ✅ Allow | ✅ Allow |
Contribute (push code, create branches) | ❌ Deny | ✅ Allow | ❌ Deny | ✅ Allow |
Contribute to pull requests (create PRs, comment, vote) | ❌ Deny | ✅ Allow | ❌ Deny | ✅ Allow |
Create branch | ❌ Deny | ✅ Allow | ❌ Deny | ✅ Allow |
Create tag | ❌ Deny | ✅ Allow | ❌ Deny | ✅ Allow |
Edit policies (branch policies) | ❌ Deny | ❌ Deny | ❌ Deny | ✅ Allow |
Bypass policies when completing pull requests | ❌ Deny | ❌ Deny | ❌ Deny | ✅ Allow |
Bypass policies when pushing | ❌ Deny | ❌ Deny | ❌ Deny | ✅ Allow |
Force push (rewrite history) | ❌ Deny | ❌ Deny | ❌ Deny | ✅ Allow |
Manage permissions | ❌ Deny | ❌ Deny | ❌ Deny | ✅ Allow |
Remove others’ locks | ❌ Deny | ❌ Deny | ❌ Deny | ✅ Allow |
What Each Permission Controls in the PR Workflow
Permission | What It Controls |
|---|---|
Read | Can see the repository, browse code, view pull requests and their diffs, see branch policies |
Contribute | Can push commits to branches, create branches, upload files. Required to push changes that a PR contains. |
Contribute to pull requests | Can create pull requests, add comments, vote (approve/reject/wait for author), resolve comments. This is the core “participate in code review” permission. |
Create branch | Can create new branches. Without this, a user can’t create a feature branch to PR from. |
Edit policies | Can configure branch policies (required reviewers, build validation, merge types, etc.) on the repository. |
Bypass policies when completing pull requests | Can merge a PR even when policies are not satisfied. Use sparingly, intended for emergency hotfixes. |
Bypass policies when pushing | Can push directly to a protected branch, bypassing the PR requirement. Dangerous, effectively disables branch protection for this user. |
Force push | Can rewrite git history on branches. Required for rebase workflows on shared branches. Dangerous on protected branches. |
Manage permissions | Can change the repository’s permission settings for other users and groups. |
The Complete PR Permissions Matrix
This table maps every action in the pull request workflow to the specific permission required.
Action | Required Permission | Default Group | Notes |
|---|---|---|---|
View a pull request | Read | Readers, Contributors, Admins | Minimum permission to see PRs |
View the PR diff | Read | Readers, Contributors, Admins | Same as viewing code |
Create a pull request | Contribute + Contribute to pull requests | Contributors, Admins | Needs both: Contribute (to have pushed the branch) + Contribute to PRs (to create the PR itself) |
Add comments on a PR | Contribute to pull requests | Contributors, Admins | Inline comments, general comments, and replies |
Resolve / re-activate comments | Contribute to pull requests | Contributors, Admins | Any reviewer can resolve; authors can also resolve |
Vote (Approve / Reject / Wait) | Contribute to pull requests | Contributors, Admins | Voting permissions are the same as commenting |
Add or remove reviewers | Contribute to pull requests | Contributors, Admins | Anyone who can comment can also modify the reviewer list |
Set auto-complete | Contribute to pull requests | Contributors, Admins | Requires the user to also have Complete permission (Contribute) |
Complete (merge) a PR | Contribute to pull requests + Contribute | Contributors, Admins | Both permissions required. The user needs write access to the target branch. |
Complete a PR when policies fail | Bypass policies when completing PRs | Admins only (by default) | Override button appears only for users with this permission |
Push directly to a protected branch | Bypass policies when pushing | Admins only (by default) | Skips PR requirement entirely |
Configure branch policies | Edit policies | Admins only (by default) | Controls who can set required reviewers, build validation, etc. |
Delete a branch after merge | Contribute | Contributors, Admins | Controlled by Contribute permission on the branch |
Abandon a PR | Contribute to pull requests | Contributors, Admins | PR author or anyone with this permission can abandon |
Reactivate an abandoned PR | Contribute to pull requests | Contributors, Admins | Same as abandon |
How to Grant or Restrict Permissions
Grant Review Permissions to a User
If someone needs to review PRs but currently can’t (e.g., they’re in the Readers group), add them to Contributors or grant specific permissions:
Option A: Add to Contributors group (recommended for most cases)
Go to Project Settings → Permissions → Groups
Click Contributors
Click Members → Add
Search for the user and add them
This grants all standard PR permissions: create, comment, vote, and complete.
Option B: Grant specific repo-level permissions (for fine-grained control)
Go to Project Settings → Repos → Repositories → select the repo
Click Security
Search for the user or group
Set Contribute to pull requests to Allow
Use Option B when you want someone to review and comment on PRs without being able to push code. For example, a security engineer who reviews PRs but doesn’t contribute code to the repo.
Restrict Merge Permissions
To prevent specific users from completing (merging) PRs while still allowing them to review:
Go to Project Settings → Repos → Repositories → select the repo
Click Security
Find the user or custom group
Set Contribute to Deny (this blocks push and merge)
Keep Contribute to pull requests as Allow (they can still review and vote)
This creates a “reviewer only” role: the user can read code, comment, and vote, but cannot merge.
Grant Policy Bypass for Emergency Hotfixes
During incidents, you may need to merge a PR before all policies are satisfied (e.g., a failing test that’s unrelated to the fix). Rather than giving Project Admin rights, grant the specific bypass permission:
Go to Project Settings → Repos → Repositories → select the repo
Click Security
Find the user or create a dedicated “Hotfix” security group
Set Bypass policies when completing pull requests to Allow
Create a dedicated “Hotfix Approvers” group with this permission and add only senior engineers or team leads. This keeps bypass available for emergencies without granting full admin rights.
Restrict Direct Pushes to Protected Branches
To ensure all changes go through PRs (no direct pushes to main):
Go to Project Settings → Repos → Repositories → select the repo → Policies → select the branch
Under branch policies, there’s no explicit “require PR” toggle — instead, when you enable any branch policy (even just “Minimum number of reviewers” set to 1), Azure DevOps automatically blocks direct pushes and requires a PR
To further lock it down, go to Security on the repo, find the Contributors group, and verify Bypass policies when pushing is set to Not set or Deny
CODEOWNERS Equivalent in Azure DevOps: Automatically Included Reviewers
Azure DevOps doesn’t have a CODEOWNERS file like GitHub. Instead, it uses Automatically included reviewers in branch policies to achieve the same result — automatically adding specific reviewers when specific file paths are changed.
How It Works
When a PR is created that modifies files matching a path filter, Azure DevOps automatically adds the specified reviewers. These reviewers can be set as required (must approve before merge) or optional (notified but don’t block).
Setting Up Auto-Reviewers (CODEOWNERS Equivalent)
Go to Project Settings → Repos → Repositories → select your repo
Click Policies → select the target branch (e.g.,
main)Under Automatically included reviewers, click Add
Configure:
Reviewers: The person or group to auto-add
Path filter: Which file paths trigger this reviewer (e.g.,
/src/api/*,/infrastructure/*,.sql)Required: Whether this reviewer must approve (blocks merge if they don’t)
Allow requestors to approve their own changes: Whether the PR author counts if they’re the auto-included reviewer
Example: Replicating a CODEOWNERS File
A GitHub CODEOWNERS file like this:
Translates to these Azure DevOps “Automatically included reviewers” policies on the main branch:
Path Filter | Reviewer | Required? | Equivalent CODEOWNERS Line |
|---|---|---|---|
| [Backend Team] group | Yes |
|
| [Frontend Team] group | Yes |
|
| [DevOps Team] group | Yes |
|
| [DBA Team] group | Yes |
|
| [Tech Writers] group | No (optional) |
|
Key Differences from GitHub CODEOWNERS
Feature | GitHub CODEOWNERS | Azure DevOps Auto-Reviewers |
|---|---|---|
Configuration location |
| Branch policy settings (UI or REST API) |
Who can modify | Anyone with write access to the file | Only users with Edit policies permission |
Granularity | Per-file path patterns | Per-file path patterns (same) |
Required vs optional | All entries are required by default | Configurable per entry — required or optional |
Multiple owners per path | Supported (last match wins) | Supported (all matching reviewers are added) |
Branch-specific | Single file applies to all protected branches | Configured per branch — can have different reviewers per branch |
Self-approval | Not allowed by default | Configurable per policy — “Allow requestors to approve their own changes” |
The Azure DevOps approach is more flexible (per-branch configuration, required vs optional per entry, self-approval toggle) but less portable (lives in settings, not in a repo file). Teams migrating from GitHub need to manually recreate their CODEOWNERS rules as auto-reviewer policies.
Permission Inheritance and Override Rules
Azure DevOps permissions follow an inheritance chain with specific override rules that are critical to understand when troubleshooting access issues.
The Inheritance Chain
Permissions set at a higher level flow down to lower levels unless explicitly overridden. A user who is a Contributor at the project level is a Contributor on all repositories in that project, unless a specific repository overrides their permissions.
Override Rules
Rule | Example |
|---|---|
Explicit Deny always wins | If a user’s group has Contribute = Allow, but the user is individually set to Contribute = Deny, the Deny wins |
Explicit settings override inherited | A repo-level Allow overrides a project-level Not set |
Not set ≠ Deny | “Not set” means the permission is inherited from the parent. “Deny” explicitly blocks regardless of inheritance. |
User-level overrides group-level | If a user belongs to Group A (Allow) and Group B (Deny), the Deny wins — Deny always takes priority |
Most restrictive wins across groups | When a user is in multiple groups with conflicting permissions, Deny from any group overrides Allow from all others |
The “Deny Always Wins” Rule
This is the most common source of confusion. If a user belongs to two security groups:
Contributors: Contribute to pull requests = Allow
External Contractors: Contribute to pull requests = Deny
The result is Deny. The user cannot create or comment on PRs, even though they’re in the Contributors group. This is by design — Azure DevOps uses a “least privilege” model where any explicit Deny overrides all Allows.
To fix: Don’t use Deny on broad groups. Instead, use “Not set” (which inherits from the parent) and only grant Allow where needed. Reserve Deny for cases where you explicitly need to block a specific user or group from a specific action.
Troubleshooting Common Permission Errors
“TF402455: Pushes to this branch are not permitted”
What it means: You’re trying to push directly to a branch that has branch policies enabled. Azure DevOps blocks direct pushes to policy-protected branches — all changes must go through a pull request.
Fix: Create a feature branch, push your changes there, and create a PR targeting the protected branch. This is the expected behavior when branch policies are configured correctly.
If you’re an admin and need to push directly (emergency): You need the “Bypass policies when pushing” permission. Check Project Settings → Repos → Security.
“You do not have permission to create a pull request”
Possible causes:
Missing “Contribute to pull requests” permission. Go to Project Settings → Repos → select repo → Security → find the user → verify “Contribute to pull requests” is Allow, not Deny or Not set.
Stakeholder access level. Users with Stakeholder access can’t interact with Repos in private projects. Upgrade to Basic.
Repo-level override. The user may be a Contributor at the project level but have an explicit Deny at the repo level. Check repo-level security.
“You need permission to complete this pull request”
Possible causes:
Missing “Contribute” permission on the target branch. Completing a PR requires write access to the target branch. Check the branch-level permissions.
Bypass required but not granted. If policies haven’t been met and the user is trying to override, they need “Bypass policies when completing pull requests.”
Deny inheritance. The user may be in a group with an explicit Deny on Contribute. Check all group memberships.
“Cannot vote on this pull request”
Possible causes:
Missing “Contribute to pull requests” permission. Voting (approve/reject) requires this permission.
The PR is in draft state. Draft PRs don’t allow voting — the author must publish first.
The user is the PR author with self-approval disabled. If the branch policy “Allow requestors to approve their own changes” is unchecked, the PR author can’t approve their own PR.
“I can review but can’t merge: Complete button is grayed out”
The Complete button requires both “Contribute to pull requests” AND “Contribute” permissions. The user has review permissions but lacks write access to the target branch. Grant “Contribute” on the repository or target branch.
If the button is grayed out but says “Set auto-complete,” it means policies haven’t been met yet. The user has permission, but the PR isn’t ready to merge.
“Reviewer was auto-added but I don’t know why”
An “Automatically included reviewers” policy matched the file paths changed in the PR. To find which policy triggered:
Go to Project Settings → Repos → select repo → Policies → select the target branch
Check Automatically included reviewers, look for path filters that match the files in the PR
The policy name shows which reviewer/group is configured
“I have Bypass permission but I don’t see the Override button”
The “Bypass policies when completing pull requests” override only appears when policies are actually failing. If all policies pass, the standard Complete button is shown. The override button appears only when you need to bypass something.
Also verify: go to Project Settings → Repos → select repo → Security → find your user → confirm “Bypass policies when completing pull requests” is explicitly set to Allow (not inherited, not Not set).
Best Practices for PR Permission Management
Use groups, not individual assignments. Assign permissions to security groups, then add users to groups. This makes it manageable at scale — when a new developer joins, add them to “Contributors” instead of setting 15 individual permissions.
Create a “Senior Reviewer” group for bypass permissions. Instead of granting bypass to Project Admins (who have all permissions), create a dedicated group with only the bypass permission. Add team leads and senior engineers. This follows the principle of least privilege.
Don’t use Deny unless you mean it. “Not set” inherits from the parent level. “Deny” explicitly blocks and overrides all Allow settings from other groups. Most access issues are caused by an accidental Deny somewhere in the inheritance chain. Use “Not set” for permissions you want inherited.
Audit permissions quarterly. As teams change and people move between projects, permissions accumulate. Review who has bypass permissions, who has edit policies permissions, and whether any individual overrides exist that shouldn’t.
Use auto-included reviewers instead of relying on PR authors to pick reviewers. This ensures the right people review the right code every time, regardless of whether the PR author remembers to add them.
For a comprehensive guide to branch policies, required reviewers, and review workflows in Azure DevOps, see the complete code review guide.
How Permissions Interact with AI Code Review
AI code review tools like CodeAnt AI operate using service accounts or personal access tokens (PATs) that need specific permissions to function. The AI tool needs:
Read on repositories to access the PR diff and codebase
Contribute to pull requests to post inline comments and vote on PRs
Status check posting to report pass/fail quality gate results (configured via service hooks, not repo permissions)
The AI tool does not need Contribute (write) permission to branches, it doesn’t push code, only reads and comments. This means the AI reviewer operates with minimal permissions, following the principle of least privilege.
When CodeAnt AI is configured as a required status check via branch policies, the quality gate blocks merges when critical issues are found, regardless of whether human reviewers have approved. This separation of concerns means human reviewers handle architecture and design decisions while the AI handles mechanical quality and security enforcement with its own independent status.
CodeAnt AI, used by Fortune 500 development teams on Azure DevOps, works on both cloud Azure DevOps and self-hosted Azure DevOps Server. For setup instructions, see the cloud setup guide or self-hosted setup guide.
Permissions Define Your Code Review Governance
Azure DevOps pull request workflows depend heavily on permission design.
When permissions are configured correctly:
Developers can create and review PRs
Designated reviewers can approve changes
Only trusted users can merge into protected branches
Branch policies enforce quality and security standards
But when permissions are misconfigured, teams run into constant friction:
Developers unable to create PRs
Reviewers unable to approve changes
Contributors accidentally merging to protected branches
Administrators bypassing policies unintentionally
The key is understanding that Azure DevOps permissions operate across access levels, security groups, and repository settings simultaneously. Even a single conflicting rule, especially an explicit Deny, can block actions across the entire workflow.
Once the permission model is clear, teams can create predictable review workflows where responsibilities are clearly separated: developers contribute code, reviewers evaluate changes, and maintainers control merges.
Modern teams are also adding AI-assisted code review to this workflow.
Tools like CodeAnt AI integrate directly with Azure DevOps pull requests, analyzing the PR diff, posting inline review comments, and enforcing automated quality gates before a merge is allowed. This means permissions still govern who can merge, while AI tools ensure what gets merged meets quality and security standards.
When permissions, policies, and automated review work together, pull requests become more than a merge step, they become a reliable quality control system for your codebase.
One of the most common questions in Azure DevOps code reviews is surprisingly simple:
“Why can this person review a pull request but not merge it?”
Or the opposite:
“Why was someone able to merge a PR without approval?”
The answer almost always comes down to permissions.
In Azure DevOps, pull request workflows are controlled by three layers working together:
Access levels (Stakeholder, Basic, Visual Studio Enterprise)
Security groups (Readers, Contributors, Administrators)
Repository-level permissions and branch policies
If any one of these layers blocks an action, the user cannot perform it, even if the other layers allow it.
This means a developer might be able to:
view a pull request
comment on the code
approve the changes
…but still cannot merge the PR.
In this guide, we’ll break down exactly how Azure DevOps permissions control the pull request workflow, including:
Who can create pull requests
Who can review and approve code changes
Who can merge or bypass policies
How security groups affect reviewer permissions
How to grant reviewer-only access or restrict merge rights
By the end, you’ll understand exactly how Azure DevOps decides who can review, approve, and merge pull requests.
How Permissions Work for Pull Requests in Azure DevOps
Permissions in Azure DevOps control who can create, view, review, approve, and complete pull requests. They operate at three levels that work together: access levels (what the user’s license allows), security group membership (what the project grants), and repository-level permissions (what the repo-specific settings allow).
If any one of these three levels blocks an action, the user can’t perform it, even if the other two levels allow it. A user with Basic access who belongs to the Contributors group but has “Contribute” set to Deny on a specific repository still can’t create PRs in that repo.
So, let's decode on how every permission affects the pull request workflow in Azure DevOps, from creating a branch to merging the final PR.
Access Levels: Stakeholder vs Basic vs Visual Studio Enterprise
Azure DevOps has three access levels that gate what features a user can access across the platform. For code review, the access level determines whether a user can even open the Repos section.
Access Level | Can View Repos / PRs? | Can Create PRs? | Can Review / Comment? | Can Vote (Approve/Reject)? | Can Complete (Merge)? | Can Configure Policies? |
|---|---|---|---|---|---|---|
Stakeholder | No, Repos section is not available (private projects). Yes for public projects. | No (private). Yes (public). | No (private). Yes (public). | No (private). Yes (public). | No | No |
Basic | Yes | Yes (with repo permissions) | Yes | Yes | Yes (with repo permissions) | No (needs admin) |
Visual Studio Enterprise | Yes | Yes (with repo permissions) | Yes | Yes | Yes (with repo permissions) | No (needs admin) |
Key takeaway: Stakeholder access cannot interact with Azure Repos in private projects at all. Every developer who participates in code review, creating PRs, reviewing code, or approving merges, needs at least Basic access. Visual Studio Enterprise and Basic have identical Repos permissions; the difference is in other Azure DevOps services (Test Plans, Artifacts, etc.).
Security Groups and Their Default Permissions
Azure DevOps projects come with built-in security groups. Each group has default permissions that apply to all repositories in the project unless overridden at the repo level.
Default Security Groups: Repository Permissions
Permission | Readers | Contributors | Build Administrators | Project Administrators |
|---|---|---|---|---|
Read (view code, PRs, branches) | ✅ Allow | ✅ Allow | ✅ Allow | ✅ Allow |
Contribute (push code, create branches) | ❌ Deny | ✅ Allow | ❌ Deny | ✅ Allow |
Contribute to pull requests (create PRs, comment, vote) | ❌ Deny | ✅ Allow | ❌ Deny | ✅ Allow |
Create branch | ❌ Deny | ✅ Allow | ❌ Deny | ✅ Allow |
Create tag | ❌ Deny | ✅ Allow | ❌ Deny | ✅ Allow |
Edit policies (branch policies) | ❌ Deny | ❌ Deny | ❌ Deny | ✅ Allow |
Bypass policies when completing pull requests | ❌ Deny | ❌ Deny | ❌ Deny | ✅ Allow |
Bypass policies when pushing | ❌ Deny | ❌ Deny | ❌ Deny | ✅ Allow |
Force push (rewrite history) | ❌ Deny | ❌ Deny | ❌ Deny | ✅ Allow |
Manage permissions | ❌ Deny | ❌ Deny | ❌ Deny | ✅ Allow |
Remove others’ locks | ❌ Deny | ❌ Deny | ❌ Deny | ✅ Allow |
What Each Permission Controls in the PR Workflow
Permission | What It Controls |
|---|---|
Read | Can see the repository, browse code, view pull requests and their diffs, see branch policies |
Contribute | Can push commits to branches, create branches, upload files. Required to push changes that a PR contains. |
Contribute to pull requests | Can create pull requests, add comments, vote (approve/reject/wait for author), resolve comments. This is the core “participate in code review” permission. |
Create branch | Can create new branches. Without this, a user can’t create a feature branch to PR from. |
Edit policies | Can configure branch policies (required reviewers, build validation, merge types, etc.) on the repository. |
Bypass policies when completing pull requests | Can merge a PR even when policies are not satisfied. Use sparingly, intended for emergency hotfixes. |
Bypass policies when pushing | Can push directly to a protected branch, bypassing the PR requirement. Dangerous, effectively disables branch protection for this user. |
Force push | Can rewrite git history on branches. Required for rebase workflows on shared branches. Dangerous on protected branches. |
Manage permissions | Can change the repository’s permission settings for other users and groups. |
The Complete PR Permissions Matrix
This table maps every action in the pull request workflow to the specific permission required.
Action | Required Permission | Default Group | Notes |
|---|---|---|---|
View a pull request | Read | Readers, Contributors, Admins | Minimum permission to see PRs |
View the PR diff | Read | Readers, Contributors, Admins | Same as viewing code |
Create a pull request | Contribute + Contribute to pull requests | Contributors, Admins | Needs both: Contribute (to have pushed the branch) + Contribute to PRs (to create the PR itself) |
Add comments on a PR | Contribute to pull requests | Contributors, Admins | Inline comments, general comments, and replies |
Resolve / re-activate comments | Contribute to pull requests | Contributors, Admins | Any reviewer can resolve; authors can also resolve |
Vote (Approve / Reject / Wait) | Contribute to pull requests | Contributors, Admins | Voting permissions are the same as commenting |
Add or remove reviewers | Contribute to pull requests | Contributors, Admins | Anyone who can comment can also modify the reviewer list |
Set auto-complete | Contribute to pull requests | Contributors, Admins | Requires the user to also have Complete permission (Contribute) |
Complete (merge) a PR | Contribute to pull requests + Contribute | Contributors, Admins | Both permissions required. The user needs write access to the target branch. |
Complete a PR when policies fail | Bypass policies when completing PRs | Admins only (by default) | Override button appears only for users with this permission |
Push directly to a protected branch | Bypass policies when pushing | Admins only (by default) | Skips PR requirement entirely |
Configure branch policies | Edit policies | Admins only (by default) | Controls who can set required reviewers, build validation, etc. |
Delete a branch after merge | Contribute | Contributors, Admins | Controlled by Contribute permission on the branch |
Abandon a PR | Contribute to pull requests | Contributors, Admins | PR author or anyone with this permission can abandon |
Reactivate an abandoned PR | Contribute to pull requests | Contributors, Admins | Same as abandon |
How to Grant or Restrict Permissions
Grant Review Permissions to a User
If someone needs to review PRs but currently can’t (e.g., they’re in the Readers group), add them to Contributors or grant specific permissions:
Option A: Add to Contributors group (recommended for most cases)
Go to Project Settings → Permissions → Groups
Click Contributors
Click Members → Add
Search for the user and add them
This grants all standard PR permissions: create, comment, vote, and complete.
Option B: Grant specific repo-level permissions (for fine-grained control)
Go to Project Settings → Repos → Repositories → select the repo
Click Security
Search for the user or group
Set Contribute to pull requests to Allow
Use Option B when you want someone to review and comment on PRs without being able to push code. For example, a security engineer who reviews PRs but doesn’t contribute code to the repo.
Restrict Merge Permissions
To prevent specific users from completing (merging) PRs while still allowing them to review:
Go to Project Settings → Repos → Repositories → select the repo
Click Security
Find the user or custom group
Set Contribute to Deny (this blocks push and merge)
Keep Contribute to pull requests as Allow (they can still review and vote)
This creates a “reviewer only” role: the user can read code, comment, and vote, but cannot merge.
Grant Policy Bypass for Emergency Hotfixes
During incidents, you may need to merge a PR before all policies are satisfied (e.g., a failing test that’s unrelated to the fix). Rather than giving Project Admin rights, grant the specific bypass permission:
Go to Project Settings → Repos → Repositories → select the repo
Click Security
Find the user or create a dedicated “Hotfix” security group
Set Bypass policies when completing pull requests to Allow
Create a dedicated “Hotfix Approvers” group with this permission and add only senior engineers or team leads. This keeps bypass available for emergencies without granting full admin rights.
Restrict Direct Pushes to Protected Branches
To ensure all changes go through PRs (no direct pushes to main):
Go to Project Settings → Repos → Repositories → select the repo → Policies → select the branch
Under branch policies, there’s no explicit “require PR” toggle — instead, when you enable any branch policy (even just “Minimum number of reviewers” set to 1), Azure DevOps automatically blocks direct pushes and requires a PR
To further lock it down, go to Security on the repo, find the Contributors group, and verify Bypass policies when pushing is set to Not set or Deny
CODEOWNERS Equivalent in Azure DevOps: Automatically Included Reviewers
Azure DevOps doesn’t have a CODEOWNERS file like GitHub. Instead, it uses Automatically included reviewers in branch policies to achieve the same result — automatically adding specific reviewers when specific file paths are changed.
How It Works
When a PR is created that modifies files matching a path filter, Azure DevOps automatically adds the specified reviewers. These reviewers can be set as required (must approve before merge) or optional (notified but don’t block).
Setting Up Auto-Reviewers (CODEOWNERS Equivalent)
Go to Project Settings → Repos → Repositories → select your repo
Click Policies → select the target branch (e.g.,
main)Under Automatically included reviewers, click Add
Configure:
Reviewers: The person or group to auto-add
Path filter: Which file paths trigger this reviewer (e.g.,
/src/api/*,/infrastructure/*,.sql)Required: Whether this reviewer must approve (blocks merge if they don’t)
Allow requestors to approve their own changes: Whether the PR author counts if they’re the auto-included reviewer
Example: Replicating a CODEOWNERS File
A GitHub CODEOWNERS file like this:
Translates to these Azure DevOps “Automatically included reviewers” policies on the main branch:
Path Filter | Reviewer | Required? | Equivalent CODEOWNERS Line |
|---|---|---|---|
| [Backend Team] group | Yes |
|
| [Frontend Team] group | Yes |
|
| [DevOps Team] group | Yes |
|
| [DBA Team] group | Yes |
|
| [Tech Writers] group | No (optional) |
|
Key Differences from GitHub CODEOWNERS
Feature | GitHub CODEOWNERS | Azure DevOps Auto-Reviewers |
|---|---|---|
Configuration location |
| Branch policy settings (UI or REST API) |
Who can modify | Anyone with write access to the file | Only users with Edit policies permission |
Granularity | Per-file path patterns | Per-file path patterns (same) |
Required vs optional | All entries are required by default | Configurable per entry — required or optional |
Multiple owners per path | Supported (last match wins) | Supported (all matching reviewers are added) |
Branch-specific | Single file applies to all protected branches | Configured per branch — can have different reviewers per branch |
Self-approval | Not allowed by default | Configurable per policy — “Allow requestors to approve their own changes” |
The Azure DevOps approach is more flexible (per-branch configuration, required vs optional per entry, self-approval toggle) but less portable (lives in settings, not in a repo file). Teams migrating from GitHub need to manually recreate their CODEOWNERS rules as auto-reviewer policies.
Permission Inheritance and Override Rules
Azure DevOps permissions follow an inheritance chain with specific override rules that are critical to understand when troubleshooting access issues.
The Inheritance Chain
Permissions set at a higher level flow down to lower levels unless explicitly overridden. A user who is a Contributor at the project level is a Contributor on all repositories in that project, unless a specific repository overrides their permissions.
Override Rules
Rule | Example |
|---|---|
Explicit Deny always wins | If a user’s group has Contribute = Allow, but the user is individually set to Contribute = Deny, the Deny wins |
Explicit settings override inherited | A repo-level Allow overrides a project-level Not set |
Not set ≠ Deny | “Not set” means the permission is inherited from the parent. “Deny” explicitly blocks regardless of inheritance. |
User-level overrides group-level | If a user belongs to Group A (Allow) and Group B (Deny), the Deny wins — Deny always takes priority |
Most restrictive wins across groups | When a user is in multiple groups with conflicting permissions, Deny from any group overrides Allow from all others |
The “Deny Always Wins” Rule
This is the most common source of confusion. If a user belongs to two security groups:
Contributors: Contribute to pull requests = Allow
External Contractors: Contribute to pull requests = Deny
The result is Deny. The user cannot create or comment on PRs, even though they’re in the Contributors group. This is by design — Azure DevOps uses a “least privilege” model where any explicit Deny overrides all Allows.
To fix: Don’t use Deny on broad groups. Instead, use “Not set” (which inherits from the parent) and only grant Allow where needed. Reserve Deny for cases where you explicitly need to block a specific user or group from a specific action.
Troubleshooting Common Permission Errors
“TF402455: Pushes to this branch are not permitted”
What it means: You’re trying to push directly to a branch that has branch policies enabled. Azure DevOps blocks direct pushes to policy-protected branches — all changes must go through a pull request.
Fix: Create a feature branch, push your changes there, and create a PR targeting the protected branch. This is the expected behavior when branch policies are configured correctly.
If you’re an admin and need to push directly (emergency): You need the “Bypass policies when pushing” permission. Check Project Settings → Repos → Security.
“You do not have permission to create a pull request”
Possible causes:
Missing “Contribute to pull requests” permission. Go to Project Settings → Repos → select repo → Security → find the user → verify “Contribute to pull requests” is Allow, not Deny or Not set.
Stakeholder access level. Users with Stakeholder access can’t interact with Repos in private projects. Upgrade to Basic.
Repo-level override. The user may be a Contributor at the project level but have an explicit Deny at the repo level. Check repo-level security.
“You need permission to complete this pull request”
Possible causes:
Missing “Contribute” permission on the target branch. Completing a PR requires write access to the target branch. Check the branch-level permissions.
Bypass required but not granted. If policies haven’t been met and the user is trying to override, they need “Bypass policies when completing pull requests.”
Deny inheritance. The user may be in a group with an explicit Deny on Contribute. Check all group memberships.
“Cannot vote on this pull request”
Possible causes:
Missing “Contribute to pull requests” permission. Voting (approve/reject) requires this permission.
The PR is in draft state. Draft PRs don’t allow voting — the author must publish first.
The user is the PR author with self-approval disabled. If the branch policy “Allow requestors to approve their own changes” is unchecked, the PR author can’t approve their own PR.
“I can review but can’t merge: Complete button is grayed out”
The Complete button requires both “Contribute to pull requests” AND “Contribute” permissions. The user has review permissions but lacks write access to the target branch. Grant “Contribute” on the repository or target branch.
If the button is grayed out but says “Set auto-complete,” it means policies haven’t been met yet. The user has permission, but the PR isn’t ready to merge.
“Reviewer was auto-added but I don’t know why”
An “Automatically included reviewers” policy matched the file paths changed in the PR. To find which policy triggered:
Go to Project Settings → Repos → select repo → Policies → select the target branch
Check Automatically included reviewers, look for path filters that match the files in the PR
The policy name shows which reviewer/group is configured
“I have Bypass permission but I don’t see the Override button”
The “Bypass policies when completing pull requests” override only appears when policies are actually failing. If all policies pass, the standard Complete button is shown. The override button appears only when you need to bypass something.
Also verify: go to Project Settings → Repos → select repo → Security → find your user → confirm “Bypass policies when completing pull requests” is explicitly set to Allow (not inherited, not Not set).
Best Practices for PR Permission Management
Use groups, not individual assignments. Assign permissions to security groups, then add users to groups. This makes it manageable at scale — when a new developer joins, add them to “Contributors” instead of setting 15 individual permissions.
Create a “Senior Reviewer” group for bypass permissions. Instead of granting bypass to Project Admins (who have all permissions), create a dedicated group with only the bypass permission. Add team leads and senior engineers. This follows the principle of least privilege.
Don’t use Deny unless you mean it. “Not set” inherits from the parent level. “Deny” explicitly blocks and overrides all Allow settings from other groups. Most access issues are caused by an accidental Deny somewhere in the inheritance chain. Use “Not set” for permissions you want inherited.
Audit permissions quarterly. As teams change and people move between projects, permissions accumulate. Review who has bypass permissions, who has edit policies permissions, and whether any individual overrides exist that shouldn’t.
Use auto-included reviewers instead of relying on PR authors to pick reviewers. This ensures the right people review the right code every time, regardless of whether the PR author remembers to add them.
For a comprehensive guide to branch policies, required reviewers, and review workflows in Azure DevOps, see the complete code review guide.
How Permissions Interact with AI Code Review
AI code review tools like CodeAnt AI operate using service accounts or personal access tokens (PATs) that need specific permissions to function. The AI tool needs:
Read on repositories to access the PR diff and codebase
Contribute to pull requests to post inline comments and vote on PRs
Status check posting to report pass/fail quality gate results (configured via service hooks, not repo permissions)
The AI tool does not need Contribute (write) permission to branches, it doesn’t push code, only reads and comments. This means the AI reviewer operates with minimal permissions, following the principle of least privilege.
When CodeAnt AI is configured as a required status check via branch policies, the quality gate blocks merges when critical issues are found, regardless of whether human reviewers have approved. This separation of concerns means human reviewers handle architecture and design decisions while the AI handles mechanical quality and security enforcement with its own independent status.
CodeAnt AI, used by Fortune 500 development teams on Azure DevOps, works on both cloud Azure DevOps and self-hosted Azure DevOps Server. For setup instructions, see the cloud setup guide or self-hosted setup guide.
Permissions Define Your Code Review Governance
Azure DevOps pull request workflows depend heavily on permission design.
When permissions are configured correctly:
Developers can create and review PRs
Designated reviewers can approve changes
Only trusted users can merge into protected branches
Branch policies enforce quality and security standards
But when permissions are misconfigured, teams run into constant friction:
Developers unable to create PRs
Reviewers unable to approve changes
Contributors accidentally merging to protected branches
Administrators bypassing policies unintentionally
The key is understanding that Azure DevOps permissions operate across access levels, security groups, and repository settings simultaneously. Even a single conflicting rule, especially an explicit Deny, can block actions across the entire workflow.
Once the permission model is clear, teams can create predictable review workflows where responsibilities are clearly separated: developers contribute code, reviewers evaluate changes, and maintainers control merges.
Modern teams are also adding AI-assisted code review to this workflow.
Tools like CodeAnt AI integrate directly with Azure DevOps pull requests, analyzing the PR diff, posting inline review comments, and enforcing automated quality gates before a merge is allowed. This means permissions still govern who can merge, while AI tools ensure what gets merged meets quality and security standards.
When permissions, policies, and automated review work together, pull requests become more than a merge step, they become a reliable quality control system for your codebase.
FAQs
What’s the difference between “Contribute” and “Contribute to pull requests”?
Why does Deny override Allow in Azure DevOps permissions?
What does “Bypass policies when completing pull requests” do?
What permissions do I need to review a pull request in Azure DevOps?
Who can approve a pull request in Azure DevOps?
Table of Contents
Start Your 14-Day Free Trial
AI code reviews, security, and quality trusted by modern engineering teams. No credit card required!
Share blog:











