Branches, Fast-Forward and Three-Way Merges, and Branching Strategies: Diagnostics, Failure Modes, Security, and Performance
Diagnose wrong-branch merges, ref/copy misconceptions, deleted-branch recovery assumptions, unresolved conflicts, pull-created merges, and overcomplicated branching models without destructive guesses.
Learning objectives
- Apply an evidence-first runbook to branch, merge, ref, and conflict failures.
- Diagnose merges performed from the wrong current branch and unexpected history after pull.
- Distinguish deleting a branch ref from deleting commit objects or reachability.
- Interpret unresolved merge state and repair it by resolving and staging intended content.
- Recognize when branching complexity is an organizational cost rather than a Git requirement.
1. Diagnostic sequence — preserve the graph before changing it
-
Preserve evidence: current branch,
HEADOID, status, graph, exact merge/pull command. -
Inspect refs and ancestry:
branch -vv,show-ref,log --graph,merge-base. -
Inspect in-progress state: status, unmerged index
entries,
MERGE_HEADwhen relevant. - Inspect configuration: merge/pull defaults only when behavior suggests a policy source.
- Choose the least destructive correction, then re-run the read-only checks.
2. Failure mode — merging from the wrong current branch
git merge topic integrates topic
into the branch currently checked out. If you intended to
update trunk but were on release/1.x, Git can produce a
completely valid merge in the wrong place.
git branch --show-current
git status --short --branch
git log --graph --decorate --oneline --all
git rev-parse HEAD
The preventive control is boring and effective: verify the current branch before integration. On shared/published history, do not reflexively rewrite the mistaken merge; determine the team's published-history policy and use a coordinated corrective commit/revert when appropriate. Chapter 10 covers undo strategies.
3. Failure mode — treating branches like directories or duplicated project copies
Creating git branch experiment adds a ref; it does not
copy the working tree or object database. Switching then updates the
shared working tree/index to match the selected commit. Two branch
names can point at the same OID.
git show-ref --heads
git rev-parse trunk
git rev-parse experiment
4. Failure mode — “I deleted the branch, so the commits vanished”
Branch deletion removes a name. First ask whether the commit is still reachable:
git cat-file -e <oid>^{commit}
git branch --contains <oid>
git log --all --decorate --oneline -- <optional-path>
If the commit was merged into trunk, it is still in trunk ancestry. If it was unmerged and the only branch ref was force-deleted, recovery may still be possible through reflogs for a time; preserve the repository and avoid pruning. Recovery is Chapter 10.
5. Failure mode — assuming “no conflict” means “correct merge”
Git detects textual/content-level conflicts, not business intent. One branch can change a timeout value while another changes retry behavior in another file; Git may merge both cleanly even though the combined system overloads a dependency. Conversely, a one-line file can conflict because both sides changed the same line differently.
Merge success must therefore be followed by tests, static checks, review, and environment validation appropriate to the system.
6. Intentionally broken example — trying to continue with unresolved files
In a disposable conflicted merge, run:
git status
git diff --name-only --diff-filter=U
git merge --continue
Git refuses to complete the merge while unmerged paths remain. Typical diagnostics mention unmerged files and the need to fix conflicts and stage the result. Interpret the failure as state evidence:
- the merge has not been committed;
- at least one index path is still unmerged;
- you must edit/choose the intended content;
git add pathmarks that path resolved;- only then can
git merge --continuefinish.
The repair is not to force a commit with unresolved index stages.
7. Failure mode — an accidental merge commit created by pull
git pull combines fetching with integration. Depending
on command-line options and configuration such as
pull.ff/pull.rebase, integration can
merge, rebase, squash, fast-forward, or refuse divergence. If a team
wants no surprise merge commits from pull, make the policy explicit
and inspect it:
git config --show-origin --show-scope --get pull.ff
git config --show-origin --show-scope --get pull.rebase
git log --graph --decorate --oneline --all
Chapter 07 will separate fetch from integration so you can see each ref movement independently.
8. Failure mode — adopting a fashionable branching diagram
A workflow with main, develop, permanent
release branches, hotfix branches, and multiple promotion lanes can
be correct for a product with long-lived supported releases. The
same diagram can be harmful for a single-service team deploying
continuously. Diagnose the real constraints: release cadence, number
of supported versions, review requirements, rollback model, CI
maturity, and feature-flag capability.
9. Security concerns that genuinely touch branching
- Local branch names do not authorize deployment; server-side policy and CI controls decide who may update protected integration refs.
- A merge can combine independently safe changes into an unsafe behavior, so security tests must run on the integrated result.
- Force-moving or force-deleting refs can hide expected review/release anchors; controlled refs should be protected by server policy.
10. Performance and operational cost
The primary “performance” issue in branching is human/system
integration throughput, not CPU time for git merge.
Long-lived divergence increases CI permutations, review size,
conflict resolution, duplicated fixes, and backport work. Measure
lead time and integration failure rate before adding more branch
lanes.
11. Red-zone operations are not first-response merge diagnostics
git reset --hard, force pushes,
git branch -D, reflog expiry, or aggressive object
pruning simply because a merge went wrong.
Preserve refs/reflogs and inspect the graph. Published-history
correction and force updates require coordinated policy and later
chapters.
12. Symptom → first evidence
| Symptom | First evidence | Likely layer |
|---|---|---|
| Merge landed in unexpected line | branch --show-current, graph |
Current ref / workflow |
| Deleted branch “lost” work | branch --contains, reflog later |
Ref/reachability |
| Merge refuses to continue | status, ls-files -u |
Unmerged index |
| Unexpected merge after pull | pull config + graph | Fetch/integration policy |
| No conflict but deployment breaks | tests/integration behavior | Semantic system interaction |
13. Knowledge check
Question 1. What is the first thing to verify before
git merge feature?
Question 2. Why can a clean merge still be wrong?
Question 3. What does unresolved
git merge --continue tell you?
Question 4. Why should an unmerged branch not be force-deleted casually?
14. Summary
Branch/merge incidents become tractable when you separate current ref, graph ancestry, in-progress index state, and policy configuration. Most mistakes need narrow ref/integration corrections or explicit follow-up history—not destructive cleanup.
Authoritative references
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.