Configuring git mergetool for three-way resolution Jump to heading

Resolving a large conflict in a text editor means scrolling between marker sections and holding three versions in your head. A merge tool lays them out side by side β€” ours, the base, theirs β€” with the result below, so you can see each side’s change against the ancestor and pick or combine hunks with a click. git mergetool launches one for each conflicted file, but out of the box it often picks a tool nobody has installed, leaves .orig backup files everywhere, and opens a two-pane view that hides the base. This page configures it properly for the editors teams actually use, and explains when it is worth reaching for. It belongs to 3-way merge fundamentals.

When to use this approach Jump to heading

  • Conflicts regularly span dozens of lines or several hunks in one file.
  • You resolve conflicts in files where structure matters β€” nested configuration, long functions.
  • Team members use different editors and want a consistent way to launch resolution.
  • For short conflicts, reading markers directly is faster; set up diff3 and zdiff3 conflict markers first either way.

Step 1 β€” Pick a tool that shows the base Jump to heading

The tool must show the merge base as its own pane, or most of the benefit is lost. Tools differ in layout; the important thing is three inputs plus a result.

The four-pane layout of a three-way merge toolA three-way merge tool shows the local version, the base and the remote version across the top, and the result being edited at the bottom. Seeing the base next to each side is what lets you tell which side changed a line.LOCALours$LOCALBASEcommon ancestor$BASEREMOTEtheirs$REMOTEMERGEDthe result$MERGEDthe four variables are what git mergetool passes to any tool you configure
# See which tools Git knows how to drive and which are installed
git mergetool --tool-help | sed -n '1,25p'

Step 2 β€” Configure the tool and its command Jump to heading

For tools Git knows, setting merge.tool is enough. For anything else, define mergetool.<name>.cmd using the four variables Git provides.

# VS Code, using its built-in three-way merge editor
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait --merge "$REMOTE" "$LOCAL" "$BASE" "$MERGED"'

# vimdiff with a layout that shows the base (Git 2.37+ supports layout strings)
git config --global merge.tool vimdiff
git config --global mergetool.vimdiff.layout "LOCAL,BASE,REMOTE / MERGED"

# Meld, which Git drives natively
git config --global merge.tool meld

Quote the variables in custom commands: paths with spaces otherwise break the command in confusing ways.

# Verification: launch on a conflicted file and confirm four panes appear
git merge feature/x || git mergetool -- path/to/conflicted.file

Step 3 β€” Stop the clutter and the prompts Jump to heading

By default git mergetool writes a .orig backup of each file and asks for confirmation before opening each one. Turn both off; the backup is redundant because the conflicted state is in the index and the reflog.

git config --global mergetool.keepBackup false
git config --global mergetool.prompt false
# Trust the tool's exit code so files are marked resolved only when you save and quit successfully
git config --global mergetool.vscode.trustExitCode true

trustExitCode matters: without it Git asks β€œwas the merge successful?” after each file. With it, closing the tool normally marks the file resolved, and aborting leaves it conflicted.

Default mergetool behaviour against a tuned setupOut of the box, git mergetool prompts before each file, leaves .orig backups behind and asks after each file whether the merge succeeded. A tuned setup opens files directly, keeps the working tree clean and uses the tool's exit status to mark files resolved.DefaultsTunedbefore each filepromptopen directlybackup files*.orig left behindnonemarking resolvedasks every timetool exit codebase panedepends on toolalways shownthree config lines remove most of the friction people complain about

Step 4 β€” Resolve, then inspect before committing Jump to heading

The tool writes the result into the working tree and stages it. Before committing, check that no markers remain and that the result does what both sides intended β€” the tool makes combining hunks easy, which also makes combining them wrongly easy.

git diff --cached --check          # flags leftover conflict markers and whitespace errors
git diff --cached                  # read the result one more time
git grep -nE '^(<{7}|={7}|>{7}|\|{7})( |$)' -- $(git diff --cached --name-only) || echo "no markers"
A mergetool session from conflict to commitA merge stops with conflicts. git mergetool opens each conflicted file in the configured tool with all four panes. Saving and closing stages the result. A marker check and a final diff review come before the merge commit.Conflictgit merge stopsmergetoolone file at a timeSave + closeexit 0 = resolvedCheckdiff --cached --checkCommitgit committhe tool resolves files; you still review the result as a whole

Step 5 β€” Share a team default without forcing it Jump to heading

Teams benefit from a shared default, but editors are personal. Put a sensible default in a team configuration file included by everyone, as described in shipping a team gitconfig with includeIf, and let individuals override it in their own global configuration.

# team.gitconfig β€” included by every developer
[merge]
    conflictStyle = zdiff3
[mergetool]
    keepBackup = false
    prompt = false
[mergetool "vscode"]
    cmd = code --wait --merge \"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"
    trustExitCode = true

Leave merge.tool itself unset in the team file, so each person chooses; the per-tool settings are ready whichever they pick.

Validation checklist Jump to heading

Frequently Asked Questions Jump to heading

Can I use mergetool during a rebase? Jump to heading

Yes. During a rebase that stops on a conflict, git mergetool works the same way; remember that during a rebase β€œlocal” is the branch you are rebasing onto and β€œremote” is your commit being replayed.

Does a merge tool understand code structure? Jump to heading

Most work line by line, like Git. Some language-aware tools can merge at the syntax level and resolve conflicts like two imports added in the same place. They are worth trying for heavy refactoring work, but review their results carefully.

Why does mergetool say there is nothing to merge? Jump to heading

It only opens files with unresolved conflicts. If you already staged a file with git add, Git considers it resolved. Use git checkout --conflict=zdiff3 -- path to restore the conflict, then run the tool again.