Chapter 3.2 — Reading Conflict Markers☕ 16 min read

Reading Conflict Markers

Markers padho, dono side samjho, sahi choose karo, aur markers HATAO! Commit mein markers reh jaana badi galti hai.

01The Three Conflict Markers

<<<<<<< HEAD — Marks the beginning of the conflict. Lines below this are YOUR current branch's version.

======= — The separator. Divides your changes from their changes.

>>>>>>> branch-name — Marks the end of the conflict. Lines above this (after =======) are the INCOMING branch's version.

These markers are inserted directly into your file by Git. You must remove these markers and choose the correct code before committing. Leaving markers in a committed file is a serious mistake.

# What a conflict looks like in your file:
function getConfig() {
<<<<<<< HEAD
  return { port: 3000 };     // YOUR version (current branch)
=======
  return { port: 8080 };     // THEIR version (incoming branch)
>>>>>>> feature/api-port
}

# Resolution options:
# 1. Keep yours:   return { port: 3000 };
# 2. Keep theirs:  return { port: 8080 };
# 3. Combine:      return { port: process.env.PORT || 3000 };
# 4. Write new:    return { port: 3000, host: "localhost" };
Conflict markers are not comments. They are NOT ignored by the compiler or interpreter. If you commit a file with <<<<<<< still in it, your code will break at runtime. Every marker must be removed and replaced with the correct resolved code.
02HEAD vs Incoming: Who is Who?

HEAD = the branch you are currently ON (where you ran git merge).

branch-name (after >>>>>>>) = the branch you are merging IN.

If you're on main merging feature: HEAD = main's version, feature = incoming version.

If you're on feature rebasing onto main: HEAD = main's version (rebase reverses the perspective!).

Understanding which side is which is crucial for making the right choice.

# Scenario: On main, merging feature
git checkout main
git merge feature
# <<<<<<< HEAD        -> main's version
# =======
# >>>>>>> feature      -> feature's version

# Scenario: On feature, rebasing onto main (perspective flips!)
git checkout feature
git rebase main
# <<<<<<< HEAD        -> main's version (because rebase applies ON main)
# =======
# >>>>>>> feature      -> your feature's version

# Always read the branch name after >>>>>>> to confirm!
💡 Pro Tip: During a rebase, the meaning of HEAD flips. This is the #1 source of confusion in conflict resolution. When rebasing, HEAD is the branch you're rebasing ONTO, not your current branch. Always check the label after >>>>>>> to verify which side is which.
03Multiple Conflicts in One File

A single file can have MULTIPLE conflict sections.

Each conflict has its own set of <<<<<<<, =======, >>>>>>> markers.

You must resolve EACH conflict individually.

Search for <<<<<<< in your editor to find all conflicts.

Don't assume resolving one conflict fixes the whole file.

After resolving, search again for <<<<<<< to verify none were missed.

# File with multiple conflicts:
const config = {
<<<<<<< HEAD
  port: 3000,
=======
  port: 8080,
>>>>>>> feature
  host: "localhost",
};

function start() {
<<<<<<< HEAD
  console.log("Starting...");
=======
  console.log("Bootstrapping...");
>>>>>>> feature
}
# Two separate conflicts! Resolve each one independently.
Pro tip: Use grep -n "<<<<<<<" file.js or your IDE's search to find ALL conflict markers before you start resolving. Count them. After resolving, search again and verify the count is zero. Missing even one conflict marker means broken code in production.
04Diagnosing Conflicts with Git Commands

git status — lists all conflicted files and their conflict type.

git diff — shows only the conflicting sections (during a merge).

git diff --name-only --diff-filter=U — lists only unmerged (conflicted) file names.

git ls-files -u — lists unmerged files with stage numbers (1=common, 2=ours, 3=theirs).

These commands help you understand the scope of conflicts before diving into resolution.

# List all conflicted files
git status
# Unmerged paths:
#   both modified:   app.js
#   added by them:   new-module.js

# Quick list of just the filenames
git diff --name-only --diff-filter=U
# app.js
# new-module.js

# See the conflicting sections
git diff
# Shows only the parts that Git couldn't auto-merge

# Detailed unmerged file info
git ls-files -u
# 100644 abc123 1  app.js   (common ancestor)
# 100644 def456 2  app.js   (ours - HEAD)
# 100644 ghi789 3  app.js   (theirs - merging branch)
💡 Pro Tip: The three stages in git ls-files -u correspond to the three-way merge: stage 1 = common ancestor (base), stage 2 = ours (HEAD), stage 3 = theirs (incoming). You can extract each version using git show :1:filename, git show :2:filename, git show :3:filename.
05Resolution Strategies: Which Side to Choose?

Keep yours: Your change is correct, discard theirs.

Keep theirs: Their change is correct, discard yours.

Keep both: Combine the changes if they're complementary.

Write new: Neither side is fully correct, write a new solution.

Most conflicts are resolved by combining or rewriting, not simply choosing one side.

Always understand WHY both sides made their changes before choosing.

# Strategy 1: Keep yours
# <<<<<<< HEAD
console.log("v2");   # Keep this
# =======
console.log("v1");   # Discard this
# >>>>>>> feature
# Result: console.log("v2");

# Strategy 2: Combine both
# <<<<<<< HEAD
function login() {}
# =======
function logout() {}
# >>>>>>> feature
# Result:
function login() {}
function logout() {}

# Strategy 3: Write new
# <<<<<<< HEAD
port = 3000
# =======
port = 8080
# >>>>>>> feature
# Result:
port = process.env.PORT || 3000
The best resolution is often not "yours" or "theirs" — it is a NEW solution that incorporates the intent of both changes. Ask yourself: "What was each person trying to achieve?" Then write code that satisfies both intents. This is why understanding the WHY behind each change matters more than the code itself.

Lo kar liya — Key Points:

  • ✅ <<<<<<< HEAD marks the start of your current branch's version
  • ✅ ======= separates your version from the incoming version
  • ✅ >>>>>>> branch-name marks the end of the incoming branch's version
  • ✅ HEAD = the branch you're ON, branch-name = the branch you're merging IN
  • ✅ A single file can have multiple conflicts, each with its own set of markers
  • ✅ You MUST remove all conflict markers before committing; leaving them in is a critical error
Course Search
Search across all chapters & stages
📖

Search the course

Type any topic — branching, stash, rebase, hooks — and jump straight to that chapter.

merge branchesgit stashundo commitrebase