SkillAgentSearch skills...

Resolve.nvim

A Neovim plugin for resolving merge conflicts with conflict marker highlighting and resolution commands.

Install / Use

/learn @spacedentist/Resolve.nvim
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<h1 align="center">resolve.nvim</h1> <p align="center">A Neovim plugin for resolving merge conflicts with ease.</p> <p align="center"> <video src="https://github.com/user-attachments/assets/a6b55e7a-c490-4a43-8562-1851b93610fd" width="876" controls muted loop> ![Demo Screencast](https://github.com/user-attachments/assets/a6b55e7a-c490-4a43-8562-1851b93610fd) </video> </p>

You can watch a three-minute demo on YouTube

Features

  • Automatically detect merge conflicts in buffers
  • Semantic highlighting for both markers and content sections with automatic light/dark theme support
  • Navigate between conflicts quickly
  • Resolve conflicts with simple commands
  • Support for standard 3-way merge and diff3 formats
  • View diffs between base and each version separately or together in a floating window
  • List all conflicts in quickfix window
  • Buffer-local keymaps (only active in buffers with conflicts)
  • Matchit integration for % jumping between conflict markers
  • <Plug> mappings for easy custom keybinding
  • Customisable hooks/callbacks on conflict detection

Development

This plugin was inspired by prior work:

The feature I was missing in other plugins was a quick way to compare the local or remote side of the conflict with the common base (which is included in conflicted files if enabled, e.g. by the merge.conflictStyle setting in git set to diff3).

Development was aided by Claude Code. Pull requests are welcome. If you use AI coding tools, please read and understand all code changes before submitting them as a PR.

Requirements

  • Neovim >= 0.9
  • delta - required for diff view features (optional if you only use highlighting and conflict resolution)

Installation

Using lazy.nvim

{
  "spacedentist/resolve.nvim",
  event = { "BufReadPre", "BufNewFile" },
  opts = {},
}

Using packer.nvim

use {
  "spacedentist/resolve.nvim",
  config = function()
    require("resolve").setup()
  end,
}

Using vim-plug

Plug 'spacedentist/resolve.nvim'

lua << EOF
  require("resolve").setup()
EOF

Configuration

Default configuration:

require("resolve").setup({
  -- Conflict marker patterns (Lua patterns, must match from start of line)
  markers = {
    ours = "^<<<<<<<+",      -- Start of "ours" section
    theirs = "^>>>>>>>+",    -- End of "theirs" section
    ancestor = "^|||||||+",  -- Start of ancestor/base section (diff3)
    separator = "^=======+$", -- Separator between sections
  },
  -- Set to false to disable default keymaps
  default_keymaps = true,
  -- Callback function called when conflicts are detected
  -- Receives: { bufnr = number, conflicts = table }
  on_conflict_detected = nil,
  -- Callback function called when all conflicts are resolved
  -- Receives: { bufnr = number }
  on_conflicts_resolved = nil,
})

Theming and Highlights

The plugin creates highlight groups for both conflict markers and their content sections, with semantic colours that automatically adapt to light/dark backgrounds:

Marker Highlights (bold lines)

| Highlight Group | Marker | Dark Theme | Light Theme | Meaning | |----------------|--------|------------|-------------|---------| | ResolveOursMarker | <<<<<<< | Green tint | Light green | Your changes (keep) | | ResolveTheirsMarker | >>>>>>> | Blue tint | Light blue | Incoming changes | | ResolveSeparatorMarker | ======= | Grey | Light grey | Neutral divider | | ResolveAncestorMarker | \|\|\|\|\|\|\| | Amber tint | Light amber | Original/base (diff3) |

All markers are displayed in bold with normal text colour and a tinted background.

Section Highlights (content between markers)

| Highlight Group | Section | Dark Theme | Light Theme | Meaning | |----------------|---------|------------|-------------|---------| | ResolveOursSection | Ours content | Subtle green | Very light green | Your changes | | ResolveTheirsSection | Theirs content | Subtle blue | Very light blue | Incoming changes | | ResolveAncestorSection | Base content | Subtle amber | Very light amber | Original (diff3) |

The section highlights provide a subtle background tint to help visually distinguish which code belongs to which side.

The highlights automatically update when you change colour schemes or toggle between light/dark backgrounds.

Customising Highlights

Override the highlight groups in your config to customise the appearance:

-- After calling setup(), override any highlights you want to change

-- Marker highlights (bold lines)
vim.api.nvim_set_hl(0, "ResolveOursMarker", { bg = "#3d5c3d", bold = true })
vim.api.nvim_set_hl(0, "ResolveTheirsMarker", { bg = "#3d4d5c", bold = true })
vim.api.nvim_set_hl(0, "ResolveSeparatorMarker", { bg = "#4a4a4a", bold = true })
vim.api.nvim_set_hl(0, "ResolveAncestorMarker", { bg = "#5c4d3d", bold = true })

-- Section highlights (content areas)
vim.api.nvim_set_hl(0, "ResolveOursSection", { bg = "#2a3a2a" })
vim.api.nvim_set_hl(0, "ResolveTheirsSection", { bg = "#2a2f3a" })
vim.api.nvim_set_hl(0, "ResolveAncestorSection", { bg = "#3a322a" })

Or link to existing highlight groups if you prefer theme-matched colours:

-- Markers
vim.api.nvim_set_hl(0, "ResolveOursMarker", { link = "DiffAdd" })
vim.api.nvim_set_hl(0, "ResolveTheirsMarker", { link = "DiffChange" })
vim.api.nvim_set_hl(0, "ResolveSeparatorMarker", { link = "NonText" })
vim.api.nvim_set_hl(0, "ResolveAncestorMarker", { link = "DiffText" })

-- Sections
vim.api.nvim_set_hl(0, "ResolveOursSection", { link = "DiffAdd" })
vim.api.nvim_set_hl(0, "ResolveTheirsSection", { link = "DiffChange" })
vim.api.nvim_set_hl(0, "ResolveAncestorSection", { link = "DiffText" })

To disable section highlights entirely while keeping marker highlights:

vim.api.nvim_set_hl(0, "ResolveOursSection", {})
vim.api.nvim_set_hl(0, "ResolveTheirsSection", {})
vim.api.nvim_set_hl(0, "ResolveAncestorSection", {})

Usage

Default Keymaps

When default_keymaps is enabled (keymaps are buffer-local, only active when conflicts exist):

  • ]x - Navigate to next conflict
  • [x - Navigate to previous conflict
  • <leader>gco - Choose ours (current changes)
  • <leader>gct - Choose theirs (incoming changes)
  • <leader>gcb - Choose both (keep both versions)
  • <leader>gcB - Choose both reverse (theirs then ours)
  • <leader>gcm - Choose base/ancestor (diff3 only)
  • <leader>gcn - Choose none (delete conflict)
  • <leader>gcl - List all conflicts in quickfix window
  • <leader>gcdo - Show diff ours (base → ours, diff3 only)
  • <leader>gcdt - Show diff theirs (base → theirs, diff3 only)
  • <leader>gcdb - Show diff both (base → ours and base → theirs, diff3 only)
  • <leader>gcdv - Show diff ours → theirs (direct comparison, works without diff3)
  • <leader>gcdV - Show diff theirs → ours (reverse comparison, works without diff3)

The <leader>gc prefix displays as "Git Conflicts" in which-key, and <leader>gcd displays as "Diff".

Commands

The plugin provides the following commands:

  • :ResolveNext - Navigate to next conflict
  • :ResolvePrev - Navigate to previous conflict
  • :ResolveOurs - Choose ours version
  • :ResolveTheirs - Choose theirs version
  • :ResolveBoth - Choose both versions (ours then theirs)
  • :ResolveBothReverse - Choose both versions (theirs then ours)
  • :ResolveBase - Choose base/ancestor version (diff3 only)
  • :ResolveNone - Choose neither version
  • :ResolveList - List all conflicts in quickfix
  • :ResolveDetect - Manually detect conflicts
  • :ResolveDiffOurs - Show diff of our changes from base (diff3 only)
  • :ResolveDiffTheirs - Show diff of their changes from base (diff3 only)
  • :ResolveDiffBoth - Show both diffs in floating window (diff3 only)
  • :ResolveDiffOursTheirs - Show diff ours → theirs (works without diff3)
  • :ResolveDiffTheirsOurs - Show diff theirs → ours (works without diff3)

Custom Keymaps

If you prefer custom keymaps, disable the default ones and set your own using the <Plug> mappings:

require("resolve").setup({
  default_keymaps = false,
})

-- Example: Set custom keymaps using <Plug> mappings
-- Register groups for which-key (optional)
vim.keymap.set("n", "<leader>gc", "", { desc = "+Git Conflicts" })
vim.keymap.set("n", "<leader>gcd", "", { desc = "+Diff" })

vim.keymap.set("n", "]c", "<Plug>(resolve-next)", { desc = "Next conflict" })
vim.keymap.set("n", "[c", "<Plug>(resolve-prev)", { desc = "Previous conflict" })
vim.keymap.set("n", "<leader>gco", "<Plug>(resolve-ours)", { desc = "Choose ours" })
vim.keymap.set("n", "<leader>gct", "<Plug>(resolve-theirs)", { desc = "Choose theirs" })
vim.keymap.set("n", "<leader>gcb", "<Plug>(resolve-both)", { desc = "Choose both" })
vim.keymap.set("n", "<leader>gcB", "<Plug>(resolve-both-reverse)", { desc = "Choose both reverse" })
vim.keymap.set("n", "<leader>gcm", "<Plug>(resolve-base)", { desc = "Choose base" })
vim.keymap.set("n", "<leader>gcn", "<Plug>(resolve-none)", { desc = "Choose none" })
vim.keymap.set("n", "<leader>gcdo", "<Plug>(resolve-diff-ours)", { desc = "Diff ours" })
vim.keymap.set("n", "<leader>gcdt", "<Plug>(resolve-diff-theirs)", { desc = "Diff theirs" })
vim.keymap.set("n", "<leader>gcdb", "<Plug>(resolve-diff-both)", { desc = "Diff both" })
vim.keymap.set("n", "<leader>gcdv", "<Plug>(resolve-diff-vs)", { desc = "Diff ours → theirs" })
vim.keymap.set("n", "<leader>gcdV", "<Plug>(resolve-diff-vs-reverse)", { desc = "Diff theirs → ours" })
vim.keymap.set("n", "<leader>gcl", "<Plug>(resolve-list)", { desc = "List conflicts" })

Available <Plug> Mappings

The following <Plug> mappings

Related Skills

View on GitHub
GitHub Stars50
CategoryDevelopment
Updated15d ago
Forks4

Languages

Lua

Security Score

95/100

Audited on Mar 18, 2026

No findings