I like neovim and using git via the cli. Git has some options to customize specific tasks, for instance solving merge conflicts using git mergetool. In this blog post I’m going to demonstrate how to setup git and neovim to solve git merge conflicts without the need of an additional GUI tool.
To achieve this there are a few prerequisites:
- neovim and git are installed
- a merge conflict to test the config against
Next Git’s config has to be updated in one of the following places:
- Inside the git repository under .git/config (for repo specific configuration)
All of these are parsed and concatenated by git before command execution takes place. NOTE: Local configuration overrules global configuration options if present.
To update such files different approaches can be considered.
For instance, using the git cli:
git config mergetool nvim
This only registers a variable which still needs a command to be executed.
git config mergetool.nvim.cmd 'nvim -d -c "wincmd l" -c "norm ]c" "$LOCAL" "$MERGED" "$REMOTE"'
A short notice what is actually being executed here:
nvim -dopens neovim in diffmode.
-c "wincmd l"executes
<C-w>lto move the focus to the next split to the right.
-c "norm ]c"puts the cursor inside the split to the first change. It is the equivalent of hitting
]cin command mode which is indicated by
norm. Command mode is also known as normal mode in vim.
"$LOCAL" "$MERGED" "$REMOTE"defines the arrangement of the displayed diffs.
After inserting the new options
git config -l | grep 'merge' should reveal the following:
merge.tool=nvim mergetool.nvim.cmd=nvim -d -c "wincmd l" -c "norm ]c" "$LOCAL" "$MERGED" "$REMOTE"
Inside the git config file it should look similar to this:
[merge] tool = "nvim" [mergetool] keepBackup = false prompt = false [mergetool "nvim"] cmd = "nvim -d -c \"wincmd l\" -c \"norm ]c\" \"$LOCAL\" \"$MERGED\" \"$REMOTE\""
git mergetool will then parse all merge conflicted files and populate them iteratively to the mergetool command.
:diffget local will use the left diff from the local changes and
:diffget remote vice versa.
To jump to the next change use
After resolving all conflicts for a given file
:wqa finishes the process and populates the next merge conflicted file into a new diffview.
Furthermore git will also place backup files of the originals inside the git repository, unless git config contains
keepBackup = false.
Git will also ask before any merge conflicted file is opened in a diff, unless
prompt is set to
This is just one approach among many, but it works quite well for me.