Skip to content

Git difftool vs mergetool: What's the Difference and When to Use Each

git difftool and git mergetool look similar but solve different problems. Learn which command to run, when to run it, and how to configure each independently.

TL;DR

  • git difftool: opens a visual diff to view differences between two commits, branches, or files; works anytime
  • git mergetool: opens a visual editor to resolve conflicts; only available after a merge or rebase that produced conflicts
  • Both commands delegate to an external tool (Meld, VS Code, vimdiff, etc.) but serve completely different purposes
  • You can configure them to use different tools via diff.tool and merge.tool independently

What You'll Learn

  • The conceptual difference between diffing and merging, and why Git separates the two commands
  • When each command is available and what happens if you run the wrong one
  • The file variables ($LOCAL, $BASE, $REMOTE, $MERGED) your merge tool works with
  • Key flags like --dir-diff and --cached that make difftool genuinely useful day-to-day
  • How to wire up different tools for diff and merge operations in your .gitconfig
  • Troubleshooting the most common mistakes, including why mergetool immediately exits

The Problem

You've seen both commands in documentation and tutorials. You've configured a tool like Meld or VS Code. But which one do you actually run? When you're looking at a branch comparison before a PR, is that difftool or mergetool? When a git merge blows up with conflicts, do you need difftool or mergetool?

Running the wrong one wastes time. git mergetool with no active conflicts exits immediately, printing "No files need merging". git difftool doesn't help you resolve anything. It's read-only in intent.

Common Questions This Article Answers:

  • What's the actual difference between git difftool and git mergetool?
  • Can I use git mergetool to compare branches before merging?
  • Why does git mergetool exit immediately when I run it?
  • Can I configure Meld for diffing and VS Code for merging?
  • What are $LOCAL, $BASE, $REMOTE, and $MERGED in a merge tool?

Quick Answer

git difftool is for looking at differences. You can run it against any two points in history (two commits, two branches, a file from yesterday vs today) anytime, regardless of repository state. Think of it as a visual git diff.

git mergetool is for resolving conflicts. Git only makes it available after a merge, rebase, or cherry-pick that couldn't automatically reconcile conflicting changes. It opens each conflicted file in a three-way editor showing your version, their version, and the common ancestor, letting you build the final result. Run it when you have no active conflicts and it has nothing to do.

Same external tool, different jobs, different availability.

How git difftool Works

What It Does

git difftool is a thin wrapper around git diff that opens your configured tool instead of printing to the terminal. Every flag that works with git diff works here. The only difference is where the output goes.

# Compare working directory against HEAD (unstaged changes)
git difftool

# Compare staged changes (what's about to be committed)
git difftool --cached

# Compare two commits
git difftool abc1234 def5678

# Compare current branch against main
git difftool main

# Compare two branches
git difftool main feature/new-login

# Compare a specific file between commits
git difftool HEAD~2 HEAD -- src/auth/login.js

# Compare working directory against a remote branch
git difftool origin/main

By default, difftool opens files one at a time, prompting you before each one:

Viewing (1/3): 'src/auth/login.js'
Launch 'meld' [Y/n]?

Key Flags

--dir-diff: The flag you'll use most. Instead of opening files one at a time, it copies both sides into temporary directories and opens the tool once with the full directory tree. Much faster for reviewing a large changeset.

# Compare all changes on feature branch against main in one shot
git difftool --dir-diff main feature/payment-refactor

# Review all staged changes before committing
git difftool --dir-diff --cached

# Compare two commits, full directory view
git difftool --dir-diff HEAD~3 HEAD

--cached / --staged: Diffs the index (staging area) against HEAD. Use this to review exactly what git commit will include.

git difftool --cached
git difftool --staged   # identical, two names for the same flag

--tool-help: Lists every tool Git knows about on your system, split into "available" and "may be available":

# Run to see all available tools on your system:
git difftool --tool-help
# Output lists tools under two sections:
# "'git difftool --tool=<tool>' may be set to one of the following:" (available)
# "The following tools are valid, but not currently available:" (installed but missing config)

--no-prompt / -y: Skip the "Launch tool? [Y/n]" prompt for each file. Useful in scripts or when you always want to open every changed file.

git difftool -y main feature/ui-rework

When to Use difftool

Situation Command
Review all unstaged changes visually git difftool
Check what's staged before committing git difftool --cached
Compare your branch against main before raising a PR git difftool --dir-diff main
Understand what changed between two releases git difftool v1.2.0 v1.3.0
Review a colleague's branch git difftool main their-branch

How git mergetool Works

What It Does

After git merge, git rebase, or git cherry-pick produces conflicts, Git marks conflicted files with conflict markers and stops. git mergetool finds those files and opens each one in your configured merge tool.

# Typical conflict workflow
git merge feature/payments
# Auto-merging src/cart.js
# CONFLICT (content): Merge conflict in src/cart.js
# Automatic merge failed; fix conflicts and then commit the result.

# Open each conflicted file in your merge tool
git mergetool

The tool receives four file versions for each conflicted file:

Variable Contents
$LOCAL Your version: the current branch (HEAD)
$BASE The common ancestor: what both sides diverged from
$REMOTE Their version: the branch being merged in
$MERGED The output file: what you save to resolve the conflict

A three-way merge tool (Meld, KDiff3, Beyond Compare) shows all three source files side by side, with $MERGED as the editable output pane in the middle or bottom.

The Workflow

# 1. Attempt the merge (or rebase)
git merge feature/new-api

# 2. Git tells you which files have conflicts
# CONFLICT (content): Merge conflict in src/api/client.js
# CONFLICT (content): Merge conflict in src/api/types.ts

# 3. Open merge tool — it processes each conflicted file in turn
git mergetool

# 4. In your tool: resolve conflicts, save, close the tool window
# Git marks that file as resolved automatically

# 5. After all files are resolved, commit
git commit
# Git pre-fills the merge commit message

# 6. Clean up .orig backup files (if you haven't disabled them)
git clean -f "*.orig"

Useful mergetool Config Options

# Don't prompt before opening each file
git config --global mergetool.prompt false

# Don't leave .orig backup files lying around
git config --global mergetool.keepBackup false

# Tell Git to trust the tool's exit code to determine success
git config --global mergetool.meld.trustExitCode true

# Show diff3 style conflicts (includes common ancestor in markers)
# Helps your merge tool and helps you understand conflicts in the raw file
git config --global merge.conflictStyle diff3

When to Use mergetool

git mergetool has exactly one use case: you have active merge conflicts and you want to resolve them visually. That's it.

# Check whether you actually have conflicts before running mergetool
git status
# On branch main
# You have unmerged paths.
#   (fix conflicts and run "git commit")
#
#   both modified:   src/cart.js

# If you see "You have unmerged paths" — now run mergetool
git mergetool

Side-by-Side Comparison

git_difftool:
  purpose: "View differences between two states"
  when_available: "Anytime — no conflicts required"
  typical_use_cases:
    - "Pre-PR branch review"
    - "Check staged changes before committing"
    - "Compare releases or commits"
    - "Code review of a colleague's branch"
  what_it_opens: "Two-pane diff view (before / after)"
  file_variables: "$LOCAL (old), $REMOTE (new)"
  requires_conflicts: false
  modifies_files: false

git_mergetool:
  purpose: "Resolve merge conflicts"
  when_available: "Only after a merge/rebase/cherry-pick with conflicts"
  typical_use_cases:
    - "Resolve conflicts after git merge"
    - "Resolve conflicts during git rebase"
    - "Resolve conflicts after git cherry-pick"
  what_it_opens: "Three-pane merge view (LOCAL / BASE / REMOTE + MERGED output)"
  file_variables: "$LOCAL, $BASE, $REMOTE, $MERGED"
  requires_conflicts: true
  modifies_files: true   # writes the resolved content to $MERGED

Common Workflows

1. Pre-Merge Review (difftool)

Before merging a feature branch, use difftool to understand what's coming in. This is read-only. You're reviewing, not resolving.

# See everything that's different between main and the feature branch
git difftool --dir-diff main feature/checkout-redesign

# Filter to a specific directory if the changeset is large
git difftool --dir-diff main feature/checkout-redesign -- src/checkout/

2. Conflict Resolution (mergetool)

After a merge creates conflicts, switch to mergetool.

# Merge the branch
git merge feature/checkout-redesign

# If conflicts: open each one in your merge tool
git mergetool

# After resolving all files
git status          # verify no remaining unmerged paths
git commit          # complete the merge

3. Reviewing Staged Changes Before Committing (difftool)

Before every commit, it's good practice to review exactly what you're about to push.

# Stage your changes
git add src/auth/

# Review what's staged — opens difftool, not mergetool
git difftool --cached

# Happy with it? Commit.
git commit -m "refactor: extract auth token logic"

4. Comparing Branches for Code Review (difftool)

When reviewing a colleague's branch without a full PR tool:

# Fetch their branch
git fetch origin

# Open a full directory diff in one tool window
git difftool --dir-diff main origin/feature/user-settings

# Narrow to specific files
git difftool origin/main origin/feature/user-settings -- src/settings/

5. Rebase Conflict Resolution (mergetool)

Rebasing replays commits one at a time. Conflicts may appear at each step.

git rebase main

# CONFLICT (content): Merge conflict in src/api/client.js
# error: could not apply a1b2c3d... add retry logic

# Resolve conflicts for this commit
git mergetool

# Continue the rebase
git rebase --continue

# Repeat if more commits have conflicts

Configuring Different Tools for Each

Git keeps diff.tool and merge.tool completely separate. You can use a lightweight diff viewer for comparisons and a full three-way editor for conflicts.

Using Different Tools

# Use VS Code for diff operations (fast, familiar)
git config --global diff.tool vscode

# Use Meld for merge operations (better three-way view)
git config --global merge.tool meld

# Verify your settings
git config --get diff.tool    # vscode
git config --get merge.tool   # meld

Configuring Custom Tool Commands

If your tool isn't built into Git's known list, define it manually:

# Custom difftool command
git config --global diff.tool mytool
git config --global difftool.mytool.cmd 'mytool "$LOCAL" "$REMOTE"'

# Custom mergetool command
git config --global merge.tool mytool
git config --global mergetool.mytool.cmd 'mytool --merge "$LOCAL" "$BASE" "$REMOTE" --output "$MERGED"'

Example: VS Code for diff, Meld for merge

# diff.tool — VS Code opens two-pane diff
git config --global diff.tool vscode
git config --global difftool.vscode.cmd 'code --wait --diff "$LOCAL" "$REMOTE"'

# merge.tool — Meld opens three-pane merge editor
git config --global merge.tool meld
git config --global mergetool.meld.path "/usr/bin/meld"
git config --global mergetool.keepBackup false
git config --global mergetool.prompt false

Verifying Your Full Config

# See all diff and merge tool settings at once
git config --list | grep -E "(diff|merge)\.(tool|cmd|path)"

# Quick functional test for difftool (works anytime)
git difftool --tool-help

# Quick functional test for mergetool
git mergetool --tool-help

Troubleshooting

mergetool exits immediately with no output

This is the most common mistake. git mergetool has nothing to do when there are no active conflicts.

# Wrong: running mergetool with no conflicts
git mergetool
# No files need merging
# (exits immediately)

# Check your actual state first
git status
# If output shows "nothing to commit, working tree clean" — there are no conflicts.
# Use git difftool instead if you want to compare things.

If you just resolved conflicts and the above still happens, confirm all files are staged:

git status
# Look for "Unmerged paths:" — if none, you're done, just commit
git commit

difftool opens the wrong tool

Check which tool is configured:

git config --get diff.tool

# If blank, Git falls back to merge.tool, then picks a suitable tool from what's installed
# Set it explicitly:
git config --global diff.tool meld

If the tool opens but shows "not available", confirm it's in PATH:

which meld          # macOS/Linux
where meld          # Windows

# If not found, set the full path:
git config --global difftool.meld.path "/usr/bin/meld"

"tool not found" error when running mergetool

git mergetool
# error: tool 'meld' not available

# Check what's actually available on your system
git mergetool --tool-help

# Switch to something available, or install the tool you want
# On Ubuntu/Debian:
sudo apt install meld

# On macOS with Homebrew:
brew install meld

# On Windows with Chocolatey:
choco install meld

Backup .orig files cluttering your working directory

After git mergetool runs, it leaves .orig backups by default (cart.js.orig, etc.). Disable them:

git config --global mergetool.keepBackup false

# Or clean up existing ones manually
git clean -f "*.orig"

difftool prompts for every file and it's slow

Use --no-prompt (-y) to skip confirmation, or use --dir-diff to open everything in one tool window:

git difftool -y main feature/big-refactor

# Or the directory approach — one tool window, all files
git difftool --dir-diff main feature/big-refactor

Frequently Asked Questions

Q: Can I use git difftool to preview conflicts before they happen?

A: Yes. Before merging, run git difftool --dir-diff main feature/branch to see every difference between the two branches. This shows what will be merged but doesn't simulate which lines will conflict. Git's auto-merge algorithm handles many changes silently. It's still the best way to understand the scope of a merge before you attempt it.

Q: After resolving conflicts with mergetool, do I need to git add the files?

A: Not usually. When git mergetool successfully processes a file, it stages the resolved version automatically. You can verify with git status: resolved files should appear under "Changes to be committed", not "Unmerged paths". If a file still shows as unmerged, open it and remove any remaining conflict markers, then git add it manually.

Q: Can I use git difftool during a rebase to review what changed?

A: Yes. git difftool is always available regardless of repository state. During a rebase, you can run git difftool HEAD to see what the current state looks like vs the previous commit, or git difftool --cached to review what's staged. If a rebase produces conflicts, switch to git mergetool for those specific files.

Q: What's the difference between --cached and --staged?

A: They're identical. --staged was added later as a more descriptive alias for --cached. Both compare the index (staging area) against HEAD. Use whichever feels more natural. git difftool --staged reads well; git difftool --cached is what you'll see in older documentation.

Q: My merge tool shows only two panes, not three. Is something wrong?

A: Some tools only show a two-pane diff by default. For merge conflict resolution you really want three panes (LOCAL / BASE / REMOTE) plus an output pane, because without the common ancestor ($BASE) it's harder to reason about who changed what. Check your tool's settings to enable three-way mode. In Meld, this is the default when opened via git mergetool. In VS Code, it requires enabling the merge editor in settings.

Q: Does git mergetool work with git cherry-pick conflicts?

A: Yes. git mergetool works after any operation that produces conflicts: git merge, git rebase, git cherry-pick, and git stash pop. The workflow is identical: run git mergetool once conflicts are present, resolve each file, then continue with git cherry-pick --continue (or git rebase --continue, etc.).

Key Takeaways

  • difftool = view differences: works anytime, opens a two-pane diff, read-only in intent
  • mergetool = resolve conflicts: only available after a conflicted merge/rebase/cherry-pick, opens a three-way editor, writes the resolved output
  • Running git mergetool with no conflicts is harmless but does nothing. Check git status first
  • --dir-diff is the most useful difftool flag for real workflow use; it opens one tool window for the entire changeset
  • diff.tool and merge.tool are independent config keys. Configure them separately if you prefer different tools for each job
  • After mergetool finishes, verify with git status and then git commit to complete the merge

What's Next?

Now that you know which command to run, the next step is configuring the right tool for each:

Both posts assume you understand the difference between difftool and mergetool, which you now do.

Resources & References


Tags: #git #development-tools #workflow #merge #diff