Merge Methods, Auto-Merge, Merge Queue, Conflict Handling, and Branch Cleanup: Concepts, Architecture, and Mental Model
Build a precise integration mental model: merge commit, squash, and rebase create different Git graphs and commit identities; auto-merge and merge queues add hosted policy and validation state around those graph operations.
Learning objectives
- Predict the commit-graph and commit-identity consequences of merge commit, squash merge, and rebase merge before integrating a pull request.
- Explain auto-merge as deferred GitHub integration that waits for repository requirements rather than as a new Git merge algorithm.
-
Explain merge queues, speculative merge groups, queue ordering,
and the
merge_groupevent without confusing queue refs with ordinary PR branches. - Choose between GitHub’s limited web conflict editor and local Git conflict resolution based on conflict shape and inspection needs.
- Treat head-branch deletion, restoration, and stale-branch cleanup as repository lifecycle operations with downstream dependency checks.
- Inspect repository merge policy and PR merge state read-only before changing either.
1. The practical problem: “Merge” is not one operation
Chapter 08 ended with review evidence attached to a current pull-request head. The next question is not merely “can we click Merge?” A GitHub repository can turn the same reviewed change into different histories, can defer the integration until gates pass, can test speculative combinations through a queue, and can delete the head branch afterward. Those choices affect commit identity, audit trails, CI evidence, rollback reasoning, and later release automation.
2. Separate four layers before reasoning about integration
| Layer | Examples | Source of truth |
|---|---|---|
| Core Git graph | commits, parents, refs, merge-base, conflict markers | Git objects/refs in local or hosted repository |
| Pull request state | base/head repositories, head OID, review decision, mergeability | GitHub PR object |
| Integration policy | allowed merge methods, required checks/reviews, auto-merge, merge queue | GitHub repository/rules policy |
| Delivery state | workflow runs, deployment/environment state, releases | GitHub Actions or external delivery systems |
A PR can be approved yet blocked by a required check; a check can be green yet the PR can conflict with the base; a PR can be merged while deployment later fails. Do not compress these into a single “green” state.
3. Three merge methods create three different histories
flowchart LR
A[Base A] --> B[Base B]
B --> M[Merge commit M]
T1[Topic T1] --> T2[Topic T2]
T2 --> M
B2[Base B] --> S[Squash commit S]
U1[Topic U1] --> U2[Topic U2]
U2 -.changes combined.-> S
B3[Base B] --> R1[Rewritten R1]
R1 --> R2[Rewritten R2]
V1[Topic V1] -.content replayed.-> R1
V2[Topic V2] -.content replayed.-> R2
Merge commit: GitHub preserves the PR branch commits as ancestors of the base and adds an explicit merge commit with two parents. GitHub’s default merge uses a non-fast-forward merge.
Squash merge: GitHub combines the PR changes into one new commit on the base. The original topic commits are not ancestors of the updated base, so continuing a long-lived branch after a squash can create confusing repeated commit ranges.
Rebase merge: GitHub replays each PR commit onto the current base without a merge commit. GitHub creates new commit SHAs and updates committer information; the resulting base commits are therefore not the same objects as the original topic commits.
| Question | Merge commit | Squash | Rebase |
|---|---|---|---|
| Original PR commits remain ancestors of base? | Yes | No | No; replayed commits have new SHAs |
| Explicit merge point? | Yes | No | No |
| One base commit per PR? | No, plus merge commit | Yes | No |
| Linear base history? | Not necessarily | Yes for the integration | Yes for the integration |
| Best fit | Meaningful internal commit history / topology | One logical change per PR | Clean, meaningful commits and linear history |
4. Auto-merge controls timing, not graph semantics
Auto-merge is a GitHub-hosted request: “when every configured requirement is satisfied, integrate this PR using the chosen merge method.” It only becomes useful when the PR cannot merge immediately because a required review or status check is pending. Repository maintainers enable the feature; people with write access can enable it for an eligible PR.
Auto-merge can be disabled by later state changes. GitHub documents
that a push by someone without write permission or a base-branch
change disables auto-merge. Treat the
autoMergeRequest field as state to inspect, not as a
promise that the PR will eventually merge.
gh pr view 42 -R OWNER/REPO --json number,isDraft,headRefOid,baseRefOid,mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,autoMergeRequest
5. Merge queue tests speculative integration against a moving busy base
flowchart TD
P1[PR 1 passed normal gates] --> Q[Merge queue]
P2[PR 2 passed normal gates] --> Q
Q --> G1[Speculative merge group]
G1 --> C1[Required checks]
C1 -->|pass| B[Target branch]
C1 -->|fail| R[Remove/retry according to queue state]
B --> G2[Next speculative group]
A merge queue is useful when many approved PRs target a protected branch. Instead of forcing every author to update against the latest base, GitHub constructs speculative integration state that includes the latest target branch and queued changes ahead of the PR. Required checks run against that merge group; only passing groups advance to the base branch.
For GitHub Actions, queue-aware required workflows must include the
merge_group event. Its GITHUB_SHA is the
merge-group SHA and GITHUB_REF is the merge-group ref.
A workflow that only listens to pull_request can leave
the queue waiting forever because the required check is never
reported for the speculative group.
name: integration-gate
on:
pull_request:
merge_group:
permissions:
contents: read
jobs:
integration-gate:
runs-on: ubuntu-latest
steps:
- run: echo "same required check name runs for PR and merge group"
6. Conflict resolution changes the PR head; choose the smallest trustworthy tool
GitHub’s web conflict editor handles simple competing line changes. GitHub documents an important consequence: resolving a conflict in the web UI merges the entire base branch into the PR head branch. That is a real history change, not a cosmetic text edit. More complex conflicts must be resolved locally.
Local resolution is usually easier to inspect for production work:
fetch the base, merge or rebase deliberately, inspect
git status and the conflict markers, run relevant
tests, commit the resolution, and push the updated head. Avoid a
blind force push during active review; if history rewrite is truly
required, Chapter 08’s communication/freshness rules still apply.
7. Branch cleanup is dependency cleanup, not housekeeping
A merged or closed PR head branch can be deleted when no open PR still depends on it. GitHub can also automatically delete merged head branches. A deleted PR head can be restored from the closed PR page in supported cases. Before deletion, inventory downstream dependencies: open dependent PRs, release scripts, Pages sources, long-running environments, external CI references, or human handoff instructions.
| Action | What changes | What does not automatically change |
|---|---|---|
| Delete merged head branch | Hosted branch ref disappears | Merged commits reachable from base remain; local clones keep their local branch |
| Restore branch from PR | Hosted head ref is recreated | Local clones are not automatically updated |
| Enable automatic deletion | Future merged PR head refs are candidates for cleanup | Protected/rule-blocked refs may remain; downstream tools are not “fixed” |
8. Read-only inspection before changing merge policy
\, command substitution such as
$(...), here-documents, printf, and
rm -rf are Git Bash/Bash/zsh syntax. PowerShell users
can put the same Git/gh arguments on one line, use the
backtick for continuation, and use
Set-Content/Add-Content/Remove-Item -Recurse -Force
for file operations. GitHub merge and policy semantics are
shell-independent.
# Repository merge settings, no mutation.
gh repo view OWNER/REPO --json nameWithOwner,defaultBranchRef,mergeCommitAllowed,squashMergeAllowed,rebaseMergeAllowed,deleteBranchOnMerge
# Pull-request integration state.
gh pr view 42 -R OWNER/REPO --json baseRefName,baseRefOid,headRefName,headRefOid,commits,mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,autoMergeRequest
# Versioned API evidence.
gh api -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2026-03-10" repos/OWNER/REPO/pulls/42 --jq '{state,mergeable,mergeable_state,head_sha:.head.sha,base_sha:.base.sha,merged,merge_commit_sha}'
GitHub may calculate some mergeability fields asynchronously. If a field is temporarily unknown, preserve that state and query again rather than inventing a conclusion.
9. DevOps connection: merge policy is production change management
Integration is the moment review evidence and automation evidence become reachable from a release branch. A team that cannot explain its merge graph cannot reliably trace regressions; a team whose queue-aware CI never runs cannot trust queued validation; a team that deletes branches without dependency inventory can break downstream automation. Merge policy therefore belongs in the operating model, not in individual button preference.
10. Lesson summary
Merge commit, squash, and rebase differ in graph shape and commit
identity. Auto-merge defers an allowed merge method until gates
pass. Merge queues validate speculative combinations against a busy
protected branch and require queue-aware checks such as
merge_group. Conflict resolution moves the PR head, and
branch cleanup must account for downstream dependencies.
Knowledge check
Which merge method preserves the original PR commits as ancestors of the base and adds an explicit integration point?
Merge commit.
Why does a GitHub rebase merge produce different commit SHAs from the topic branch?
GitHub replays the commits onto the base and creates new commit objects/committer metadata.
What does auto-merge add to Git?
Nothing to the Git merge algorithm. It is hosted GitHub policy/timing that waits for required conditions and then executes an allowed merge method.
Why must a required Actions workflow include merge_group when a merge queue is used?
The queue validates a speculative merge-group SHA/ref. Without a merge_group run, the required check may never be reported for that state.
Does deleting a merged head branch delete the merged commits from the base branch?
No. The hosted head ref is removed, while commits reachable from the base remain.
Authoritative references
Pull request merges
About merge methods on GitHub
Automatically merging a pull request
Merging a pull request with a merge queue
Managing a merge queue
Events that trigger workflows: merge_group
Resolving a merge conflict on GitHub
Resolving a merge conflict using the command line
Deleting and restoring branches in a pull request
Managing the automatic deletion of branches
About protected branches
gh pr merge
gh pr view
REST API endpoints for pull requests
REST API versions
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.