Chapter 06Lesson 04~90 minutes

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.

DiagnosticsWrong branchMerge conflictsSafety

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

  1. Preserve evidence: current branch, HEAD OID, status, graph, exact merge/pull command.
  2. Inspect refs and ancestry: branch -vv, show-ref, log --graph, merge-base.
  3. Inspect in-progress state: status, unmerged index entries, MERGE_HEAD when relevant.
  4. Inspect configuration: merge/pull defaults only when behavior suggests a policy source.
  5. 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:

  1. the merge has not been committed;
  2. at least one index path is still unmerged;
  3. you must edit/choose the intended content;
  4. git add path marks that path resolved;
  5. only then can git merge --continue finish.

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

Do not reach for 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.

Next

Integrate mainline, feature, hotfix, conflict resolution, and a small-team policy

The checkpoint lab builds the entire graph, verifies every merge shape, and compares merge/squash/rebase alternatives without rewriting shared history.

Authoritative references

 git-merge
 git-branch
 git-pull
 gitrevisions

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.