Chapter 09Lesson 04~210 minutes

Merge Methods, Merge Trains, Mergeability Checks, Conflict Resolution, and Integration Strategies: Diagnostics, Failure Modes, Security, and Performance

Diagnose stale CI evidence, unexpected commit identities, unsafe conflict resolutions, merge-train confusion, and premature branch cleanup with preserved SHAs and least-destructive repair.

DiagnosticsStale pipelineCommit identityConflict semanticsTrain stateEvidence

Learning objectives

  • Diagnose a merge blocked by target advancement without assuming a previously green pipeline is still valid.
  • Reconcile source, merge, squash, and target SHAs when the resulting history differs from expectation.
  • Repair a bad conflict resolution by returning to preserved evidence rather than rewriting history blindly.
  • Distinguish ordinary MR pipeline status from merged-results and merge-train status.
  • Recover from premature source-branch deletion using MR metadata and reachable commits.
Availability baseline (verified 2026-08-21). Merge commit, merge commit with semi-linear history, fast-forward merge, squash options, ordinary merge-request pipelines, conflict resolution, auto-merge, merge checks such as pipeline/thread requirements, and source-branch cleanup are available on GitLab Free across GitLab.com, Self-Managed, and Dedicated. Merged results pipelines and merge trains are Premium/Ultimate. GitLab 19.2 documents automatic rebase before merge for semi-linear and fast-forward methods as generally available; older Self-Managed versions can differ. The mandatory chapter path therefore uses Free merge methods, local conflict resolution, and ordinary MR/API evidence, while merge trains are optional or simulated.

1. Diagnostic sequence: preserve, scope, inspect, repair, verify

Integration incidents invite destructive reactions: force-push the branch, rebase repeatedly, delete the MR, or bypass a gate. Resist that. Use a stable sequence:

  1. Preserve: source SHA, target SHA, MR IID/URL, pipeline ID/SHA, merge/squash SHA fields, conflict output.
  2. Scope: offering, project, source/target refs, merge method, squash setting, mergeability reason, pipeline type.
  3. Inspect: Git graph, API detailed_merge_status, head pipeline SHA, project settings, and discussion/approval state.
  4. Repair: use the least destructive action—rerun/rebase/resolve/update policy—without hiding the original failure.
  5. Verify: compare exact SHAs and target reachability after the correction.

2. Failure: pipeline passed, but the target moved

Suppose MR pipeline 900 passed on source SHA S1. Another MR advances target from T1 to T2. The green pipeline proves S1 passed as a source-branch MR pipeline; it does not prove S1 + T2 is valid.

MR_IID="17"
glab api "projects/$PROJECT_ID/merge_requests/$MR_IID"   --jq '{sha,diff_refs,detailed_merge_status,head_pipeline}'

git fetch origin
git rev-parse origin/main

git log --graph --decorate --oneline --all -n 25

If the method is fast-forward or semi-linear, the MR may report need_rebase. On Free, rebase/update the source and let the MR pipeline run again if the project requires exact source validation. On paid tiers, merged-results pipelines or merge trains can validate a more representative integration candidate.

3. Failure: “the merge SHA is not the source SHA”

This is often expected, not corruption. A merge commit creates a new commit with two parents. Squash creates a new commit representing multiple source commits. Fast-forward without squash may make the target equal the source tip. Diagnose using all identities:

glab api "projects/$PROJECT_ID/merge_requests/$MR_IID"   --jq '{sha,merge_commit_sha,squash_commit_sha,target_branch,state,merged_at}'

git fetch origin --prune
git show --no-patch --pretty=raw origin/main
git log --graph --decorate --oneline --all -n 40

The repair is usually documentation or a policy choice, not rewriting the target. Rewrite history only under an explicit incident/recovery procedure; this chapter never requires force-push.

4. Failure: the conflict markers disappeared, but behavior is wrong

An operator resolves mode=feature versus mode=target by keeping only mode=feature. Git is satisfied because the syntax conflict is gone, but the target-side semantic requirement vanished.

Return to the preserved tips and compare:

git show "$SOURCE_SHA_BEFORE:conflict.txt"
git show "$TARGET_SHA_AFTER_ADVANCE:conflict.txt"
git show "$RESOLVED_SHA:conflict.txt"

# Run the smallest relevant test after semantic resolution.
./scripts/test-config-behavior.sh
Do not “repair” a bad resolution by force-pushing a rewritten history into a protected/shared branch. In a normal shared workflow, add a corrective commit or reopen/new MR with preserved evidence.

5. Failure: merge-train status is mistaken for ordinary pipeline status

A train car can be waiting/running because it is validating an ordered candidate that includes earlier MRs. The source MR’s own head pipeline might already be green. These are different objects. On Premium/Ultimate, inspect the merge-train UI/API and candidate pipeline rather than treating the head pipeline as train proof.

# Premium/Ultimate, read-only example if your project already uses trains.
glab api "projects/$PROJECT_ID/merge_trains" --paginate   --jq '.[] | {id,target_branch,status,merge_request:{iid:.merge_request.iid},pipeline}' 

The REST response represents train entries and does not expose an explicit queue-position field. For exact position, current docs recommend sorting IDs or using GraphQL MergeTrainCar.index.

6. Failure: source branch was deleted before evidence capture

Do not assume the work is lost. The MR can still retain sha, merge_commit_sha, and squash_commit_sha; the target may contain the integrated commits. Preserve API output immediately and test object/reachability locally.

glab api "projects/$PROJECT_ID/merge_requests/$MR_IID"   | tee ch09-evidence/mr-recovery.json

git fetch origin --prune
SOURCE_SHA="$(jq -r .sha ch09-evidence/mr-recovery.json)"
git cat-file -t "$SOURCE_SHA" || echo "object not present locally yet"

git fetch origin "$SOURCE_SHA" || true
git show --no-patch --oneline "$SOURCE_SHA" || true

If the source commit is still reachable remotely or by MR refs, create a new recovery branch only when needed and only in the disposable lab. Do not reconstruct by guessing from commit messages.

7. Intentionally broken example: outdated source under fast-forward policy

Expected GitLab state: detailed_merge_status=need_rebase or equivalent current message because the target advanced. The unsafe response is to bypass the policy. The correct response is to preserve SHAs, rebase the source onto the latest target, inspect changed commit identities, rerun required validation, and then merge.

git switch ch09-feature
git fetch origin main
OLD_SOURCE="$(git rev-parse HEAD)"
git rebase origin/main
NEW_SOURCE="$(git rev-parse HEAD)"
printf 'old_source=%s
new_source=%s
' "$OLD_SOURCE" "$NEW_SOURCE"

# Push normally when the branch has never been published. If the branch was already
# shared and the rebase rewrote it, follow your repository's explicit collaboration
# policy; this lesson does not instruct a force push.

8. Reliability, performance, and cost belong to the causal chain

A merge train can spend more compute than independent pipelines because later cars may be rebuilt when earlier context changes. That cost can be justified when integration failures are expensive. Conversely, repeatedly rebasing every MR in a fast-moving Free project can also consume CI minutes and developer attention. Measure the bottleneck rather than weakening gates because “CI is slow.”

Knowledge check

A green MR pipeline references source SHA S1, but main advanced afterward. What is the first conclusion?

When can target SHA legitimately differ from source SHA?

Why is removing conflict markers insufficient verification?

Why might a merge-train entry be pending when the MR head pipeline is green?

What is the first recovery source after premature branch deletion?

Summary

Integration diagnosis is identity-driven. Preserve exact SHAs and pipeline context, distinguish head pipelines from integrated candidates, interpret expected new merge/squash identities correctly, and repair semantic conflicts without erasing evidence. Most failures need a targeted rebase, rerun, correction, or documentation fix—not history rewrite.

Official references

Next lesson

Prove the full integration model

Lesson 5 combines graph prediction, a deliberate mergeability failure, conflict repair, two integration strategies, reachability verification, evidence capture, and safe cleanup.

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
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.