Git, CI/CD & GitOpsXXX · Pull Requests and Merge RequestsLifecycle
PR lifecycle and merge strategies — squash, merge commit, and rebase
What you'll learn
- Trace the PR lifecycle from draft through review to merge
- Explain what each merge strategy — squash, merge commit, rebase — produces on the trunk
- Identify the trade-off between readable history and atomic history
- Choose the right merge strategy for an infrastructure repository
Prerequisites
Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x
A PR ends when merged or closed. The merge strategy determines the trunk’s shape. Squash, merge commit, rebase — three strategies, three histories, three audit consequences.
The PR lifecycle
A PR moves through six states. Draft — change being prepared. Open — change ready. Changes requested — reviewer asked for revisions. Approved — required approvals met. Merged — merge event on base ref. Closed — withdrawn or rejected.
stateDiagram-v2
[*] --> Draft
Draft --> Open: ready for review
Open --> ChangesRequested: reviewer asks for revisions
ChangesRequested --> Open: author pushes fix
Open --> Approved: required approvals met
Approved --> Merged: merge button pressed
Open --> Closed: withdrawn or rejected
Merged --> [*]
Closed --> [*]
The three merge strategies
gh pr merge 123 --squash --subject "feat(login): v2 login path" --body "Closes #456"
gh pr merge 123 --merge
gh pr merge 123 --rebase
Squash collapses the branch into one commit on the base ref. Merge commit keeps the head’s commits and adds a merge commit with two parents. Rebase replays the head commits onto the base ref; no merge commit.
flowchart LR
subgraph squash["squash"]
M1["main"] --> S["single commit on main"]
S --> S1["tip"]
F1["feature: a,b,c"] -. "collapsed" .-> S
end
subgraph merge["merge commit"]
M2["main"] --> N1["main tip"]
N1 --> M["merge commit"]
F2["feature: a,b,c"] --> M
M --> M3["new main tip"]
end
subgraph rebase["rebase"]
M4["main tip"] --> R1["a'"]
R1 --> R2["b'"]
R2 --> R3["c'"]
R3 --> R4["new main tip"]
F3["feature: a,b,c"] -. "replayed" .-> R4
end
The trade-off
The trade-off is between readable history and atomic history. Squash produces a trunk where each commit is one atomic change — easy to revert, easy to bisect. Merge commit preserves the conversation but is harder to read. Rebase is linear like squash but preserves commits, so the audit trail no longer matches the conversation.
For an infrastructure repository, the operational answer is usually squash with a detailed PR description. The description is where the rationale lives; the squash commit is where the change lives.
Production discipline
- Pick one strategy per repository. Mixed trunk is harder to read and bisect.
- Document the choice in CONTRIBUTING.md.
- Configure the squash author. Default to the PR author.
- Use a detailed PR description. When squashing, the description is the audit trail.
- Disable force-push to merged branches.
Cross-course references
- GitOps with Argo CD - Part IV (SyncPatterns): how merge strategy interacts with the GitOps sync trigger.
- CI/CD Pipeline Patterns - Part VI (ReleaseEngineering): how merge strategy interacts with release tagging.
- Terraform for Production Sysadmins - Part XI (PRWorkflows): the Terraform-specific merge strategy decision.
Quiz
Knowledge check · 4 questions
Q1. A team uses squash merges on their infrastructure repository. Six months after a Terraform change is merged, an auditor asks: which intermediate commits led to the final configuration? Where should the auditor look?
Q2. Rebase merges produce a merge commit with two parents, the same as merge-commit merges.
Q3. Name the three merge strategies and the shape each produces on the trunk.
Q4. Diagnose a broken git bisect caused by a merge-strategy mismatch between two repositories in the same monorepo.
A monorepo contains a Terraform module repository and an Ansible playbook repository. The Terraform repository uses squash merges; the Ansible repository uses merge commits. An engineer runs `git bisect` across the whole monorepo to find the commit that introduced a production bug. The bisect skips hundreds of commits because the merge commits do not have a single attributable diff.
Passing score: 75%. Answers are checked in this browser.