AI Code Review

Feb 27, 2026

Code Review Permissions in Azure DevOps: Who Can Review, Approve, and Merge Pull Requests

Amartya | CodeAnt AI Code Review Platform
Sonali Sood

Founding GTM, CodeAnt AI

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:

  1. Access levels (Stakeholder, Basic, Visual Studio Enterprise)

  2. Security groups (Readers, Contributors, Administrators)

  3. 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)

  1. Go to Project SettingsPermissionsGroups

  2. Click Contributors

  3. Click MembersAdd

  4. 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)

  1. Go to Project SettingsReposRepositories → select the repo

  2. Click Security

  3. Search for the user or group

  4. 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:

  1. Go to Project SettingsReposRepositories → select the repo

  2. Click Security

  3. Find the user or custom group

  4. Set Contribute to Deny (this blocks push and merge)

  5. 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:

  1. Go to Project SettingsReposRepositories → select the repo

  2. Click Security

  3. Find the user or create a dedicated “Hotfix” security group

  4. 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):

  1. Go to Project SettingsReposRepositories → select the repo → Policies → select the branch

  2. 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

  3. 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)

  1. Go to Project SettingsReposRepositories → select your repo

  2. Click Policies → select the target branch (e.g., main)

  3. Under Automatically included reviewers, click Add

  4. 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

/src/api/*

[Backend Team] group

Yes

/src/api/ @backend-team

/src/frontend/*

[Frontend Team] group

Yes

/src/frontend/ @frontend-team

/infrastructure/*

[DevOps Team] group

Yes

/infrastructure/ @devops-team

*.sql

[DBA Team] group

Yes

*.sql @dba-team

/docs/*

[Tech Writers] group

No (optional)

/docs/ @tech-writers

Key Differences from GitHub CODEOWNERS

Feature

GitHub CODEOWNERS

Azure DevOps Auto-Reviewers

Configuration location

CODEOWNERS file in repo root

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:

  1. 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.

  2. Stakeholder access level. Users with Stakeholder access can’t interact with Repos in private projects. Upgrade to Basic.

  3. 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:

  1. Missing “Contribute” permission on the target branch. Completing a PR requires write access to the target branch. Check the branch-level permissions.

  2. 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.”

  3. 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:

  1. Missing “Contribute to pull requests” permission. Voting (approve/reject) requires this permission.

  2. The PR is in draft state. Draft PRs don’t allow voting — the author must publish first.

  3. 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:

  1. Go to Project SettingsRepos → select repo → Policies → select the target branch

  2. Check Automatically included reviewers, look for path filters that match the files in the PR

  3. 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:

  1. Access levels (Stakeholder, Basic, Visual Studio Enterprise)

  2. Security groups (Readers, Contributors, Administrators)

  3. 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)

  1. Go to Project SettingsPermissionsGroups

  2. Click Contributors

  3. Click MembersAdd

  4. 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)

  1. Go to Project SettingsReposRepositories → select the repo

  2. Click Security

  3. Search for the user or group

  4. 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:

  1. Go to Project SettingsReposRepositories → select the repo

  2. Click Security

  3. Find the user or custom group

  4. Set Contribute to Deny (this blocks push and merge)

  5. 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:

  1. Go to Project SettingsReposRepositories → select the repo

  2. Click Security

  3. Find the user or create a dedicated “Hotfix” security group

  4. 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):

  1. Go to Project SettingsReposRepositories → select the repo → Policies → select the branch

  2. 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

  3. 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)

  1. Go to Project SettingsReposRepositories → select your repo

  2. Click Policies → select the target branch (e.g., main)

  3. Under Automatically included reviewers, click Add

  4. 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

/src/api/*

[Backend Team] group

Yes

/src/api/ @backend-team

/src/frontend/*

[Frontend Team] group

Yes

/src/frontend/ @frontend-team

/infrastructure/*

[DevOps Team] group

Yes

/infrastructure/ @devops-team

*.sql

[DBA Team] group

Yes

*.sql @dba-team

/docs/*

[Tech Writers] group

No (optional)

/docs/ @tech-writers

Key Differences from GitHub CODEOWNERS

Feature

GitHub CODEOWNERS

Azure DevOps Auto-Reviewers

Configuration location

CODEOWNERS file in repo root

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:

  1. 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.

  2. Stakeholder access level. Users with Stakeholder access can’t interact with Repos in private projects. Upgrade to Basic.

  3. 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:

  1. Missing “Contribute” permission on the target branch. Completing a PR requires write access to the target branch. Check the branch-level permissions.

  2. 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.”

  3. 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:

  1. Missing “Contribute to pull requests” permission. Voting (approve/reject) requires this permission.

  2. The PR is in draft state. Draft PRs don’t allow voting — the author must publish first.

  3. 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:

  1. Go to Project SettingsRepos → select repo → Policies → select the target branch

  2. Check Automatically included reviewers, look for path filters that match the files in the PR

  3. 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: