Chapter 09Lesson 04~155 minutes

Merge Methods, Auto-Merge, Merge Queue, Conflict Handling, and Branch Cleanup: Diagnostics, Failure Modes, Security, and Performance

Diagnose blocked or surprising integrations from commit graphs, PR head/base OIDs, required checks, auto-merge state, merge-queue events, conflicts, and downstream branch dependencies before taking destructive action.

Diagnosticsmerge_groupConflict recoverySafety

Learning objectives

  • Use an evidence-preserving diagnostic sequence for merge-policy, auto-merge, queue, conflict, and cleanup failures.
  • Explain duplicate-looking history after squash/rebase choices using ancestry and patch identity instead of guessing from commit messages.
  • Diagnose auto-merge that never completes by separating required review/check/policy/environment gates.
  • Diagnose a merge queue that cannot report a required check because CI omits the merge_group trigger.
  • Recognize when web conflict resolution changed more history than expected and verify the resulting PR head before approving/merging.
  • Recover from premature branch cleanup with the least destructive option and avoid using force, bypass, or history rewrite as first response.
Availability: Diagnostics use public GitHub Free-compatible evidence wherever possible. Merge-queue failures use documented fixtures unless the learner has an eligible organization-owned repository. Enterprise audit-log or environment-policy evidence may be discussed as optional; the mandatory path uses PR/check/ref/API evidence.

1. Diagnostic sequence: preserve → scope → inspect → correct → verify

  1. Preserve evidence: PR URL/number, base/head OIDs, commit list, graph, check rollup, review decision, auto-merge request, branch-protection response, workflow trigger configuration, and relevant branch refs.
  2. Identify scope: which repository/owner, base branch, head branch, PR, workflow/check, merge-group ref, or downstream automation is affected?
  3. Inspect controls: allowed merge methods, rules/protection, required checks/reviews, queue requirement, Actions event triggers, conflict state, and branch dependencies.
  4. Choose least destructive correction: change the wrong setting/check/branch dependency—not the history or policy unrelated to the cause.
  5. Verify independently: graph ancestry, PR JSON, check result, queue state, or hosted ref must prove the repair.
gh pr view PR -R OWNER/REPO --json   baseRefOid,headRefOid,commits,mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,autoMergeRequest

gh repo view OWNER/REPO --json mergeCommitAllowed,squashMergeAllowed,rebaseMergeAllowed,deleteBranchOnMerge

gh api -H "X-GitHub-Api-Version: 2026-03-10"   repos/OWNER/REPO/branches/BASE/protection

2. Failure: duplicate-looking or unexpected commits after the wrong strategy

Suppose a long-running branch was squash-merged, development continued on the same branch, and a second PR now shows commits whose changes were already represented by the earlier squash commit. The first reaction should not be “force reset everything.” The commit SHAs differ because the squash commit is a new object, so Git cannot infer that the original branch commits became ancestors of the base.

git fetch origin
# What commits are reachable from head but not base?
git log --oneline origin/main..origin/long-running-topic
# What patch content is actually different?
git diff --stat origin/main...origin/long-running-topic
git diff origin/main...origin/long-running-topic

Repair options depend on desired future history: start a fresh topic branch from the current base and reapply only remaining changes, or deliberately rebase/cherry-pick with communicated history rewrite in the disposable context. The lesson’s safest production pattern is shorter-lived branches and a merge strategy aligned with branch lifetime.

3. Broken example: auto-merge is enabled but never completes

{
  "autoMergeRequest": {"mergeMethod":"SQUASH"},
  "reviewDecision": "APPROVED",
  "mergeStateStatus": "BLOCKED",
  "statusCheckRollup": [
    {"name":"integration-gate","conclusion":"FAILURE"},
    {"name":"security-gate","conclusion":"SUCCESS"}
  ]
}

Interpretation: auto-merge exists, so the repository feature and PR request were configured. Approval is present. The PR is still blocked because a required check failed. The least destructive correction is to inspect the failing workflow/log and repair the actual condition, then rerun/retrigger the check. Disabling the required check or merging with admin bypass would erase the causal evidence.

Security-sensitive: gh pr merge --admin bypasses normal requirements when the caller has sufficient rights. This chapter mentions it only to explain why it is not a diagnostic repair.

4. Broken example: queue waits because the required workflow ignores merge_group

Fixture: integration-gate is required on main. A PR passes its pull_request run and enters the merge queue. GitHub creates merge-group SHA G42, but no integration-gate check ever appears for G42.

# BROKEN for a required queue check
on:
  pull_request:

The cause is event coverage, not the PR code. Repair the workflow so the same required check runs for the queue state:

on:
  pull_request:
  merge_group:
permissions:
  contents: read

After merging the workflow fix into the base, re-enqueue/re-evaluate according to the queue’s current state. Do not create a second differently named required check unless the protection policy is intentionally changed; ambiguous or missing required check names can create a different blockage.

5. Failure: web conflict resolution changed more history than the author expected

GitHub’s web conflict editor commits a merge of the entire base branch into the PR head. A reviewer expecting “one text fix” may therefore see a new head commit and a broader ancestry change. Preserve the before/after head OIDs and inspect the new graph:

git fetch origin
git log --graph --decorate --oneline --all --max-count=30
gh pr view PR --json headRefOid,commits,files,mergeable,reviewDecision,statusCheckRollup

If the result is semantically correct, re-review the current head and continue. If the web resolution introduced unintended content, do not “hide” it with another force update; use a controlled new commit or, in a disposable/private topic branch with explicit coordination, a deliberate history correction and fresh review.

6. Failure: branch was deleted while something still depends on it

Symptoms may include a dependent PR whose base disappeared, an external CI job that cannot fetch the ref, or a human handoff that names a branch no longer present. First inspect whether the PR is merged/closed and whether GitHub offers Restore branch. Also identify other open PRs or external systems that referenced the branch.

Evidence Least destructive correction
Closed/merged PR page offers Restore branch Restore the head ref, then repair the dependent workflow/PR
Merged commit still reachable but branch restore unavailable Create a new branch deliberately from the known commit only after validating the intended SHA
External automation referenced an obsolete branch name Update automation to durable release/default refs; branch restoration may be temporary recovery
Open dependent PR exists Do not delete base ref until dependency is retargeted or merged
Branch deletion is destructive ref mutation. Restoration can help, but it is not a substitute for dependency inventory before cleanup.

7. Failure: the desired merge method is unavailable

If gh pr merge --rebase cannot proceed, distinguish four causes: repository rebase merging is disabled; a branch/ruleset merge-method rule conflicts; the PR cannot currently be safely rebased; or the caller lacks merge permission. Inspect settings and merge state before changing anything.

gh repo view OWNER/REPO --json mergeCommitAllowed,squashMergeAllowed,rebaseMergeAllowed
gh pr view PR -R OWNER/REPO --json mergeable,mergeStateStatus,reviewDecision,statusCheckRollup

8. Performance, rate limits, and billing only where causal

Merge queues can increase CI executions because speculative groups are revalidated as queue order/base state changes. That can affect throughput and compute use, especially with expensive third-party CI or private-repository hosted runners. Do not hard-code current included minutes or prices; measure queue churn, run duration, and current plan billing when designing the policy. REST/GraphQL polling for queue or PR state is also rate-limited—prefer event-driven status plus bounded polling/backoff rather than tight loops.

9. Security-sensitive operations checklist

Operation Why sensitive Safer chapter pattern
Force-update PR/base branch Can invalidate review and overwrite shared history Normal commit/merge resolution; if rewrite unavoidable, disposable branch + explicit coordination
Admin bypass Can skip required controls Fix failing requirement; use bypass only under separate incident governance
Delete head/base branch Removes hosted ref and may break dependencies Inventory dependencies; verify merged/closed state; restore if needed
Disable required check/queue Weakens integration policy Repair event/check configuration
Workflow privilege change Can increase token capability during untrusted PR evaluation Keep explicit least-privilege permissions; no secret/context dumps
Repository deletion/transfer Changes ownership/availability broadly Not needed in this chapter; archive disposable repo at cleanup

10. Diagnostic runbook

1. Record PR URL, base/head OIDs, merge method requested, current graph.
2. Record reviewDecision, mergeable/mergeStateStatus, required checks, autoMergeRequest.
3. Record repository merge settings and branch protection/ruleset requirements.
4. For queue failures, record merge-group SHA/ref and whether required CI listens to merge_group.
5. For conflicts, record which branch was merged/rebased into which head and inspect resulting diff/graph.
6. For cleanup failures, inventory every PR/workflow/release/external system referencing the branch.
7. Repair the smallest causal control or code condition.
8. Re-run/observe the same evidence source that originally failed.
9. Record merged SHA separately from deployment/release evidence.

Knowledge check

Auto-merge is configured and reviews are approved, but one required check is failing. What should you fix?

A queue-required check passes on PRs but never appears on queued merge groups. What is the first workflow setting to inspect?

Why can a squash-merged long-lived branch create duplicate-looking future PR history?

What does web conflict resolution do to the PR head?

A deleted branch breaks an external job. What is safer than immediately recreating a branch by name from memory?

Next lesson

Integrate the mechanics under one protected-branch checkpoint

Lesson 05 combines two merge policies, a required check, blocked auto-merge, a controlled conflict, safe recovery, graph verification, cleanup, and a written busy-branch merge policy.

Authoritative references

 Pull request merges
 Automatically merging a pull request
 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
 About protected branches
 gh pr merge
 REST API endpoints for protected branches
 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.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.