PYTHON • GETTING STARTED AND TOOLING

Resolving Merge Conflicts — Resolve simple merge conflicts in text files (intro)

Learn how to handle the inevitable clashes when two developers edit the same file at the same time.

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
Bell Labs created the Source Code Control System, one of the first tools for tracking changes to files. It locked files so only one person could edit at a time, preventing conflicts entirely but slowing teams down.
1986
CVS Introduces Concurrent Editing
The Concurrent Versions System allowed multiple developers to edit files simultaneously. It could automatically merge non-overlapping changes, but conflicts still needed manual resolution.
2005
Git Is Born
Linus Torvalds created Git for Linux kernel development. Git introduced fast branching and distributed workflows, making merges frequent — and merge conflicts a routine part of development.
2008
GitHub Launches
GitHub made collaborative coding mainstream. Millions of developers began using pull requests and branches daily, making merge conflict resolution an essential skill for every programmer.

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?

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.

1

Branch

A branch is an independent line of development. Think of it as a copy of your project where you can make changes without affecting the main version. You create branches to work on features, fixes, or experiments.
2

Merge

A merge is the process of combining changes from one branch into another. Git compares the two branches line-by-line and automatically incorporates non-overlapping edits.
3

Merge Conflict

A merge conflict occurs when two branches change the same lines of the same file. Git cannot automatically decide which version to keep, so it pauses the merge and asks you to intervene.
4

Conflict Markers

Git inserts special conflict markers into the file to show you both versions: <<<<<<<, =======, and >>>>>>>. Your job is to choose the correct content and remove these markers.
5

Resolution

A resolution is your final decision about what the file should contain. You might keep one version, the other, a combination of both, or write something entirely new. Afterward, you stage and commit the result.
✦ KEY TAKEAWAY
Think of a merge conflict like two people editing the same sentence in a shared Google Doc at the same time, except the document cannot highlight both changes live. Instead, it saves both versions side-by-side and asks you, the editor, to choose the final wording. Git's conflict markers are simply the document's way of saying, "I found two versions of this section — please pick one or combine them."

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.

The file 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.

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.

Git compares both branches against the common ancestor. Since both Branch A and Branch B modified the same line, Git flags it as a conflict and requires your decision.
💡 Why not just a two-way comparison?
Without the ancestor, Git would not know who made the change. If branch A has line X and branch B has line Y, was it A that changed from Y to X, or B that changed from X to Y? The ancestor answers this question. If the ancestor also has line X, then only branch B made a change, so Git can safely use B's version — no conflict needed.

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.

The three conflict markers Git inserts into your file
MarkerMeaningWhat Follows
<<<<<<< HEADStart of conflict — marks the beginning of your current branch's versionThe lines from your branch (the branch you are currently on)
=======Divider — separates the two conflicting versionsThe lines from the incoming branch (the branch being merged in)
>>>>>>> branch-nameEnd of conflict — names the incoming branchNormal, non-conflicting code resumes after this line

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
You must remove all conflict markers (<<<<<<<, =======, >>>>>>>) 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.

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 conflictRun git status to see which files have conflicts. Git will list them under "Unmerged paths." Open greeting.py in your text editor. Look for the <<<<<<< marker to find the conflict zone.
Found conflict in greeting.py at line 4.
2
Step 2 — Read both versionsYour 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 resolutionAfter 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 fileDelete 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 commitSave the file. Run git add greeting.py to mark the conflict as resolved. Then run git commit to 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
Most modern code editors (VS Code, PyCharm, etc.) highlight conflict markers with color-coded buttons like "Accept Current Change," "Accept Incoming Change," and "Accept Both Changes." These buttons automate the deletion of markers, but you should understand what is happening under the hood so you can handle complex situations manually.

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.

Common merge conflict resolution strategies
StrategyWhen to UseRisks
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 bothBoth 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 entirelyBoth versions have problems, or the requirements have changed since both were written.Takes more time and requires full understanding of the desired behavior.
✦ KEY TAKEAWAY
Resolving a merge conflict is like being an editor reviewing two writers' drafts of the same paragraph. You do not have to pick one draft wholesale. You can take the best sentence from each, rearrange them, or rewrite the paragraph entirely. The only rule is that the final version must read cleanly — no tracked changes or editor's notes left behind (that is what leftover conflict markers are).

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.

From beginner conflict resolution to professional workflows
What You LearnedWhere It Leads
Reading conflict markers in a text editorUsing 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 mergeResolving conflicts during git rebase, which replays your commits on top of another branch one-by-one
Deciding between your code and a classmate's codeReviewing pull requests on GitHub, where conflicts are highlighted in the browser and discussed before merging
Manually editing files after a conflictWriting automated tests that run after every merge to verify the resolved code actually works

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.

Practice Problems

PROBLEM 1 — CONCEPTUAL
In your own words, explain why Git cannot automatically resolve a merge conflict. What specific condition must be true for a conflict to occur?
PROBLEM 2 — BASIC CALCULATION
Given the following conflict in a file called config.py, write what the file should look like if you accept the incoming change: <<<<<<< HEAD max_retries = 3 ======= max_retries = 5 >>>>>>> update-config
PROBLEM 3 — INTERMEDIATE
You encounter this conflict in 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.
PROBLEM 4 — APPLIED
You are working on a group project with three classmates. Two of you edited the same file (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.
PROBLEM 5 — CRITICAL THINKING
A classmate argues, "Merge conflicts are a sign that Git is broken. A better version control system would never have conflicts." Do you agree or disagree? Explain your reasoning, and suggest at least two practices that could reduce (but not eliminate) merge conflicts on a team project.

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.

Varsity Tutors • Python • Resolving Merge Conflicts — Resolve simple merge conflicts in text files (intro)