Skip to main content

Managing Merge Conflicts

A comprehensive guide to understanding, resolving, and preventing merge conflicts in Git.


What is a Merge Conflict?

┌─────────────────────────────────────────────────────────────────────────────┐
│ WHAT IS A MERGE CONFLICT? │
└─────────────────────────────────────────────────────────────────────────────┘

A merge conflict occurs when Git cannot automatically combine changes
because TWO PEOPLE modified the SAME LINES in the SAME FILE.

EXAMPLE SCENARIO:
─────────────────

Original file (in develop):
┌────────────────────────────────────┐
│ const taxRate = 0.10; │ ← Line 5
└────────────────────────────────────┘

Developer A (feature/tax-update): Developer B (feature/tax-fix):
┌────────────────────────────────────┐ ┌────────────────────────────────────┐
│ const taxRate = 0.11; │ │ const taxRate = 0.12; │
└────────────────────────────────────┘ └────────────────────────────────────┘

When Developer B tries to merge after Developer A:

┌────────────────────────────────────────────────────────────────────────┐
│ ⚠️ CONFLICT! Git doesn't know which value to use: 0.11 or 0.12? │
└────────────────────────────────────────────────────────────────────────┘

Understanding Conflict Markers

When a conflict occurs, Git marks the conflicting section in your file:

<<<<<<< HEAD
const taxRate = 0.11; // Your current branch changes
=======
const taxRate = 0.12; // Incoming changes from the branch you're merging
>>>>>>> feature/tax-fix

Breakdown:

┌─────────────────────────────────────────────────────────────────────────────┐
│ <<<<<<< HEAD │
│ ───────────────────────────────────────────────────────────────────────── │
│ This marks the START of the conflict │
│ "HEAD" = your current branch (the branch you're ON) │
├─────────────────────────────────────────────────────────────────────────────┤
│ const taxRate = 0.11; │
│ ───────────────────────────────────────────────────────────────────────── │
│ This is YOUR code (current branch) │
├─────────────────────────────────────────────────────────────────────────────┤
│ ======= │
│ ───────────────────────────────────────────────────────────────────────── │
│ This separates the two versions │
├─────────────────────────────────────────────────────────────────────────────┤
│ const taxRate = 0.12; │
│ ───────────────────────────────────────────────────────────────────────── │
│ This is THEIR code (incoming branch) │
├─────────────────────────────────────────────────────────────────────────────┤
│ >>>>>>> feature/tax-fix │
│ ───────────────────────────────────────────────────────────────────────── │
│ This marks the END of the conflict │
│ Shows the name of the incoming branch │
└─────────────────────────────────────────────────────────────────────────────┘

How to Resolve Conflicts (Step-by-Step)

┌─────────────────────────────────────────────────────────────────────────────┐
│ CONFLICT RESOLUTION WORKFLOW │
└─────────────────────────────────────────────────────────────────────────────┘

┌──────────────────┐
│ CONFLICT OCCURS │
│ during merge/ │
│ pull/rebase │
└────────┬─────────┘


┌──────────────────┐
│ 1. DON'T PANIC! │
│ Run: git status│
│ See conflicting│
│ files │
└────────┬─────────┘


┌──────────────────┐
│ 2. OPEN file in │
│ VSCode │
│ Look for <<<< │
│ markers │
└────────┬─────────┘


┌──────────────────┐
│ 3. DECIDE which │
│ code to keep │
│ (or combine) │
└────────┬─────────┘


┌──────────────────┐
│ 4. EDIT file to │
│ remove markers│
│ keep correct │
│ code │
└────────┬─────────┘


┌──────────────────┐
│ 5. TEST that the │
│ code works │
└────────┬─────────┘


┌──────────────────┐
│ 6. STAGE the file│
│ git add <file>│
└────────┬─────────┘


┌──────────────────┐
│ 7. COMMIT │
│ git commit │
│ (or continue │
│ merge/rebase) │
└────────┬─────────┘


┌──────────────────┐
│ DONE! │
└──────────────────┘

Practical Example: Resolving a Conflict

Scenario: You're merging develop into your feature branch

Step 1: Attempt the merge

git checkout feature/my-feature
git merge develop

# Output:
# Auto-merging src/FileCabinet/SuiteScripts/vendor_invoice.js
# CONFLICT (content): Merge conflict in src/FileCabinet/SuiteScripts/vendor_invoice.js
# Automatic merge failed; fix conflicts and then commit the result.

Step 2: Check which files have conflicts

git status

# Output:
# On branch feature/my-feature
# You have unmerged paths.
#
# Unmerged paths:
# (use "git add <file>..." to mark resolution)
# both modified: src/FileCabinet/SuiteScripts/vendor_invoice.js

Step 3: Open the file in VSCode

VSCode will highlight conflicts with colors:

  • Green = Your changes (Current)
  • Blue = Incoming changes

You'll see buttons above the conflict:

┌────────────────────────────────────────────────────────────────────────────┐
│ [Accept Current Change] [Accept Incoming Change] [Accept Both] [Compare] │
├────────────────────────────────────────────────────────────────────────────┤
│ <<<<<<< HEAD │
│ const taxRate = 0.11; │
│ const taxName = 'PPN 11%'; │
│ ======= │
│ const taxRate = 0.12; │
│ >>>>>>> develop │
└────────────────────────────────────────────────────────────────────────────┘

Step 4: Choose resolution strategy

Option A: Accept Current Change (keep your version)

const taxRate = 0.11;
const taxName = 'PPN 11%';

Option B: Accept Incoming Change (use their version)

const taxRate = 0.12;

Option C: Accept Both Changes (combine both)

const taxRate = 0.11;
const taxName = 'PPN 11%';
const taxRate = 0.12; // This would cause an error - don't blindly accept both!

Option D: Manual Edit (write custom solution)

// Decided with team: use new tax rate but keep the name
const taxRate = 0.12;
const taxName = 'PPN 12%';

Step 5: Remove ALL conflict markers

Make sure no <<<<<<<, =======, or >>>>>>> remain in the file!

// WRONG - still has markers:
<<<<<<< HEAD
const taxRate = 0.11;
=======
const taxRate = 0.12;
>>>>>>> develop

// CORRECT - clean code:
const taxRate = 0.12;
const taxName = 'PPN 12%';

Step 6: Test the code

# Validate with SDF
Ctrl+Shift+P → SuiteCloud: Validate Project

# Make sure there are no syntax errors

Step 7: Stage and commit

# Stage the resolved file
git add src/FileCabinet/SuiteScripts/vendor_invoice.js

# Complete the merge
git commit -m "Merge develop into feature/my-feature

Resolved conflict in vendor_invoice.js:
- Used new tax rate 0.12 from develop
- Kept taxName variable from feature branch"

Using VSCode Merge Editor (3-Way Merge)

VSCode has a powerful built-in merge editor:

┌─────────────────────────────────────────────────────────────────────────────┐
│ VSCode 3-Way Merge Editor │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ INCOMING (theirs) │ │ CURRENT (yours) │ │
│ │ │ │ │ │
│ │ const taxRate = 0.12│ │ const taxRate = 0.11│ │
│ │ │ │ const taxName = ... │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────┐ │
│ │ RESULT │ │
│ │ │ │
│ │ const taxRate = ??? ← You decide what goes here │ │
│ │ │ │
│ └───────────────────────────────────────────────────┘ │
│ │
│ [Accept Incoming] [Accept Current] [Accept Combination] [Complete Merge] │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

To open the Merge Editor:

  1. Click on a conflicted file in Source Control panel
  2. Click "Resolve in Merge Editor" button
  3. Use checkboxes to select which changes to include
  4. Click "Complete Merge" when done

Conflict Resolution by Scenario

Feature Development Conflicts

When it happens: Merging develop into your feature branch before PR

# Before creating PR, always sync with develop
git checkout feature/my-feature
git fetch origin
git merge origin/develop

# If conflicts occur:
# - Usually in files you both modified
# - Often in shared libraries or configs

Best Practice:

┌─────────────────────────────────────────────────────────────────────────────┐
│ FEATURE BRANCH: Sync with develop FREQUENTLY │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ develop ──●───────●───────●───────●───────●───────●──────► │
│ │ ▲ ▲ ▲ ▲ │ │
│ │ │ │ │ │ │ │
│ feature └───●───┴───●───┴───●───┴───●───┴───●───┘ │
│ │ │ │ │ │ │
│ merge merge merge merge merge │
│ develop develop develop develop (PR) │
│ │
│ ✓ Small, frequent merges = Small, easy conflicts │
│ ✗ One big merge at the end = Big, complex conflicts │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

Common Conflict Files in SDF:

File TypeWhy Conflicts OccurResolution Tip
manifest.xmlMultiple scripts addedInclude all dependencies
Custom Records XMLMultiple field additionsMerge all new fields
Shared LibrariesDifferent utility functionsKeep both functions
Config filesDifferent settingsDiscuss with team

Bugfix Conflicts

When it happens: Your bugfix touches code that changed in develop

git checkout bugfix/my-fix
git merge origin/develop

# Conflict likely in:
# - The file you're fixing
# - Related test files

Resolution Strategy:

  1. Understand both changes - What did develop add? What is your fix?
  2. Apply your fix to their code - Usually you need to re-apply your fix to the new code
  3. Test thoroughly - Make sure both the new feature AND your fix work

Example:

// CONFLICT: You fixed a bug, but they refactored the function

// Their version (develop):
function calculateTax(amount, rate) {
// They refactored to use new parameter
return amount * rate;
}

// Your version (bugfix):
function calculateTax(amount) {
// You fixed the null check
if (!amount) return 0;
return amount * TAX_RATE;
}

// RESOLUTION: Apply your fix to their refactored code
function calculateTax(amount, rate) {
if (!amount) return 0; // Your fix
return amount * rate; // Their refactor
}

Hotfix Conflicts

When it happens: Syncing hotfix back to develop

# After merging hotfix to main
git checkout develop
git merge main # Sync the hotfix

# Conflict if develop has diverged significantly

Resolution Strategy:

  1. Hotfix code takes priority - The fix is critical and tested
  2. Carefully integrate - Make sure develop's changes don't break the fix
  3. Test in sandbox - Deploy develop to sandbox and verify fix still works

Preventing Merge Conflicts

┌─────────────────────────────────────────────────────────────────────────────┐
│ CONFLICT PREVENTION BEST PRACTICES │
└─────────────────────────────────────────────────────────────────────────────┘

1. COMMUNICATE WITH YOUR TEAM
─────────────────────────────
"Hey, I'm working on vendor_invoice.js today"
→ Others avoid modifying the same file

2. PULL/MERGE FREQUENTLY
─────────────────────────────
git fetch origin
git merge origin/develop
→ Do this at least daily on long-running branches

3. KEEP BRANCHES SHORT-LIVED
─────────────────────────────
Feature branches: 1-3 days ideal, max 1 week
→ Less time = less divergence = fewer conflicts

4. MAKE SMALL, FOCUSED COMMITS
─────────────────────────────
One change per commit
→ Easier to identify and resolve conflicts

5. AVOID REFORMATTING CODE
─────────────────────────────
Don't change indentation/formatting in files you're not modifying
→ Formatting changes cause unnecessary conflicts

6. USE SEPARATE FILES WHEN POSSIBLE
─────────────────────────────
New functionality? Create a new file instead of adding to existing
→ Different files = no conflicts

Commands Reference

CommandDescription
git statusSee which files have conflicts
git diffSee the conflict details
git checkout --ours <file>Keep your version entirely
git checkout --theirs <file>Keep their version entirely
git add <file>Mark conflict as resolved
git merge --abortCancel the merge and go back
git reset --hard HEADAbandon all changes (use carefully!)

When to Ask for Help

Get Help When:
  • You're not sure which code is correct
  • The conflict involves code you don't understand
  • Multiple files have complex conflicts
  • You've been stuck for more than 15 minutes
  • The conflict involves critical business logic

Who to ask:

  1. The person who wrote the conflicting code (check git blame)
  2. Your IT Lead
  3. Senior team member

Troubleshooting Common Issues

"I accidentally committed with conflict markers"

# Fix: Amend the commit
# 1. Fix the file (remove markers)
# 2. Stage the fix
git add <file>
# 3. Amend the commit
git commit --amend

"I want to start over"

# Abort the current merge
git merge --abort

# You're back to before the merge
# Try again when ready

"I accepted the wrong changes"

# If you haven't committed yet:
git checkout --conflict=merge <file>
# This restores the conflict markers so you can try again

# If you already committed:
git revert HEAD
# Then redo the merge

"Too many conflicts, this is overwhelming"

# Option 1: Abort and get help
git merge --abort

# Option 2: Resolve one file at a time
git status # List all conflicted files
# Fix one file
git add <file>
# Repeat for each file
# Finally commit when all resolved