3.2 Pull Request Workflows & Merge Strategies
Key Takeaways
- Pull Requests (PRs) act as the formal governance boundary and quality gate between developer work branches and protected target branches.
- Squash merging condenses all feature branch commits into a single commit on the target branch, producing a clean, strictly linear Git history ideal for Trunk-Based Development.
- Standard merge commits (git merge --no-ff) preserve every individual commit and create a two-parent merge node, maintaining full historical context and easy single-command rollback.
- Rebase and merge rewrites commit SHAs to replay individual feature commits sequentially onto the target branch tip, creating a linear history while preserving granular commit counts.
- Semi-linear merge (native to Azure Repos) rebases the source branch onto the target branch tip before creating a merge commit, ensuring linear progression while preserving merge node boundaries.
3.2 Pull Request Workflows & Merge Strategies
Quick Summary: Pull requests (PRs) serve as the authoritative gate between developer work branches and protected shared branches. In Exam AZ-400, understanding the commit topology and operational trade-offs of the four primary merge strategies—Merge Commit (
--no-ff), Squash Merge (--squash), Rebase and Merge (rebase), and Semi-Linear Merge—is essential for designing clean Git histories, ensuring traceability, and executing rapid rollbacks.
The Pull Request (PR) Lifecycle in Enterprise DevOps
A Pull Request (referred to as a Merge Request in some platforms) is not a native Git command; it is a platform-level collaboration workflow provided by Azure Repos, GitHub, and GitLab. It acts as the operational checkpoint where human code review, automated verification pipelines, and regulatory compliance intersect.
Pull Request Governance Lifecycle:
[Developer Workspace]
│ (git push)
▼
[Draft PR Created] ──────► [Automated CI Validation Triggered] (Fast feedback, non-blocking)
│
▼ (Publish / Mark Ready)
[Active Review State] ────► [Reviewers Assigned / CodeOwners] (Human inspection, inline suggestions)
│
▼
[Conversation Resolution] ─► [Required Reviewer Approvals] (Min 2 reviewers, no self-approval)
│
▼
[Quality Gate Passed] ────► [Enforced Merge Strategy] ───► [Merged to Protected Main]
1. Draft Pull Requests
Both GitHub and Azure Repos provide Draft Pull Requests (also called Set to Draft in Azure DevOps):
- Purpose: Allows developers to publish an early, incomplete work-in-progress branch to the central repository.
- Benefits:
- Triggers automated CI validation pipelines early, ensuring unit tests and security scans run before code completion.
- Allows developers to share code diffs with senior architects for structural feedback.
- Prevents accidental merging: the platform explicitly blocks completion while in Draft state.
- Avoids notification spam: assigned reviewers are not prompted for formal review until the author clicks Mark as Ready for Review (GitHub) or Publish (Azure Repos).
2. Code Inspection & Discussion Threads
Modern PR reviews involve inline annotations and multi-line comments. Reviewers can suggest precise replacements using markdown suggestion syntax:
```suggestion
var client = _httpClientFactory.CreateClient("PaymentGateway");
```
In Azure Repos, review comments exist inside stateful discussion threads. A thread can have statuses such as Active, Pending, Resolved, Won't Fix, or Closed. Branch policies can enforce that a PR cannot be completed until all comment threads are explicitly marked as Resolved.
3. Reviewer Voting States (Azure Repos)
Azure Repos features granular reviewer voting options that govern completion eligibility:
- Approve (green check): Reviewer signs off on the PR.
- Approve with suggestions: Reviewer approves the PR, but leaves optional recommendations for the author's discretion. Does not block merge.
- Wait for author: Reviewer found issues and is waiting for the author to push new commits or answer questions. Blocks merge if the reviewer is required.
- Reject: Reviewer fundamentally rejects the proposed changes. Completely blocks PR completion until changed.
Merge Strategies & Git History Topologies
When a pull request is approved and quality gates are satisfied, the source branch must be incorporated into the target branch (main). How Git executes this merge dictates the readability, auditability, and rollback characteristics of the repository history.
Exam AZ-400 heavily tests the differences among the four merge strategies.
Commit Graph Topology Comparison:
1. Merge Commit (--no-ff) 2. Squash Merge 3. Rebase and Merge 4. Semi-Linear Merge
main: o───o───────M (2 parents) main: o───o────────S (1 parent) main: o───o───A'──B' (Linear) main: o───o───────M (Linear Base)
\ / (A & B squashed) (SHAs rewritten) \ /
feat: A───B feat: A'──B' (Rebased first)
1. Merge Commit (git merge --no-ff / Standard 3-Way Merge)
A standard merge commit preserves the complete, unaltered history of the feature branch. Git performs a 3-way merge between the target branch tip, the feature branch tip, and their common ancestor, generating a new merge commit object that has two parent commits (parent 1: main, parent 2: feature).
Git Mechanics & CLI Equivalent
git checkout main
git pull origin main
git merge --no-ff feature/user-profile -m "Merge PR #204: feature/user-profile"
git push origin main
Operational Characteristics
- Topology: Non-linear graph showing distinct branches diverging and converging ("railroad tracks").
- Commit Preservation: Preserves every single commit created by the developer on the feature branch, including intermediate commits ("wip", "fixed typo", "formatting").
- Audit & Compliance: Complete, unvarnished chronological truth. Every commit retains its original SHA, author timestamp, and committer timestamp.
- Rollback Behavior: Reverting the entire PR is clean and instantaneous using
git revert -m 1 <merge-commit-sha>. The-m 1flag designates parent 1 (main) as the mainline, cleanly reversing all changes introduced by the second parent. - Drawback: A busy repository with dozens of merges per day produces a tangled, difficult-to-navigate Git graph. Running
git bisectto locate regressions can land on broken intermediate commits inside the feature branch.
2. Squash Merge (git merge --squash)
Squash merging takes all commits on the source branch, combines their cumulative diff into a single unified changeset against the target branch, and creates one new commit on the target branch. The new commit has only one parent (the previous tip of main).
Git Mechanics & CLI Equivalent
git checkout main
git pull origin main
git merge --squash feature/user-profile
git commit -m "feat(profile): implement user profile page and avatar upload (#204)"
git push origin main
Operational Characteristics
- Topology: Strictly linear commit history. The Git log on
mainreads like a clean, high-level changelog where every commit maps 1:1 to an approved PR or Azure Boards User Story. - Commit Preservation: Granular commits on the feature branch are discarded from the
mainhistory. The original commit SHAs cease to exist on the mainline. - Audit & Compliance: The PR description and title become the commit message. Enterprise teams format this message with traceability metadata (e.g.,
AB#1284 feat: add multi-factor auth validation). - Rollback Behavior: Very straightforward. Because the entire feature is encapsulated in a single standard commit, running
git revert <commit-sha>undoes the feature without needing the-mmainline flag. - Trunk-Based Standard: Squash merging is the universal standard for Trunk-Based Development. It eliminates developer commit noise and guarantees that every commit on
mainrepresents a complete, compilable, and tested unit of work. - Drawback: Fine-grained debugging across intermediate commits is lost once the feature branch is deleted. Continued development on the same feature branch is problematic because Git cannot easily compute future merge bases without re-rebasing.
3. Rebase and Merge (git rebase + Fast-Forward)
Rebase and merge takes each commit from the source branch and replays them one by one onto the tip of the target branch, updating the target branch using a fast-forward merge. No merge commit is created.
Git Mechanics & CLI Equivalent
git checkout feature/user-profile
git pull origin main --rebase
# Resolve any conflicts commit by commit
git checkout main
git merge --ff-only feature/user-profile
git push origin main
Operational Characteristics
- Topology: Strictly linear commit history without merge commit nodes.
- Commit Preservation: Preserves all individual commits from the feature branch, but rewrites every commit SHA because their parent pointers and timestamps are recalculated.
- Audit & Traceability Caveat: Because commit SHAs are rewritten, any external links (e.g., work item comments referencing original commit hashes) will point to stale, orphaned commits.
- Drawback: If an author made 15 messy commits on their feature branch, all 15 messy commits appear sequentially on
main. Furthermore, if an intermediate commit broke the build before being fixed three commits later,git bisectcan land on the broken commit, disrupting automated root-cause analysis.
4. Semi-Linear Merge (Azure Repos Native / Rebase with Merge Commit)
Semi-linear merge is a specialized hybrid merge strategy natively supported by Azure Repos. It requires that the feature branch is first rebased onto the exact tip of main (ensuring the branch has zero divergence from main), and then merges the branch using a non-fast-forward merge commit (--no-ff).
Semi-Linear Merge Detail:
Step 1 (Ensure branch is rebased onto tip of main):
main: o───o───o (Tip)
\
feat (rebased): A'──B'
Step 2 (Create non-fast-forward merge commit M):
main: o───o───o───────────M (Parent 1 is tip, Parent 2 is B')
\ /
feat: A'───────B'
Operational Characteristics
- Topology: The mainline progression is strictly linear: every merge commit has
parent 1as the immediate predecessor onmain. However, each PR's commits remain neatly grouped inside an explicit merge commit container. - The Architectural Benefit: It combines the visual encapsulation and easy revertibility of a merge commit with the clean, non-interleaving guarantees of a linear history.
- Enforcement: If someone else merges a PR to
mainwhile your PR is being approved, Azure Repos detects that your PR branch is no longer based on the tip of main and blocks the merge. You must click Rebase in the PR UI before the platform will allow completion.
Comparison Matrix: The Four Merge Strategies
| Feature / Metric | 1. Merge Commit (--no-ff) | 2. Squash Merge (--squash) | 3. Rebase and Merge (rebase) | 4. Semi-Linear Merge |
|---|---|---|---|---|
| Mainline Graph | Tangled / Non-linear | Strictly Linear | Strictly Linear | Semi-Linear (Linear backbone) |
| Merge Commit Created? | Yes (Two parents) | No (One parent standard) | No (Fast-forward) | Yes (Two parents, linear base) |
| Preserves Feature Commits? | Yes (Original SHAs) | No (Combined into 1) | Yes (Rewritten SHAs) | Yes (Rewritten SHAs) |
| Rewrites Commit SHAs? | No | Yes (Brand new commit) | Yes | Yes |
| Single-Command Revert | git revert -m 1 <sha> | git revert <sha> | Difficult (must revert N commits) | git revert -m 1 <sha> |
| Git Bisect Quality | Low (can hit broken WIPs) | Exceptional (1 PR = 1 commit) | Low to Medium | High |
| Azure Repos Support | Native | Native | Native | Native (Exclusive setting) |
| GitHub Support | "Create a merge commit" | "Squash and merge" | "Rebase and merge" | Requires custom ruleset / action |
| Best For | Full audit of branch history | Trunk-Based / Clean history | Linear individual commit logs | Enterprise audit + linear history |
Branch Protection: GitHub vs. Azure Repos
To prevent developers from pushing code directly to main or executing non-compliant merges, organizations enforce Branch Protection Rules (GitHub) and Branch Policies (Azure Repos).
Platform Terminology Mapping:
Azure Repos Policy Setting GitHub Protection Equivalent Setting
--------------------------------------------------------------------------------------
Limit merge types allowed (e.g. Squash only) ---> Allow squash merging only
Require a minimum number of reviewers ---> Require pull request reviews before merging
Reset reviewer votes on new changes ---> Dismiss stale pull request approvals when new commits are pushed
Check for linked work items ---> Requires GitHub Apps / Actions (e.g. Azure Boards app)
Check for comment resolution ---> Require conversation resolution before merging
Build validation (Required pipeline) ---> Require status checks to pass before merging (Strict mode)
Automatically included reviewers (Path-based) --> CODEOWNERS file + Require review from Code Owners
Realistic Exam Scenarios & Anti-Patterns
Scenario 1: Clean Linear History in Trunk-Based Development
- Exam Scenario: A development lead wants to implement Trunk-Based Development in Azure Repos. Developers frequently make small, messy commits while testing ("wip", "fixed linting error"). The lead requires that when changes merge into
main, the commit history onmainmust contain exactly one commit per pull request, formatted with the work item ID, and thatmainretains a strictly linear history. - AZ-400 Correct Choice: Configure Azure Repos branch policies on
mainto Limit merge types allowed, selecting Squash merge only.
Scenario 2: Regulated Audit with Single-Command Reversion
- Exam Scenario: A banking application hosted in Azure DevOps is subject to strict regulatory auditing. Auditors require that every feature introduced to
maincan be traced as a distinct merge operation and must be capable of being reverted with a single command if security anomalies occur. However, the release engineering team refuses to accept non-linear, interleaved branch histories. - AZ-400 Correct Choice: Configure the branch policy on
mainto enforce Semi-linear merge (Rebase with merge commit). This ensures all branches are rebased onto the tip ofmainbefore generating a single two-parent merge commit.
A DevOps engineer is configuring branch policies for a mission-critical repository in Azure Repos. The development team follows Trunk-Based Development and wants to ensure that the main branch history remains strictly linear. Additionally, each completed pull request must appear as exactly one comprehensive commit on the main branch, discarding all intermediate 'work-in-progress' developer commits. Which merge strategy must be enforced in the branch policy?
When a developer executes a 'git rebase' on a feature branch against the latest main branch, what fundamental change occurs to the commits on that feature branch, and why is this problematic if the branch is shared with other developers?
An enterprise development team in Azure Repos requires that the main branch maintain a strictly linear progression without interleaved branch curves, while also demanding that each merged pull request retain an explicit merge commit node so the entire feature can be reverted with a single command ('git revert -m 1'). Which merge type should the team configure in their branch policy?