Module 05: Merge Conflicts
Learning Objectives
By the end of this module, you will:
- Understand what merge conflicts are and why they occur
- Identify merge conflicts in your repository
- Read and interpret conflict markers
- Resolve merge conflicts manually step-by-step
- Complete a merge after resolving conflicts
Challenge
Setup
Run the setup script to create your challenge environment:
.\setup.ps1
This will create a challenge/ directory with a repository that has a merge conflict waiting to happen!
Your Task
You have a repository with a main branch and a feature branch called update-config. Both branches have modified the same configuration file in different ways, creating a merge conflict.
Your mission:
- Attempt to merge the
update-configbranch intomain - Git will tell you there's a conflict - don't panic!
- Resolve the conflict by keeping BOTH settings (timeout AND debug)
- Complete the merge
Steps to follow:
- Navigate to the challenge directory:
cd challenge - Make sure you're on main:
git branch - Try to merge:
git merge update-config - Git will report a conflict!
- Open
config.pyin your text editor - Follow the step-by-step guide below to resolve it
- Save the file, stage it, and commit
What Are Merge Conflicts?
A merge conflict occurs when Git cannot automatically combine changes because both branches modified the same lines in the same file.
Example scenario:
main branch changes line 5: TIMEOUT = 30
feature branch changes line 5: DEBUG = True
Git doesn't know which one you want! So it asks you to decide.
When do conflicts happen?
- ✅ Two branches modify the same line(s)
- ✅ One branch deletes a file that another branch modifies
- ❌ Different files are changed (no conflict!)
- ❌ Different lines in the same file are changed (no conflict!)
Step-by-Step: Resolving Your First Conflict
Step 1: Attempt the Merge
cd challenge
git merge update-config
You'll see:
Auto-merging config.py
CONFLICT (content): Merge conflict in config.py
Automatic merge failed; fix conflicts and then commit the result.
Don't panic! This is normal. Git is just asking for your help.
Step 2: Check What Happened
git status
You'll see:
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: config.py
This tells you that config.py needs your attention!
Step 3: Open the Conflicted File
Open config.py in your text editor. You'll see something like this:
# config.py - Application configuration
APP_NAME = "My Application"
VERSION = "1.0.0"
<<<<<<< HEAD
TIMEOUT = 30
=======
DEBUG = True
>>>>>>> update-config
Let's break down what you're seeing:
Understanding Conflict Markers
Git has added special markers to show you both versions:
<<<<<<< HEAD ← Start of YOUR version (current branch)
TIMEOUT = 30 ← What YOU have on main
======= ← Divider between versions
DEBUG = True ← What THEY have on update-config
>>>>>>> update-config ← End of THEIR version
The three parts:
<<<<<<< HEAD- Everything between here and=======is YOUR current branch's version=======- This separates the two versions>>>>>>> update-config- Everything between=======and here is the INCOMING branch's version
Step 4: Decide What to Keep
You have three options:
Option A: Keep YOUR version (main)
# config.py - Application configuration
APP_NAME = "My Application"
VERSION = "1.0.0"
TIMEOUT = 30
Option B: Keep THEIR version (update-config)
# config.py - Application configuration
APP_NAME = "My Application"
VERSION = "1.0.0"
DEBUG = True
Option C: Keep BOTH (this is what we want!)
# config.py - Application configuration
APP_NAME = "My Application"
VERSION = "1.0.0"
TIMEOUT = 30
DEBUG = True
Step 5: Edit the File to Resolve the Conflict
What the file looks like NOW (with conflict markers):
# config.py - Application configuration
APP_NAME = "My Application"
VERSION = "1.0.0"
<<<<<<< HEAD
TIMEOUT = 30
=======
DEBUG = True
>>>>>>> update-config
What you need to do:
- Delete the line
<<<<<<< HEAD - Keep the line
TIMEOUT = 30 - Delete the line
======= - Keep the line
DEBUG = True - Delete the line
>>>>>>> update-config
What the file should look like AFTER (conflict resolved):
# config.py - Application configuration
APP_NAME = "My Application"
VERSION = "1.0.0"
TIMEOUT = 30
DEBUG = True
Save the file!
Step 6: Mark the Conflict as Resolved
Tell Git you've fixed the conflict by staging the file:
git add config.py
This tells Git: "I've resolved the conflict in this file, it's ready to be committed."
Step 7: Check Your Status
git status
You should see:
On branch main
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Changes to be committed:
modified: config.py
Great! Git knows the conflict is resolved and is ready for you to complete the merge.
Step 8: Complete the Merge
git commit
Git will open your editor with a default merge message:
Merge branch 'update-config'
# Conflicts:
# config.py
You can keep this message or customize it. Save and close the editor.
Or use a one-liner:
git commit -m "Merge update-config: resolve config conflict"
Step 9: Verify the Merge
git log --oneline --graph
You should see your merge commit!
cat config.py
Verify the file has BOTH settings and NO conflict markers!
Visual Summary: Before and After
Before Resolution (WRONG ❌)
# config.py
APP_NAME = "My Application"
VERSION = "1.0.0"
<<<<<<< HEAD
TIMEOUT = 30
=======
DEBUG = True
>>>>>>> update-config
This will NOT run! Conflict markers are syntax errors!
After Resolution (CORRECT ✅)
# config.py
APP_NAME = "My Application"
VERSION = "1.0.0"
TIMEOUT = 30
DEBUG = True
Clean code, no markers, both settings preserved!
Common Mistakes to Avoid
❌ Mistake 1: Forgetting to Remove Conflict Markers
TIMEOUT = 30
======= ← Still has conflict marker!
DEBUG = True
This is invalid Python code and will crash!
❌ Mistake 2: Committing Without Staging
# Wrong order:
git commit # Error! File not staged
# Correct order:
git add config.py # Stage first
git commit # Then commit
❌ Mistake 3: Only Keeping One Side When You Need Both
# If the task asks for BOTH settings, this is wrong:
TIMEOUT = 30
# Missing DEBUG = True
Useful Commands Reference
# During a conflict
git status # See which files have conflicts
git diff # See the conflict in detail
# Resolving
git add <file> # Mark file as resolved
git commit # Complete the merge
# If you want to start over
git merge --abort # Cancel the merge, go back to before
# After resolving
git log --oneline --graph # See the merge commit
Real-World Conflict Resolution Workflow
Here's what you'll do every time you have a conflict:
# 1. Attempt the merge
git merge feature-branch
# → Git says: "CONFLICT! Fix it!"
# 2. Check what's wrong
git status
# → Shows which files have conflicts
# 3. Open the file, find the markers
# <<<<<<< HEAD
# your version
# =======
# their version
# >>>>>>> branch
# 4. Edit the file to resolve
# Remove the markers, keep what you need
# 5. Stage the resolved file
git add config.py
# 6. Complete the merge
git commit -m "Resolve conflict in config.py"
# 7. Celebrate! 🎉
What If You Get Stuck?
Option 1: Abort the Merge
git merge --abort
This puts everything back to how it was before the merge. You can try again!
Option 2: Ask for Help
git status # See what's going on
git diff # See the conflict details
Pro Tips
✅ Use git status constantly - It tells you exactly what to do next
✅ Search for <<<<<<< - Your editor's search function can find all conflicts quickly
✅ Test after resolving - Make sure your code still works!
✅ Read both sides carefully - Sometimes you need parts from each version
✅ Take your time - Conflicts are not a race. Understand what changed and why.
Verification
Once you've resolved the conflict and completed the merge, verify your solution:
.\verify.ps1
The verification will check that:
- ✅ The merge conflict was resolved
- ✅ The merge was completed successfully
- ✅ BOTH settings are in the config file (TIMEOUT and DEBUG)
- ✅ NO conflict markers remain
- ✅ The merge commit exists in history
Need to Start Over?
If you want to reset the challenge and start fresh:
.\reset.ps1
What You've Learned
🎉 Congratulations! You can now:
- Recognize when a merge conflict occurs
- Read and understand conflict markers
- Edit files to resolve conflicts
- Stage resolved files with
git add - Complete a merge with
git commit
This is a critical skill! Every developer encounters merge conflicts. Now you know exactly what to do when they happen.
Quick Reference Card
When you see a conflict:
- Don't panic ✅
- Run
git statusto see which files - Open the file in your editor
- Find the markers (
<<<<<<<,=======,>>>>>>>) - Decide what to keep (one side, other side, or both)
- Remove ALL markers (the
<<<<<<<,=======,>>>>>>>lines) - Save the file
- Stage it (
git add filename) - Commit (
git commit) - Verify (
git status,git log --oneline --graph)
Remember: The conflict markers are NOT valid code - they MUST be removed!