Skip to content

Cheatsheet: Merge conflicts

Git stores snapshots. Every other command is just navigating those snapshots.

A conflict is git asking which snapshot to make current.

Terminal window
git status # 1. recognize merge state
# 2. find markers in each file (open in editor, search <<<<<<<)
# 3. decide on the resolution
# 4. edit to the resolution + delete ALL markers
git add <file> # 5. stage
git commit # 6. commit (git pre-fills the message)

Default style:

<<<<<<< HEAD
your version
=======
their version
>>>>>>> their-branch-name

diff3 style (recommended; turn on once):

<<<<<<< HEAD
your version
||||||| ancestor
original version (common ancestor)
=======
their version
>>>>>>> their-branch-name

Setup commands:

Terminal window
git config --global merge.conflictstyle diff3 # standard recommendation
git config --global merge.conflictstyle zdiff3 # modern alternative, even cleaner
Typegit indicatorResolution
Textual<<<<<<< markersPick one, the other, or combine; remove markers; git add
Logical combineMarkers around adjacent changes that should coexistWrite both into the resolution; add a test
SemanticNO markers; auto-merge succeededCannot fix at merge; catch with integration tests
Delete-modify”deleted by us / modified by them”git rm <file> (delete) or git add <file> (modify)
Rename-editDelete-modify on old path + clean file on new pathApply edits to new path; git rm old path; git add new path
Terminal window
git merge --abort

Takes the repo back to exactly the state before the merge started. No data loss.

Use when: conflicts too large, wrong branch, teammate’s branch unexpected, you’re tired/distracted, you realize you should rebase first.

Don’t use when: you’re partway through resolving (aborting throws away resolution work). Instead, leave the merge state and come back later.

  • Rebase your branch onto main daily (or use git pull --rebase)
  • PRs land within 1-3 days of opening
  • Big refactors announced in team channel before starting
  • Feature flags + small PRs instead of long-lived branches
  • Engineers on different modules where possible
ToolWhen to use
Plain text editor + markersDefault; works everywhere; sufficient for 95% of conflicts
VS Code merge editorBest day-to-day; 1-click “accept this side” buttons + 3-pane mode
JetBrains merge toolBest for complex multi-region conflicts
GitHub web conflict resolverOne-line PR conflicts; not for complex
git mergetoolConfigurable external tool; most developers never use it

Worked example quick walkthroughs (lesson refresher)

Section titled “Worked example quick walkthroughs (lesson refresher)”

Example 1, Trivial textual: Both branches renamed the same heading differently. Pick the one product approved. 30 seconds.

Example 2, Logical combine: Discount codes (your branch) + gift cards (their branch) in the same calculateTotal. Combine in order; write a test for the combined case.

Example 3, Rename + edit: You renamed authenticateUser to signIn; they added a requireMfa parameter. Keep your rename AND adopt their parameter. Conflicts in declaration + every call site.

Example 4, Delete-modify: You deleted a file; they fixed a bug in it. Choose: delete (your delete wins) or modify (their fix wins) or both (their fix now, plan delete for later PR).

Example 5, Semantic (no markers, fails at runtime): Validation rejecting negatives + refunds using negatives. Git can’t catch; integration tests + thoughtful review do.

Example 6, Rename-edit (if rename not detected): You moved a file; they edited the old path. Apply their edits to the new path; git rm the old.

L8 introduces remotes and forks: the way branches travel across machines and across repositories. You’ll learn origin vs upstream, the push/fetch/pull mechanic, what git pull --rebase does, and the fork-based contribution model used by open-source projects.

L8 closes Phase 2. After L8 you can collaborate end-to-end with a real partner on a real project.