SECTION 1
Historical Context & Motivation
Before modern version control systems existed, programmers working on the same codebase had to coordinate manually. They might email files back and forth, keep numbered copies on a shared drive, or simply shout across the room, "Don't touch main.py right now!" As software projects grew to involve dozens or even thousands of contributors, this approach became completely unworkable. The need for a system that could automatically merge changes from different people became critical.
Version control tools like Git solved most of this problem by tracking every change and automatically combining work from different branches. However, when two people edit the exact same lines of a file, Git cannot decide whose version to keep. This situation is called a merge conflict, and it requires a human to step in and resolve it.
1972 • SCCS — Early Version Control
1986 • CVS Introduces Concurrent Editing
2005 • Git Is Born
2008 • GitHub Launches
Today, understanding how to read and resolve merge conflicts is as fundamental as writing code itself. Whether you are collaborating on a school project or contributing to open-source software, you will encounter merge conflicts. The key question is: how do you read the conflict markers Git places in your files, and how do you decide what the final code should look like?
SECTION 2
Core Principles & Definitions
Before you can resolve a merge conflict, you need to understand a few foundational ideas about how Git tracks and combines changes. These concepts form the mental model you will rely on every time you see those intimidating conflict markers in a file.
Branch
Merge
Merge Conflict
Conflict Markers
<<<<<<<, =======, and >>>>>>>. Your job is to choose the correct content and remove these markers.Resolution
KEY TAKEAWAY
SECTION 3
Visual Explanation — Anatomy of a Merge Conflict
The diagram below shows exactly what happens inside a file when Git encounters a merge conflict. Understanding this visual layout is the single most important step toward confidently resolving conflicts.
greeting.py after a failed merge. Lines 1–3 and 11–13 are unchanged. The conflict zone (lines 4–10) contains both versions. The HEAD section shows your current branch's code, and the incoming section shows the other branch's code. The equals divider separates them.Notice three critical markers in the conflict zone. The <<<<<<< HEAD line marks the beginning and tells you everything between it and the divider is from your current branch. The ======= divider separates the two competing versions. Finally, >>>>>>> feature-welcome marks the end and names the incoming branch. Everything outside these markers is code that both branches agreed on, so Git left it alone.
SECTION 4
How Git Detects Conflicts — The Three-Way Merge
Git does not simply compare two files against each other. It uses a technique called a three-way merge. When you merge branch B into branch A, Git finds the common ancestor — the commit where the two branches originally diverged. Git then compares each branch's file to this ancestor to determine what changed.
If branch A changed line 5 but branch B did not, Git keeps branch A's version of line 5. If branch B changed line 10 but branch A did not, Git keeps branch B's version. These are clean merges — Git handles them automatically. A conflict only arises when both branches changed the same line relative to the ancestor, because Git cannot guess which change you intended.
Why not just a two-way comparison?
SECTION 5
Detailed Breakdown of Conflict Markers
When you open a file with a merge conflict, the conflict markers may look intimidating at first. However, they follow a strict, predictable pattern. Once you learn to read them, resolving conflicts becomes a straightforward process. Let's break down each marker and its role.
| Marker | Meaning | What Follows |
|---|---|---|
<<<<<<< HEAD | Start of conflict — marks the beginning of your current branch's version | The lines from your branch (the branch you are currently on) |
======= | Divider — separates the two conflicting versions | The lines from the incoming branch (the branch being merged in) |
>>>>>>> branch-name | End of conflict — names the incoming branch | Normal, non-conflicting code resumes after this line |
The three conflict markers Git inserts into your file
A single file can contain multiple conflict zones if different sections of the same file were edited by both branches. Each conflict zone has its own set of three markers. You must resolve every conflict zone before Git considers the merge complete.
- Option A — Keep yours: Delete the incoming section, the divider, and all three markers. Keep only the code between
<<<<<<<and=======. - Option B — Keep theirs: Delete your section, the divider, and all three markers. Keep only the code between
=======and>>>>>>>. - Option C — Combine both: Manually edit the section to include the best parts of both versions, then delete all three markers.
- Option D — Rewrite: Replace the entire conflict zone with completely new code, then delete all three markers.
Critical Rule
<<<<<<<, =======, >>>>>>>) from the file. If you leave even one marker in, your code will not run correctly — Python will throw a SyntaxError because these markers are not valid Python syntax.SECTION 6
Worked Example — Resolving a Conflict Step by Step
Let's walk through a complete scenario. You and your classmate are both working on a Python project. You are on the main branch, and your classmate worked on a branch called feature-greeting. When you run git merge feature-greeting, Git reports a conflict in greeting.py.
Resolving a Merge Conflict in greeting.py
- 1
Step 1 — Identify the conflict
Rungit statusto see which files have conflicts. Git will list them under "Unmerged paths." Opengreeting.pyin your text editor. Look for the<<<<<<<marker to find the conflict zone.Found conflict ingreeting.pyat line 4. - 2
Step 2 — Read both versions
Your version (HEAD) uses an f-string:print(f"Hello, {name}!"). Your classmate's version uses string concatenation:print("Welcome, " + name + "!"). Both are valid Python, but the greeting text and string formatting style differ. - 3
Step 3 — Decide on the resolution
After discussing with your classmate, you decide the f-string style is cleaner, but you prefer the word "Welcome" over "Hello." You will combine both versions by using f-string syntax with the welcome message.Decision: combine both — use f-string with "Welcome" greeting. - 4
Step 4 — Edit the file
Delete all three conflict markers and both original versions. Replace them with the combined code:print(f"Welcome, {name}!"). Make sure only clean, valid Python remains in the file.The conflict zone now reads:def greet(name): print(f"Welcome, {name}!") - 5
Step 5 — Stage and commit
Save the file. Rungit add greeting.pyto mark the conflict as resolved. Then rungit committo complete the merge. Git will auto-generate a merge commit message, which you can accept or customize.Merge complete! The conflict is resolved, and the project history records your decision.
Pro Tip
SECTION 7
Conflict Resolution Strategies — Strengths & Limitations
There is no single "correct" way to resolve every merge conflict. Your strategy depends on the context: what the code does, who wrote it, and what the project needs. Here is a comparison of common approaches.
| Strategy | When to Use | Risks |
|---|---|---|
| Accept yours (HEAD) | You are confident your changes are correct and the incoming changes are outdated or unnecessary. | You may accidentally discard important work from the other branch. |
| Accept theirs (incoming) | The other developer's version is clearly better, or your changes were experimental. | You lose your own changes — make sure they are not needed. |
| Combine both | Both versions add different value, like one adding a feature and the other fixing formatting. | You must understand both changes well enough to merge them without introducing bugs. |
| Rewrite entirely | Both versions have problems, or the requirements have changed since both were written. | Takes more time and requires full understanding of the desired behavior. |
Common merge conflict resolution strategies
KEY TAKEAWAY
SECTION 8
Connection to Advanced Git Workflows
The simple text-based conflict resolution you have learned here is the foundation for more advanced Git workflows used in professional software development. As projects grow, teams adopt strategies like rebasing, cherry-picking, and pull request reviews that all build on your ability to read and resolve conflicts.
| What You Learned | Where It Leads |
|---|---|
| Reading conflict markers in a text editor | Using dedicated merge tools (VS Code merge editor, KDiff3, Meld) that show conflicts in a side-by-side or three-pane view |
Resolving conflicts from git merge | Resolving conflicts during git rebase, which replays your commits on top of another branch one-by-one |
| Deciding between your code and a classmate's code | Reviewing pull requests on GitHub, where conflicts are highlighted in the browser and discussed before merging |
| Manually editing files after a conflict | Writing automated tests that run after every merge to verify the resolved code actually works |
From beginner conflict resolution to professional workflows
As you gain experience, you will also learn to prevent many merge conflicts before they happen. Strategies like keeping branches short-lived, merging frequently from main, and communicating with teammates about which files you are working on can dramatically reduce the number of conflicts you encounter.
SECTION 9
Practice Problems
Question 1: CONCEPTUAL
Show answer
Question 2: BASIC CALCULATION
config.py, write what the file should look like if you accept the incoming change:
<<<<<<< HEAD
max_retries = 3
=======
max_retries = 5
>>>>>>> update-configShow answer
======= divider and the >>>>>>> marker. The resolved file should simply contain: max_retries = 5. No conflict markers should remain. After saving, you would run git add config.py followed by git commit to complete the merge.Question 3: INTERMEDIATE
utils.py:
<<<<<<< HEAD
def calculate_area(radius):
return 3.14 * radius ** 2
=======
def calculate_area(r):
import math
return math.pi * r ** 2
>>>>>>> improve-math
Which version is better and why? Write the resolved code.Show answer
improve-math branch is better for two reasons: first, it uses math.pi which provides a much more precise value of π than the hardcoded 3.14; second, importing from the standard library is a best practice. However, you might combine the best of both by keeping the descriptive parameter name radius from the HEAD version. The resolved code would be: def calculate_area(radius):
import math
return math.pi * radius ** 2Question 4: APPLIED
main.py) on separate branches. When you try to merge, Git shows two separate conflict zones in the same file. Describe the complete process you would follow to resolve both conflicts and finish the merge. Include the Git commands you would use.Show answer
git status to confirm that main.py is listed under "Unmerged paths." Open the file and locate both conflict zones by searching for <<<<<<<. For each conflict zone, read both versions carefully, discuss with your classmate whose changes are involved, and decide whether to keep one version, combine them, or rewrite the section. Edit the file to remove all six conflict markers (three per zone) and leave only clean Python code. Save the file and verify it runs correctly with python main.py. Then run git add main.py and git commit to finalize the merge.Question 5: CRITICAL THINKING
Show answer
main so branches do not diverge too far, and (2) communicate with teammates about who is working on which files so overlapping edits are minimized. A third practice is to break large files into smaller modules so that different features are developed in different files, reducing the chance of overlapping changes.SUMMARY
Summary
Summary
A merge conflict occurs when two branches in Git modify the same lines of the same file. Git uses a three-way merge (comparing both branches against their common ancestor) to detect which lines conflict. When a conflict is found, Git inserts three conflict markers into the file: <<<<<<<, =======, and >>>>>>>.
To resolve a conflict, you open the file, read both versions, decide which code to keep (yours, theirs, a combination, or a rewrite), remove all conflict markers, and then run git add and git commit to finalize the merge. Merge conflicts are a normal, unavoidable part of collaborative development — mastering them is an essential skill for every programmer.