Resolve Conflicts with git mergetool
Staring at raw conflict markers in a dozen files is how you introduce a second bug while fixing the first. git mergetool opens a proper diff view instead. Allow about 10 minutes for a small text conflict, plus whatever time you need to actually understand the competing changes. This guide covers the Git 2.43.0 manpage installed with the Debian git-man package. Later Git releases keep the same workflow, but which backends are available depends on what is installed on your machine.
The route
Jump straight to the step you need, or tick off Done means at the end.
Before you start
You need a Git repository paused during a merge, with at least one unmerged file, and a graphical or terminal merge tool installed. Do not run these commands in a repository with unrelated uncommitted work unless you have saved it elsewhere first. A merge tool writes to the working tree, and accepting the wrong side is a real content change.
Check the version and see which backends this installation recognises:
git --version
git mergetool --tool-help
On the reference system, the first command reports Git 2.43.0. The second prints the tools Git knows about; it is not a guarantee that every listed program is actually installed or usable in your current display session.
Checkpoint
You have a paused merge and know the path of at least one file that git status reports as unmerged.
1. Inspect the conflict before opening a tool
Start with Git's status and, for a text conflict, the conflict markers themselves. That gives you context before a tool throws several versions of the file at you.
git status
git diff -- path/to/conflicted-file
Replace path/to/conflicted-file with a real path. With no path argument, git mergetool later visits every file still carrying a merge conflict. Supplying a file or directory narrows the session; files without conflicts are skipped, and a directory pulls in every unresolved file beneath it.
Do not treat git diff as the final answer. The working file shows <<<<<<<<, ======= and >>>>>>> markers, but a merge tool also gives you the common ancestor and both branch versions side by side. The goal is a coherent result, not just markers removed.
Checkpoint
You have identified the files that need a decision and have not changed them yet.
2. Choose an explicit merge tool
For a terminal session with Vim:
git mergetool --tool=vimdiff path/to/conflicted-file
Git's vimdiff layout shows LOCAL, BASE and REMOTE as reference buffers, with MERGED as the writable result. LOCAL is the version from the branch you had checked out, BASE is the common ancestor, REMOTE is the version being merged in. Edit only the merged result, then save and quit Vim with :wq.
To use another installed backend, swap in its name:
git mergetool --tool=meld path/to/conflicted-file
The installed manpage lists examples including emerge, gvimdiff, kdiff3, meld, vimdiff and tortoisemerge. Run git mergetool --tool-help for this machine's actual list, since a named executable can be listed and still be missing until you install it or point Git at the correct path.
To use the configured default instead, just omit --tool:
git mergetool path/to/conflicted-file
Git first consults merge.tool. If that is unset, Git picks a suitable default. An explicit or configured tool normally disables the prompt between files; use --prompt when you want the chance to skip each path, or --no-prompt when you do not.
Checkpoint
The tool has opened the intended file, you can identify the writable merged view, and you have not accepted a side without checking the surrounding change.
3. Save the resolution and handle the backup
Finish the file in the merge tool and exit normally. With Vim, :wq records the merged buffer. If you started vimdiff and want to abandon that file without claiming success, use :cq instead: it exits with a failure status so Git does not silently treat an unfinished session as resolved.
By default, Git keeps the original conflict-marked file as path/to/conflicted-file.orig, a useful recovery copy while you check the result:
git status
git diff --check
git diff -- path/to/conflicted-file
git diff --check catches whitespace errors in the result, but read the diff yourself too: automated checks cannot decide which behaviour the application actually needs. If the result is wrong, restore the conflict state from the .orig copy, but only after confirming it is genuinely the expected backup, then rerun the tool:
cp -- path/to/conflicted-file.orig path/to/conflicted-file
git mergetool --tool=vimdiff path/to/conflicted-file
Warning
That copy command changes the working file and can overwrite your current attempted resolution. Check the two paths first, and keep the backup until the new result is verified. Once you are certain the merge is correct, the .orig file is safe to remove. You can also configure Git to remove successful backups automatically, in a repository or user configuration:
git config mergetool.keepBackup false
That configuration change is ordinary user-level Git state, not an elevated operation. Leaving the default enabled is safer while you are learning a tool or resolving something important.
4. Mark the file resolved and verify the merge
Saving a file in the tool is not the same as staging it. Once the content passes your review, stage the resolved path:
git add -- path/to/conflicted-file
git status
git diff --cached --check
Repeat the mergetool and staging steps for every remaining conflict. A directory or a no-argument invocation can process several files at once, but reviewing and staging one logical group at a time makes an accidental acceptance easier to spot.
The status output should move the path from "unmerged paths" to "changes to be committed". Before committing, run the project's relevant tests, formatter or build. Then finish the merge normally:
git diff --cached
git commit
Do not use git commit to paper over an unresolved conflict. If git status still lists unmerged paths, go back to the previous checkpoint. If the whole merge should be abandoned, use the recovery command in the last section before committing anything.
Useful configuration for custom tools
Git can run a known tool from a non-standard location:
git config --global mergetool.kdiff3.path /absolute/path/to/kdiff3
Only point this at a path you have inspected and trust. A custom tool can also be defined with mergetool.<tool>.cmd. Git supplies shell variables named BASE, LOCAL, REMOTE and MERGED; the command must write the successful result to MERGED. A wrapper script, for example, could be registered as mytool:
git config mergetool.mytool.cmd '/absolute/path/to/my-tool "$BASE" "$LOCAL" "$REMOTE" "$MERGED"'
git config mergetool.mytool.trustExitCode true
git mergetool --tool=mytool path/to/conflicted-file
Set trustExitCode to true only when the program reliably returns success or failure. Otherwise Git checks whether the merged file changed and may ask you to confirm the result. Treat custom commands as shell commands: quote the variables, use an absolute executable path where practical, and review the command before running it.
Abort or recover
If the merge itself is no longer wanted and you have not committed it, stop and check your repository state before undoing it. The usual Git recovery command is:
git status
git merge --abort
Warning
Aborting changes the working tree and attempts to return to the pre-merge state. Save unrelated work first, and do not assume it can recover edits made outside the merge. If you only need to retry one file, keep the .orig backup and rerun git mergetool instead of aborting everything.
Done means
git statusshows no unmerged paths.git diff --cached --checkreports no whitespace errors.- The staged diff contains the intended resolution and no conflict markers.
- The project's relevant tests or build complete successfully.
- You have kept or deliberately removed each
.origbackup. - The merge commit is made only after those checks pass.