Pull Requests: Policies, Protections & Merge Rules
Design pull request workflows with branch policies in Azure DevOps and branch protection rules in GitHub. Configure required reviewers, status checks, merge strategies, and automated enforcement.
Why Pull Request Policies Matter
Think of airport security.
Before you board a plane, you go through a checkpoint. Your bag is scanned (automated check). Your ID is verified (reviewer approval). If anything looks suspicious, youβre pulled aside for a closer look (required status checks). You canβt skip the line β everyone goes through the same process.
Pull request policies are the security checkpoint for your code. Every change must pass automated tests (bag scan), get reviewed by a team member (ID check), and meet quality standards before it can merge into the main branch. No exceptions, no bypassing β the rules enforce themselves.
Azure DevOps Branch Policies
Branch policies in Azure DevOps are configured per branch (typically main and develop). They are found in Repos > Branches > Branch Policies.
| Policy | What It Enforces | Common Configuration |
|---|---|---|
| Require a minimum number of reviewers | At least N approvals before merge | 2 reviewers; requestor cannot approve their own; reset votes on new pushes |
| Check for linked work items | PR must be linked to a work item | Required β ensures traceability |
| Check for comment resolution | All PR comments must be resolved before merge | Required β prevents ignored feedback |
| Limit merge types | Only allow specific merge strategies | Allow squash merge only (most common) |
| Build validation | A specified build pipeline must succeed | CI pipeline must pass; set to required (blocking) |
| Status checks | External services must report success | SonarQube quality gate, security scanner |
| Automatically included reviewers | Specific people or teams auto-added as reviewers | Security team on infrastructure changes, DBA on schema changes |
| Reset code reviewer votes | Previous approvals are reset when new commits are pushed | Enabled β forces re-review of new changes |
Key Details for the Exam
- Bypass permissions: Project Administrators can bypass branch policies (with audit logging). You can grant βExempt from policy enforcementβ to specific users or groups β but this should be rare and audited.
- Build validation timing: You can trigger the validation build βimmediately when updatedβ or βwhen the merge is attempted.β Immediate is more common.
- Path-based policies: You can add automatically included reviewers based on file path (e.g., add the security team when
*.bicepfiles change).
GitHub Branch Protection Rules
GitHub offers two mechanisms: legacy branch protection rules and the newer repository rulesets. The exam covers both.
Legacy Branch Protection Rules
Configured in Settings > Branches > Branch protection rules.
| Rule | What It Enforces |
|---|---|
| Require a pull request before merging | No direct pushes to the branch |
| Required approving reviews | Minimum number of approvals (1-6) |
| Dismiss stale pull request approvals | Reset approvals when new commits are pushed (equivalent to Azure DevOps reset votes) |
| Require review from code owners | CODEOWNERS file designates who must review which paths |
| Require status checks to pass | CI/CD checks must succeed before merge |
| Require branches to be up to date | Branch must be rebased on latest target before merge |
| Require signed commits | All commits must be GPG-signed |
| Require linear history | Prevents merge commits (forces squash or rebase) |
| Include administrators | Even admins must follow the rules |
| Restrict who can push | Only specific people/teams can push to the branch |
| Allow force pushes | Generally disabled β force push rewrites history |
| Allow deletions | Prevent branch deletion |
GitHub Repository Rulesets (Newer)
Rulesets are the newer, more powerful replacement for branch protection rules. Key differences:
- Apply to multiple branches using patterns (e.g.,
release/*,main) - Layered rules β multiple rulesets can apply to the same branch; most restrictive wins
- Organisation-level β apply rulesets across all repositories in an organisation
- Bypass actors β explicitly define who can bypass (deploy bots, release managers)
- Evaluate mode β test a ruleset without enforcing it (see what would be blocked)
Azure DevOps vs GitHub: Protection Comparison
| Capability | Azure DevOps Branch Policies | GitHub Branch Protection / Rulesets |
|---|---|---|
| Minimum reviewers | Configurable count; requestor self-approval optional | 1-6 required approvals; code owner reviews optional |
| Reset votes on new push | Reset code reviewer votes setting | Dismiss stale pull request approvals |
| Build validation | Specify build pipeline that must succeed | Required status checks (any CI system) |
| Path-based reviewers | Automatically included reviewers by file path | CODEOWNERS file maps paths to reviewers |
| Comment resolution | Require all comments resolved before merge | No built-in equivalent (convention-based) |
| Work item linking | Require linked work items for traceability | No built-in equivalent (use PR templates) |
| Merge type restriction | Limit to specific merge types per branch | Require linear history (forces squash or rebase) |
| Bypass mechanism | Exempt from policy enforcement permission | Bypass actors in rulesets; include administrators option |
| Signed commits | Not supported natively | Require signed commits (GPG) |
| Organisation-wide | Project-level only | Rulesets support organisation-level enforcement |
| Audit trail | Full audit log of policy changes and bypasses | Audit log for Enterprise; ruleset change history |
The CODEOWNERS File
The CODEOWNERS file (placed in the root, docs/, or .github/ directory) maps file paths to required reviewers.
# Default owner for everything
* @org/platform-team
# Frontend code owned by frontend team
/src/components/** @org/frontend-team
# Infrastructure as code requires security review
/infra/** @org/security-team @jordan-rivera
# Database migrations require DBA approval
/db/migrations/** @org/dba-team
# API contracts require architect review
/api/openapi.yaml @kai-tanaka
When βRequire review from code ownersβ is enabled, PRs that modify matched paths must be approved by the designated owner β even if other reviewers have already approved.
ποΈ Amiraβs CODEOWNERS Strategy
Dr. Amira sets up CODEOWNERS for her government clientβs project:
*β Farah and Amira (default reviewers for everything)/infra/**β Major Collinsβ approved infrastructure team/security/**β Amira herself (security configurations require DevSecOps review)/docs/compliance/**β Marcus (audit) β all compliance documentation changes need his sign-off
This ensures the right eyes see the right code β automatically, without relying on developers to remember to tag reviewers.
Merge Strategies
The exam expects you to know three merge strategies, when to use each, and how they affect Git history.
Merge Commit (No Fast-Forward)
Creates a merge commit that ties two branches together. Preserves full branch history.
main ββAβββBβββββββMββ (M is merge commit)
/
feature ββCβββDβββEββ (branch history preserved)
Use when: You want to see the complete history of a feature branch, including all individual commits.
Squash Merge
Combines all feature branch commits into a single new commit on main. The feature branch history is discarded.
main ββAβββBβββSββ (S contains all changes from C+D+E)
feature ββCβββDβββE (branch deleted after merge)
Use when: You want a clean, linear main branch history. Each merge is one commit with one purpose. Most teams prefer this for feature branches.
Rebase and Merge
Replays feature branch commits on top of main, creating new commits. Results in a linear history without merge commits.
main ββAβββBβββC'βββD'βββE'ββ (C', D', E' are replayed commits)
feature ββCβββDβββE (original commits, branch deleted)
Use when: You want linear history but also want to preserve individual commits (not squash them).
Exam Tip: Merge Strategy Selection
The exam often asks which merge strategy to recommend. The decision tree:
- Need audit trail of individual commits? Use merge commit or rebase merge.
- Need clean, linear history where each merge is one logical change? Use squash merge.
- Need to preserve branch topology for debugging (see where branches diverged)? Use merge commit.
- Team uses trunk-based development with tiny changes? Squash merge or rebase β both keep history clean.
- Team has compliance requirements needing granular commit history? Merge commit preserves everything.
Most AZ-400 scenarios favour squash merge for feature branches because it keeps main history clean and each merged commit represents a complete, reviewed feature.
π’ Nadiaβs Merge Policy
Nadia configures Azure DevOps to only allow squash merge on the main branch. Every merged PR becomes one commit with the PR title as the commit message. The full branch history is preserved in the PR itself (auditors can drill into the PR to see every individual commit).
For the release/* branches, she allows merge commits β she wants to see exactly which bug fixes were backported from develop during stabilisation.
Putting It All Together: PR Workflow Design
ποΈ Amiraβs High-Security PR Workflow
For Major Collinsβ defence project, Amira designs this PR workflow:
- Developer creates a feature branch and opens a PR
- Automated checks run: CI build, unit tests, SAST scan, dependency vulnerability scan, licence compliance check
- CODEOWNERS auto-assigns reviewers based on changed files
- Two approvals required β one from the development team, one from the security team
- All comments must be resolved before merge
- PR must be linked to an approved work item (traceability)
- Reset votes on any new push β forces re-review
- Squash merge only β clean audit trail on main
- Post-merge: Work item auto-transitions to βDoneβ
Every step is enforced by branch policies β no human judgement required, no steps can be skipped.
Amira's client requires that security team members review any PR that modifies infrastructure code, even if other developers have already approved it. Which feature should Amira configure?
Kai's team wants a clean, linear Git history on main where each commit represents one complete feature. They also want to preserve the detailed commit history for audit purposes. Which merge strategy should Kai configure?
Nadia wants to apply consistent branch protection rules across all 47 repositories in her Azure DevOps organisation's GitHub Enterprise account. What should she use?
π¬ Video coming soon
Pull Request Policies Deep Dive
Next up: Repository Management: LFS, Permissions & Recovery