Merge Conflicts

Listen to Episode 7: Merge Conflicts Are Not Scary - a conversational audio overview of this chapter. Listen before reading to preview the concepts, or after to reinforce what you learned.

Understanding, Preventing, and Resolving Conflicts

Merge conflicts sound intimidating but are a normal, manageable part of collaborative development. This guide explains what conflicts are, how to read conflict markers, and how to resolve them - step by step.

Workshop Recommendation (Chapter 7)

Chapter 7 uses one controlled practice challenge so students can learn conflict resolution without high-pressure scenarios.

Chapter 7 Challenge Set

  1. Resolve conflict markers - identify and clean up conflict markers in a practice file, then open a linked PR.

Branch guidance for Chapter 7: Use a short-lived feature branch: fix/yourname-issueXX (for example, fix/maria-issue48). The same pattern you used in Chapter 6.

Challenge 7.1 Step-by-Step: Resolve Conflict Markers

Goal: Identify the three types of conflict markers in a practice file, decide which content to keep, remove the markers, and submit a clean PR.

Where you are working: the learning-room repository on GitHub.com (web editor) or in VS Code if you cloned locally.

Before you start: Open your assigned Chapter 7 challenge issue (the one titled "Chapter 7.1: Resolve Conflict Markers (@yourname)"). The issue description tells you which practice file contains the conflict markers.

Practice sample: learning-room/docs/samples/chapter-6-conflict-practice-sample.md

  1. Open the practice file specified in your challenge issue.
  2. Search the file for <<<<<<<. This is the start marker - it shows where the conflict begins.
  3. Read the content between <<<<<<< and =======. This is your version (the current branch).
  4. Read the content between ======= and >>>>>>>. This is their version (the incoming branch).
  5. Decide which content to keep:
    • Keep only your version, or
    • Keep only their version, or
    • Combine both versions into one clean paragraph.
  6. Delete all three marker lines:
    • The <<<<<<< HEAD line (or similar)
    • The ======= separator line
    • The >>>>>>> branch-name line
  7. Review the file to confirm no marker lines remain. Search for <<<<<<< again - there should be zero results.
  8. Commit your changes on a branch named fix/yourname-issueXX.
  9. Open a pull request with:
    • Title: fix: resolve conflict markers in [filename]
    • Body: Include Closes #XX (your challenge issue number) and a 1-2 sentence description of which content you kept and why.

Screen reader tip: Use your screen reader's find command (Ctrl+F in browser, Ctrl+H in VS Code) to jump directly to <<<<<<<. The markers are plain text, so they are fully readable.

You are done when: Your PR passes bot validation checks and contains no remaining conflict markers.

Completing Chapter 7: Submit Your Evidence

When your PR is open and passing checks, post a comment on your assigned Chapter 7 challenge issue:

Chapter 7 completed:
- Challenge 7.1: Opened PR #[number] resolving conflict markers in [filename]
- Content decision: kept [your version / their version / combined both] because [reason]

Expected Outcomes

If You Get Stuck

  1. Can't find the markers? Use Ctrl+F and search for <<<<<<< - they are always in sets of three.
  2. Not sure which side to keep? Read both versions aloud. Pick the one that is clearer, or combine them.
  3. Accidentally deleted too much? Undo with Ctrl+Z and start the section over.
  4. PR bot says content is wrong? Double-check that zero marker lines remain - search for <<<<<<<, =======, and >>>>>>>.
  5. Ask facilitator to sanity-check your final content before opening the PR.

Learning Moment

Merge conflicts are not failures. They are a normal collaboration checkpoint and a chance to make an intentional content decision. In real open source projects, conflicts happen whenever two people edit near the same lines. The skill is not avoiding them - it is resolving them calmly and clearly.

Learning Pattern Used in This Chapter

  1. Start with a controlled, safe conflict (practice file with known markers).
  2. Learn to read the conflict structure (your version vs. their version).
  3. Make a deliberate content decision (not just deleting randomly).
  4. Submit clean evidence through the PR workflow.
  5. Build confidence for real conflicts in future contributions.

About Learning Cards in This Chapter

This chapter provides learning cards: expandable blocks that offer perspective-specific guidance for different ways of working. Not every card appears at every step. Open the ones that match how you work.

The following table describes the five learning card types used in this chapter.

Card Who it helps What it covers
Visual / mouse Sighted users navigating with a mouse or trackpad Click targets, visual cues, color-coded conflict regions
Low vision Users with magnification, zoom, or high-contrast themes Zoom-friendly navigation, high contrast marker visibility, enlargement tips
NVDA / JAWS (Windows) Screen reader users on Windows Keystroke sequences, Focus and Browse mode, verbosity tips
VoiceOver (macOS) Screen reader users on macOS VO key sequences, rotor navigation, interaction model
CLI (git / gh) Terminal users on any platform Git and GitHub CLI commands for conflict detection and resolution

Local Git Alternative: Resolving Conflicts from Your Terminal

If you cloned the learning-room in Block 0 and prefer resolving conflicts locally

The GitHub web conflict editor works well and is the primary method taught in this chapter. If you cloned the Learning Room in Block 0 and prefer working in your terminal, here is how to resolve conflicts locally. This is the same workflow covered in depth in Chapter 11: Git and Source Control.

Step 1 - Sync main and merge into your branch:

cd ~/Documents/learning-room
git checkout main
git pull origin main
git checkout your-branch-name
git merge main

If there is a conflict, Git will report which files are affected and stop the merge.

Step 2 - Open the conflicted file:

code docs/welcome.md   # or your preferred editor

Look for the conflict markers:

<<<<<<< HEAD
Your version of the content
=======
The incoming version from main
>>>>>>> main

Step 3 - Resolve by editing:

Step 4 - Mark resolved, commit, and push:

git add docs/welcome.md
git commit -m "Resolve merge conflict in welcome.md"
git push

Your PR on GitHub updates automatically with the resolved content. The same bot checks and human review process apply.

What Is a Merge Conflict?

A merge conflict occurs when two people have both changed the same part of the same file in different ways, and Git cannot automatically decide which version is correct.

Git can merge changes automatically when they touch different parts of a file. Conflicts only happen when two changes overlap - for example:

Why Conflicts Happen

The most common causes:

Cause Example
Two people edited the same line You both fixed the same typo differently
One person deleted a file but another edited it You removed an old function; they fixed a bug in it
Two people restructured the same section You reorganized a list; they added items to it
A long-running PR diverged from main Your branch is weeks old and main has changed significantly

How to Prevent Conflicts (Prevention is Easier Than Resolution)

Avoiding conflicts in the first place saves time and reduces stress. Here are the most effective strategies:

1. Keep your branches short-lived

Work in small, focused chunks. A branch that lives for 3 days has far fewer conflicts than one that lives for 3 weeks.

2. Sync with main frequently

The longer your branch diverges from main, the more likely conflicts become.

Best practice: Sync daily if main is active:

# From your feature branch
git fetch origin
git merge origin/main
# Or: git rebase origin/main (if comfortable with rebasing)

GitHub web method: Use the "Update branch" button on your PR if it appears.

3. Communicate with your team

Let others know what files you're working on. Use issue comments:

"Heads up: I'm working on the [TODO] sections in docs/welcome.md for Challenge 3. If you're also editing welcome.md, let's coordinate so we don't conflict."

In the Learning Room, this is especially important because multiple students may claim challenges that touch the same file. Challenges 1 and 3 both modify docs/welcome.md - if two students work on both simultaneously without coordinating, a merge conflict will occur.

4. Avoid mass reformatting

Running a formatter on an entire file creates conflicts with anyone else editing that file. If you must:

5. Pull before you push

Always fetch and merge (or pull) before pushing your changes:

git pull origin main  # Sync your local main
git checkout your-branch
git merge main        # Merge main into your branch
git push              # Now push

This catches conflicts locally where they're easier to resolve.

6. Work on separate files when possible

If multiple people are working simultaneously, divide tasks by files or modules rather than everyone touching the same code.

7. Keep PRs small

A 50-file PR will almost certainly conflict with something. A 5-file PR merges quickly and cleanly.

The most effective contributors make many small PRs rather than one giant one.

8. Use Draft PRs for early visibility

Open your PR as a draft while still working. Others can see what you're changing and avoid overlapping work. Convert to "Ready for review" when done.

Advanced Prevention: Understanding Fast-Forward Merges

When your branch is perfectly up to date with main and adds new commits on top, GitHub can do a "fast-forward" merge - main simply moves forward to your latest commit. No merge commit needed. No possibility of conflicts.

How to achieve this: Rebase your branch on main right before merging:

git checkout your-branch
git fetch origin
git rebase origin/main
git push --force-with-lease  # See warning below about force pushing

Warning: Force pushing rewrites history. Only do this on branches you alone control (not shared branches). Never force push to main.

For more on force pushing and rebasing, see the Glossary.

When Conflicts Are Actually Good

Conflicts indicate that multiple people are actively improving the project. In a healthy, collaborative environment, occasional conflicts are normal and manageable.

If you never have conflicts, it might mean:

The goal isn't zero conflicts. The goal is catching them early, resolving them cleanly, and learning patterns that reduce future conflicts.

Spotting a Conflict on GitHub

When a PR has a merge conflict, you will see this message on the Conversation tab, near the merge section:

“This branch has conflicts that must be resolved”

You will also see a “Resolve conflicts” button. If you cannot see it (it may require write access), contact the PR author.

Visual / mouse users

Scroll to the bottom of the Conversation tab. The conflict message appears as a yellow or orange banner above the merge button area. Click Resolve conflicts to open the web conflict editor.

Low vision users (zoom, high contrast)

The conflict banner sits near the bottom of the Conversation tab, above the merge button area. If your browser zoom is at 200% or higher, you may need to scroll past lengthy comment threads to reach it.

Screen reader users (NVDA / JAWS - Windows)
  1. Press D to reach the bottom of the Conversation tab
  2. Navigate down with H or past the comment threads
  3. Find the heading or region containing "This branch has conflicts"
  4. Press B to find the Resolve conflicts button → Enter
Screen reader users (VoiceOver - macOS)
  1. VO+U → Landmarks or VO+Down to move toward the bottom of the Conversation tab
  2. Quick Nav H or VO+Cmd+H past comment headings until you reach the conflict notice
  3. Quick Nav B to find the Resolve conflicts button → VO+Space

Conflict Markers - What They Mean

When conflict markers appear in a file, your editor is showing you both versions of the conflicted content so you can choose. The format is always:

<<<<<<< HEAD
The content that is on YOUR current branch
=======
The content coming from the OTHER branch (or main)
>>>>>>> branch-name-or-commit-hash

Breakdown

Example in a real file

Original file (docs/keyboard-shortcuts.md) before conflict

| Insert+Space | Toggle between Browse Mode and Focus Mode |

After two students both added a shortcut to the same table row

<<<<<<< HEAD
  Insert+Space -- Toggle between Browse Mode and Focus Mode
  Insert+F5 -- List elements by type
=======
  Insert+Space -- Toggle between Browse Mode and Focus Mode
  Insert+F7 -- Elements list (links, headings, form fields)
>>>>>>> add-nvda-shortcut

Resolution options

  1. Keep your version: add only Insert+F5
  2. Keep their version: add only Insert+F7
  3. Keep both rows: add both shortcuts to the table (often the right answer when two students added different valid shortcuts)

Resolving Conflicts on GitHub (Web Editor)

GitHub has a built-in conflict editor that you can use without any local tools.

Step-by-step: GitHub Conflict Editor

Visual / mouse users
  1. Click Resolve conflicts on the PR Conversation tab
  2. GitHub opens a full-page text editor showing each conflicted file
  3. The conflict markers are highlighted - everything between <<<<<< and ======= is your version; between ======= and >>>>>>> is the incoming version
  4. Edit the content directly: delete the lines you don’t want, including the three marker lines (<<<, ===, >>>)
  5. When the file looks correct, click Mark as resolved (top-right of the file)
  6. If there are multiple conflicted files, a file list on the left lets you jump between them
  7. After all files are resolved, click Commit merge
Low vision users (zoom, high contrast)
  1. Open the conflict editor from the Resolve conflicts button on the PR Conversation tab.
  2. GitHub opens a monospace text editor. At 200% zoom or higher, the editor scrolls horizontally. Use Shift+Scroll or horizontal scrollbar to navigate wide lines.
  3. Conflict markers (<<<<<<<, =======, >>>>>>>) are displayed in highlighted bands. In high-contrast themes, the markers use distinct system colors for good visibility.
  4. The file list panel (left side) may collapse at high zoom levels. Look for a toggle or hamburger icon in the top-left corner to reopen it.
  5. Edit directly in the editor: delete unwanted lines, including all three marker lines.
  6. Click Mark as resolved in the top-right. At high zoom, this button may require horizontal scrolling to find. You can also Tab to reach it.
  7. After all files are resolved, click Commit merge.

Tip: Increase your browser's minimum font size (Settings, Appearance, Font size) for a more comfortable editing experience in the conflict editor. This setting persists across GitHub pages.

Screen reader users (NVDA / JAWS - Windows)
  1. Activate the Resolve conflicts button from the PR Conversation tab
  2. GitHub opens the conflict editor - a full-page text editor
  3. Navigate between conflicted files using the file list (press NVDA+F7 or VO+U to find the file navigation panel)
  4. Switch to Focus Mode (NVDA+Space) to enter the text editor
  5. Read the conflict markers line by line with :
    • <<<<<<< HEAD marks the start of your version
    • ======= is the dividing line
    • >>>>>>> branch-name marks the end of the incoming version
  6. Edit to keep the desired content - delete the conflict marker lines and the version you don't want
  7. Tab to Mark as resolved button → Enter
  8. Repeat for all conflicted files
  9. Tab to Commit merge button → Enter
Screen reader users (VoiceOver - macOS)
  1. Activate the Resolve conflicts button from the PR Conversation tab
  2. GitHub opens the conflict editor - a full-page text editor
  3. VO+U → navigate to the file navigation panel to switch between conflicted files
  4. VO+Shift+Down to interact with the text editor
  5. VO+Down to read the conflict markers line by line:
    • <<<<<<< HEAD marks the start of your version
    • ======= is the dividing line
    • >>>>>>> branch-name marks the end of the incoming version
  6. Edit to keep the desired content - delete the conflict marker lines and the version you don't want
  7. VO+Shift+Up to stop interacting, then Tab to Mark as resolvedVO+Space
  8. Repeat for all conflicted files
  9. Tab to Commit mergeVO+Space

What it looks like in the editor

When the conflict editor opens, your screen reader will announce a text editor. In Focus Mode, navigate with arrow keys. The content reads:

<  <  <  <  <  <  <  H  E  A  D
<button aria-label="Submit form">Submit</button>
=  =  =  =  =  =  =
<button type="submit">Send message</button>
>  >  >  >  >  >  >  f  e  a  t  u  r  e  /  f  o  r  m - i  m  p  r  o  v  e  m  e  n  t  s

(Note: screen readers may spell out the < and > characters letter by letter - this is normal)

Resolving Conflicts in VS Code (Day 2)

VS Code has excellent merge conflict tooling with full screen reader support. This is covered in depth in Git & Source Control in VS Code, but here is an overview:

VS Code shows conflicts as

<<<<<<< HEAD (Current Change)
Your version
======= original                   -- (3-way merge, if enabled)
Original version before both edits
=======
Incoming version
>>>>>>> branch-name (Incoming Change)

VS Code merge conflict actions

Visual / mouse users

When your cursor is on a conflict region, VS Code shows CodeLens action links above the conflict block in the editor:

Click the link you want. The conflict markers disappear and your chosen content remains. Save the file with Ctrl+S.

Low vision users (zoom, high contrast)

VS Code highlights conflict regions with colored background bands:

In high-contrast themes, these colors map to system theme colors that remain distinguishable. The CodeLens action links (Accept Current Change, Accept Incoming Change, Accept Both Changes, Compare Changes) appear as small text links above the conflict block.

Tips for comfort at high zoom:

Screen reader users (NVDA / JAWS - Windows)
  1. Open the conflicted file
  2. Press to navigate to a conflict marker (<<<<<<<)
  3. The CodeLens links appear above - press Tab to reach them
  4. Press Enter on your chosen action
  5. Save the file (Ctrl+S)
  6. Stage the resolved file: Ctrl+Shift+G → find the file → Stage changes
  7. Commit the merge

GitHub Copilot can help: With the cursor in a conflict region, open Copilot Chat (Ctrl+Shift+I) and type: "Resolve this merge conflict - keep meaningful changes from both sides." Copilot will suggest a resolution that you can review and accept.

Screen reader users (VoiceOver - macOS)
  1. Open the conflicted file
  2. VO+Down or arrow keys to navigate to a conflict marker (<<<<<<<)
  3. The CodeLens links appear above - Tab to reach them
  4. VO+Space on your chosen action
  5. Save the file (Cmd+S)
  6. Stage the resolved file: Cmd+Shift+G → find the file → Stage changes
  7. Commit the merge

GitHub Copilot can help: With the cursor in a conflict region, open Copilot Chat (Cmd+Option+I) and type: "Resolve this merge conflict - keep meaningful changes from both sides." Copilot will suggest a resolution that you can review and accept.

When You Feel Stuck

Ask for help - it's normal

If you are unsure which version to keep:

  1. Leave a comment on the PR: "I have a merge conflict in filename.js and I'm not sure which version to keep - could someone help me understand the intent of these two changes?"
  2. Tag the PR author or a maintainer with @username

Abandon and start fresh (nuclear option)

If a conflict is severe (the branch diverged a lot from main):

  1. Close the PR without merging
  2. Start a new branch from the latest main
  3. Apply only your intended changes to the new branch
  4. Open a new PR

This is legitimate - not a failure.

Reading a Conflict Message from Git (Command Line Reference)

If you work locally, git merge or git pull will say:

CONFLICT (content): Merge conflict in src/index.html
Automatic merge failed; fix conflicts and then commit the result.

And git status will show:

both modified: src/index.html

These are normal outputs. The conflict markers are inserted into the file by Git - open the file and follow the steps above.

Git CLI alternative - resolving conflicts in the terminal

Resolve merge conflicts entirely from the command line:

# 1. Start the merge that causes the conflict
git merge main

# 2. See which files have conflicts
git status
# Look for "both modified:" entries

# 3. Open each conflicted file in your editor
# Edit the file: remove <<<<<<, =======, >>>>>> markers
# Keep the content you want

# 4. After editing, mark the file as resolved
git add src/index.html

# 5. Complete the merge
git commit
# Git auto-fills the merge commit message

# Check the result
git log --oneline -3
GitHub CLI (gh) alternative - checking PR conflict status

Check whether a PR has conflicts without opening a browser:

# View PR status (shows merge state)
gh pr view 42

# Check all PR checks and merge readiness
gh pr checks 42

# View the diff to understand what changed
gh pr diff 42

If conflicts exist, the gh pr view output shows "This branch has conflicts that must be resolved." Resolve locally using git merge (above) then push, or use the web editor.

Summary Checklist

Before you start:
  □ My PR is small and focused (fewer conflicts = easier life)
  □ I checked that others aren't editing the same files

When you see a conflict:
  □ Don't panic - conflicts are normal
  □ Read both versions (between <<< and ===, and between === and >>>)
  □ Decide: keep one, keep both, or combine intelligently
  □ Remove ALL three conflict marker lines (<<<, ===, >>>)
  □ Verify the final file makes sense
  □ Mark as resolved → Commit merge

After resolving:
  □ Re-check that the PR description and issue link are still accurate
  □ Comment on the PR: "Resolved merge conflict - kept both the aria-label and type attribute"
  □ Request re-review if reviewers already approved before the conflict was introduced

Try It: Read a Conflict (Without Fear)

Time: 2 minutes | What you need: Any text editor or just read below

Read this merge conflict aloud. The goal is not to resolve it - just to understand what you're hearing:

The button should have an
<<<<<<< HEAD
aria-label="Submit form"
=======
aria-label="Send your response"
>>>>>>> feature-branch
attribute for screen readers.

Answer these three questions:

  1. What does your branch say? (The text between <<<<<<< HEAD and =======)
  2. What does the other branch say? (The text between ======= and >>>>>>>)
  3. Which version would you keep, and why?

You're done. You just read a merge conflict. That's the entire skill - everything else is just choosing which lines to keep and deleting the three marker lines.

What success feels like: Conflicts aren't mysterious anymore. They're just two versions side by side with markers telling you which is which. You already know how to pick the right one.

Day 2 Amplifier - Copilot Chat & Conflict Prevention

Resolve at least one conflict completely by hand before using any AI assistance. You must be able to read <<<<<<<, =======, and >>>>>>> markers and understand what each version represents. An AI-suggested resolution you cannot independently verify is a liability - you are accepting a change you do not understand into a codebase other people depend on.

Once you have mastered manual conflict resolution:

Understanding conflict markers is not a stepping stone to letting AI handle conflicts. It is the skill that tells you when AI got it wrong.

Next: Culture and Etiquette Back: Working with Pull Requests Related: Git & Source Control in VS Code