How to Survive and Even Enjoy Merge Conflicts with  vimdiff

How to Survive and Even Enjoy Merge Conflicts with  vimdiff
Screenshot by me.

The Only ~10 Commands You Need to Escape Alive

The Moment of Crisis

You type:

git merge feature

Git stares back at you and mutters:

CONFLICT (content): Merge conflict in hello.txt
Automatic merge failed; fix conflicts and then commit the result.

Normally, you might open hello.txt in nano or Emacs, delete the conflict markers (<<<<<<<, =======, >>>>>>>), and patch things together. But let’s say your environment is wired to use vimdiff as the merge tool.

You sigh, mutter something unrepeatable about Vim, and type:

git mergetool

And suddenly your terminal splits into three or four panes. Welcome to vimdiff.


What You’re Looking At

  • Left pane: YOUR branch (OURS).
  • Right pane: The other branch (THEIRS).
  • Bottom (or middle): The MERGED buffer — this is the version you’ll actually commit.

The colored highlights show where the conflicts live. At first, it looks like a modern art piece. Don’t panic.


The Workflow, Step by Step

Step 1: Move Between Panes

Think of it as a tiling window manager. To move around, prefix with Ctrl-w:

  • left → Ctrl-w h
  • right → Ctrl-w l
  • down/up → Ctrl-w j / Ctrl-w k

Your main focus is the MERGED pane, because that’s where your edits live.


Step 2: Look at the Conflict

Let’s say the conflict is this line:

  • OURS says:
This line is **super important**.
  • THEIRS says:
This line is not that important, actually.

In the MERGED pane you’ll see markers if you haven’t started resolving:

<<<<<<<
This line is **super important**.
=======
This line is not that important, actually.
>>>>>>>

Step 3: Decide How to Resolve

Option A: Just Take One Side

If you like OURS, type in the MERGED pane:

:diffget LOCAL

If you prefer THEIRS:

:diffget REMOTE

Shortcut versions exist (:diffget 2, :diffget 3) depending on window order, but LOCAL/REMOTE is safer.

Option B: Edit by Hand

Sometimes neither version is quite right. That’s when you channel your inner text surgeon:

  • enter insert mode, type what you want → i
  • back to normal mode → Esc
  • delete a whole line (great for nuking those <<<<<<< markers) → dd
  • undo last action → u
  • redo → Ctrl-r

You stitch together the best of both worlds:

This line is important (and here’s why).

Step 4: Save Your Work

Once the MERGED pane looks the way you want:

:wq

Back in the shell:

git add hello.txt
git commit

Conflict resolved.


Why Use vimdiff at All?

You might be wondering: why bother with this fancy terminal acrobatics when you could just hack away in nano or Emacs?

  • Clarity: You see OURS and THEIRS side by side. Much harder to lose track.
  • Precision: With :diffget you can pull in exactly the hunk you want.
  • Speed: Once you learn the half-dozen survival commands, you’ll resolve conflicts faster than scrolling around raw conflict markers.

It’s like learning to drive stick shift: painful for the first half-hour, but then you feel a strange sense of control.


Example Sessions

To get more familiar with the usage, let's look at the usage in example sessions.

1) Manual edit: example session (step-by-step)

The conflicted file looks like this when opened (via 

git mergetool --tool=vimdiff)

Hello world!
<<<<<<< HEAD
This line is **super important**.
=======
This line is not that important, actually.
>>>>>>> feature
Goodbye.

Goal

Keep the strong phrasing, but soften it slightly, and of course remove the conflict markers.

Session flow in vimdiff

  1. Move to the MERGED buffer (usually the bottom or the leftmost pane)
  • Use window moves if needed: Ctrl-w h/j/k/l.
  1. Jump to the conflict block
  • next conflict block → ]c
  • previous conflict block → [c
  1. Enter insert mode to edit
  • Put cursor on the line you want to change.
  • enter insert mode (type normally) → i
  • Example edit: change
This line is **super important**.
  • to
This line is important (and here’s why).
  1. Delete lines you don’t want (incl. markers)
  • Press Esc (leave insert mode).
  • On a marker line like <<<<<<< HEAD, delete the whole line: dd
  • Do the same for ======= and >>>>>>> feature lines: dd on each.
  • Also delete the unwanted alternative line (e.g. “not that important”): move to it and dd.
  1. Clean up whitespace / join lines if needed
  • delete one character under cursor → x
  • join the current line with the next → J
  • undo the last change (use liberally if you slip!) → u
  • redo → Ctrl-r
  1. Save and quit
  • :wq (write + quit)
  • Back in shell: git add <file> and continue your merge/commit.

Resulting file after your manual edit:

Hello world!
This line is important (and here’s why).
Goodbye.

2) Vim manual-edit cheat sheet (merge-conflict edition)

Pane movement (vimdiff)

move between left/right/down/up panes         Ctrl-w h/l/j/k
jump to next conflict                         ]c 
jump to previous conflict                     [c

Modes

insert mode (type text)                        i
back to normal mode                            Esc

Save / quit

write (save)                                   :w
write and quit                                 :wq
quit discarding changes                        :q!

Line & text edits

delete (cut) current line                       dd
delete character under cursor                   x
replace single character with <char>            r <char>
join current line with next                     J
undo                                            u
redo                                            Ctrl-r

Copy/paste (yank/put)

yank (copy) current line                         yy
put (paste) after cursor/line                    p
put (paste) before cursor/line                   P

Search & replace (handy in conflicts)

search for next conflict start                   /<<<<<<<         
next match                                       n
previous match                                   N
remove all separators (example)                  :%s/=======//g   
remove markers (example)                         :%s/<<<<<<<\|>>>>>>>//g   

(Use the search-and-replace examples carefully; it’s often safer to edit per block.)

Selecting blocks (if you prefer visual edits)

start character-wise selection                    v
start line-wise selection                         V
delete selection                                  d
yank selection                                    y

Diff-specific quick picks (optional, if parts are fine)

take OURS for current hunk                        :diffget LOCAL   
take THEIRS for current hunk                      :diffget REMOTE  
recompute diffs after manual edits                :diffupdate

Minimal mental model

  • Get to the MERGED pane → fix the text you want → delete the conflict markers (<<<<<<<, =======, >>>>>>>) → save (:wq) → git add → continue.
  • If you mess up: undo (u) and try again.
  • Use ]c / [c to hop conflict to conflict, and dd to delete bad/marker lines.

The Minimal Cheat Sheet

Stick this on your desk until muscle memory kicks in:

move between panes                Ctrl-w h/l/j/k   
jump to next/prev conflict        ]c / [c          
take OURS (your branch)           :diffget LOCAL   
take THEIRS (incoming branch)     :diffget REMOTE  
insert mode for manual edits      i
exit insert mode                  Esc
delete current line / char        dd / x
undo / redo                       u / Ctrl-r
save / save + quit / quit         :w / :wq / :q!

When to Actually Use It

Use vimdiff when:

  • Both sides rewrote the same code and you need to carefully compare.
  • You’re tired of juggling conflict markers by hand.
  • You want a quick, reliable way to choose OURS or THEIRS without mistakes.

If it’s just a trivial conflict, nano or Emacs is fine. But if the conflict is messy — vimdiff is your best terminal-only scalpel.


And there you are. An Emacs user, forced into Vim, who walks out not only alive but victorious. You may never love Vim, but the next time Git drags you into vimdiff, you’ll know exactly what to do — calmly, directly, efficiently.


vimdiff Merge Conflict Survival Card

Explanation

Command

!

Launch vimdiff merge after conflict

git mergetool --tool=vimdiff

Start here

Move to left / right / up / down window

Ctrl-w h / l / k / j

Navigate panes

Jump to next / previous conflict

]c / [c

Quick conflict travel

Take OURS (your branch)

:diffget LOCAL

Keep your version

Take THEIRS (incoming branch)

:diffget REMOTE

Keep their version

Take left / right pane explicitly

:diffget 2 / :diffget 3

If LOCAL/REMOTE unclear

Enter insert mode (manual edit)

i

Start typing

Exit insert mode

Esc

Return to normal mode

Delete current line

dd

Remove markers or unwanted lines

Delete character under cursor

x

Fine-grained cleanup

Undo last change

u

Safety net

Redo undone change

Ctrl-r

Double safety

Join current line with next

J

Merge lines

Yank (copy) current line

yy

Copy text

Paste after cursor

p

Paste text

Save changes

:w

Write buffer

Save and quit

:wq

Done editing

Quit without saving

:q!

Abort changes

Recompute diffs after edits

:diffupdate

Refresh highlighting


With just this card, you can walk into a vimdiff conflict cold and walk out with a clean merge.

Do you like this kind of thinking?

Follow me on Medium: 
@gwangjinkim for deep dives on Python, Lisp, system design, and developer thinking, and much more

- Subscribe on Substack
gwangjinkim.substack.com — coming soon with early essays, experiments & newsletters (just getting started).

- Visit my Ghost blog (here)
everyhub.org — with hands-on tech tutorials and tools (most of them I cross-post here in medium, but not all of them).

Follow anywhere that fits your style — or all three if you want front-row seats to what’s coming next.