Stage 2 · Tools
Branching & Merging
Resolving Conflicts
Understand conflict markers, use diff3 style, and resolve merge conflicts cleanly every time.
Why Conflicts Happen
A conflict occurs when Git cannot automatically merge changes from two branches. This happens when both branches modify the same lines in the same file, or when one branch deletes a file that the other branch modifies. Git marks the file as conflicted and waits for you to decide which changes to keep.
Conflicts are not errors — they are Git asking for human judgment. Git will never silently discard changes. When in doubt, it asks.
Git cannot determine which set of changes is 'correct' when both branches modify the same lines. It stops and asks you to resolve the conflict manually by editing the file.
Reading Conflict Markers
When a conflict occurs, Git inserts special markers into the file. These markers show the conflicting sections and identify which branch made each change.
function connect() {
<<<<<<< HEAD
const timeout = 5000;
const retries = 3;
=======
const timeout = 10000;
const retries = 5;
const backoff = 1000;
>>>>>>> feature/resilient-connection
return createConnection({ timeout, retries });
}The section between <<<<<<< and ======= is YOUR version (current branch). The section between ======= and >>>>>>> is THEIR version (branch being merged). You must remove the markers and choose or combine the changes.
- <<<<<<< HEAD — Start of your changes (current branch)
- ======= — Separator between the two versions
- >>>>>>> feature/resilient-connection — End of their changes (incoming branch)
Step-by-Step Resolution
# 1. Start a merge that produces a conflict
git merge feature/config
# Auto-merging config.ts
# CONFLICT (content): Merge conflict in config.ts
# Automatic merge failed; fix conflicts and then commit the result.
# 2. Check which files are conflicted
git status
# Unmerged paths:
# both modified: config.ts
# 3. Open the file and resolve the conflict
# Edit config.ts — remove markers, keep the right code
# 4. Stage the resolved file
git add config.ts
# 5. Complete the merge commit
git commit -m "Merge feature/config, resolve timeout conflict"The workflow is: encounter conflict → check status → edit file → stage → commit. Git stages the file as resolved with git add, then you commit to finalize the merge.
After editing a conflicted file, you must git add it. Git tracks resolution status by whether the file is staged. Unstaged conflicted files will remain in the unmerged state.
diff3 Conflict Style
The default conflict style shows your version and their version. The diff3 style adds a third section showing the common ancestor — the version both branches started from. This makes it much easier to understand what changed and why.
# Set diff3 as default for all repositories
git config --global merge.conflictstyle diff3Adding diff3 shows the original version (base) between the two conflicting sections, giving you full context for the decision.
function connect() {
<<<<<<< HEAD
const timeout = 5000;
const retries = 3;
||||||| merged common ancestor
const timeout = 3000;
const retries = 2;
=======
const timeout = 10000;
const retries = 5;
const backoff = 1000;
>>>>>>> feature/resilient-connection
return createConnection({ timeout, retries });
}Now you can see all three versions: yours (5000/3), the original (3000/2), and theirs (10000/5/backoff). You can make an informed decision about what the final values should be.
| Style | Shows | When to Use |
|---|---|---|
| merge (default) | Your version, Their version | Simple conflicts where context is obvious |
| diff3 | Your version, Base version, Their version | Complex conflicts where you need to understand what changed |
Checkout Theirs / Ours
When you want to accept one side of a conflict entirely, you can use git checkout --theirs or git checkout --ours to replace the file contents without manually editing.
# Accept their version (incoming branch)
git checkout --theirs config.ts
git add config.ts
# Accept our version (current branch)
git checkout --ours config.ts
git add config.ts
# Accept theirs for all conflicted files
git checkout --theirs .
git add .Use --theirs to accept the incoming branch's version, or --ours to keep your current branch's version. The names can be confusing: 'ours' is always the branch you are on when you start the merge.
Accepting one side blindly can discard important changes. Use this when you are certain one version is correct (e.g., accepting a config override from a specific branch). For most conflicts, manual editing is better.
Using mergetool
Git supports external merge tools that provide a visual interface for resolving conflicts. Tools like VS Code, IntelliJ, vimdiff, and kdiff3 show all three versions side by side and let you click to choose which changes to keep.
# Use the configured merge tool
git mergetool
# Launch a specific tool
git mergetool --tool=vscode
# Skip the tool and edit files manually
git mergetool --no-promptGit opens your configured merge tool with the three versions loaded. After resolving conflicts in the tool, save and close. Git marks the file as resolved.
# VS Code as merge tool
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait --merge $REMOTE $LOCAL $BASE $MERGED'
# Visual Studio Code also works if code is in PATH
git config --global merge.tool codeThe merge tool receives four arguments: $REMOTE (theirs), $LOCAL (yours), $BASE (common ancestor), and $MERGED (the output file). VS Code shows a three-way merge editor with color-coded conflicts.
Aborting a Merge
If a merge becomes too complex or you want to start over, you can abort it completely. This returns your working tree to the state before the merge started.
# Abort the current merge
git merge --abort
# This is equivalent to
git reset --mergeBoth commands undo the merge, restore your working tree, and remove any conflict state. Your branch pointer returns to where it was before you ran git merge.
If you are unsure about a conflict resolution, abort the merge, review the changes more carefully, and try again. It is better to take your time than to merge something incorrect.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.