Vgit.nvim
Visual git plugin for Neovim
Install / Use
/learn @tanvirtin/Vgit.nvimREADME
Project Diff Preview
Explore all changes in your project at a glance. The diff preview displays modified files and highlights the changes for better project-wide management.
Project Logs Preview
View and filter the logs of your current branch in an intuitive interface. Select logs and open detailed commit previews effortlessly.
Project Stash Preview
Easily manage and preview all your stashed changes in one place. Keep your work organized and accessible.
Buffer Diff Preview
Visually compare your current buffer with its version in the Git index. If focused on a hunk, this preview zooms into the relevant changes for a streamlined review experience.
Buffer Blame Preview
Gain instant insight into the author and commit history of any line in your buffer. This feature enables seamless tracing of code changes.
Buffer History Preview
Dive into the history of your file with a detailed view of all its Git iterations. See how the file has evolved through various commits.
Conflict Management
VGit simplifies conflict resolution by clearly highlighting different segments of a conflict and giving you the flexibility to choose the necessary changes, making it easy to merge and resolve conflicts efficiently.
Live Blame
Enable live blame annotations directly in your editor to see the author and commit for each line in real time. Perfect for understanding the evolution of code at a glance.
Requirements
- Neovim
0.10+ - Git
2.18.0+ - Supported Operating Systems:
linux-gnu*Darwin
Installation
[!NOTE] Package managers with lazy loading is necessary for installation.
Using packer.nvim
use {
'tanvirtin/vgit.nvim',
requires = { 'nvim-lua/plenary.nvim', 'nvim-tree/nvim-web-devicons' },
-- Lazy loading on 'VimEnter' event is necessary.
event = 'VimEnter',
config = function() require("vgit").setup() end,
}
Using lazy.nvim
{
'tanvirtin/vgit.nvim',
dependencies = { 'nvim-lua/plenary.nvim', 'nvim-tree/nvim-web-devicons' },
-- Lazy loading on 'VimEnter' event is necessary.
event = 'VimEnter',
config = function() require("vgit").setup() end,
}
Setup
You must instantiate the plugin in order for the features to work.
require('vgit').setup()
[!NOTE] Highlights, signs, keymappings are few examples of what can be configured in VGit. Advanced setting should only be used if you intend to change functionality provided by default.
<details><summary><b>Show advanced setup</b></summary>
require('vgit').setup({
keymaps = {
['n <C-k>'] = function() require('vgit').hunk_up() end,
{
mode = 'n',
key = '<C-j>',
handler = 'hunk_down',
desc = 'Go down in the direction of the hunk',
}
['n <leader>gs'] = function() require('vgit').buffer_hunk_stage() end,
['n <leader>gr'] = function() require('vgit').buffer_hunk_reset() end,
['n <leader>gp'] = function() require('vgit').buffer_hunk_preview() end,
['n <leader>gb'] = 'buffer_blame_preview',
['n <leader>gf'] = function() require('vgit').buffer_diff_preview() end,
['n <leader>gh'] = function() require('vgit').buffer_history_preview() end,
['n <leader>gu'] = function() require('vgit').buffer_reset() end,
['n <leader>gd'] = function() require('vgit').project_diff_preview() end,
['n <leader>gx'] = function() require('vgit').toggle_diff_preference() end,
},
settings = {
-- You can either allow corresponding mapping for existing hl, or re-define them yourself entirely.
hls = {
GitCount = 'Keyword',
GitSymbol = 'CursorLineNr',
GitTitle = 'Directory',
GitSelected = 'QuickfixLine',
GitBackground = 'Normal',
GitAppBar = 'StatusLine',
GitHeader = 'NormalFloat',
GitFooter = 'NormalFloat',
GitBorder = 'LineNr',
GitLineNr = 'LineNr',
GitComment = 'Comment',
GitSignsAdd = {
gui = nil,
fg = '#d7ffaf',
bg = nil,
sp = nil,
override = false,
},
GitSignsChange = {
gui = nil,
fg = '#7AA6DA',
bg = nil,
sp = nil,
override = false,
},
GitSignsDelete = {
gui = nil,
fg = '#e95678',
bg = nil,
sp = nil,
override = false,
},
GitSignsAddLn = 'DiffAdd',
GitSignsDeleteLn = 'DiffDelete',
GitWordAdd = {
gui = nil,
fg = nil,
bg = '#5d7a22',
sp = nil,
override = false,
},
GitWordDelete = {
gui = nil,
fg = nil,
bg = '#960f3d',
sp = nil,
override = false,
},
GitConflictCurrentMark = 'DiffAdd',
GitConflictAncestorMark = 'Visual',
GitConflictIncomingMark = 'DiffChange',
GitConflictCurrent = 'DiffAdd',
GitConflictAncestor = 'Visual',
GitConflictMiddle = 'Visual',
GitConflictIncoming = 'DiffChange',
},
live_blame = {
enabled = true,
format = function(blame, git_config)
local config_author = git_config['user.name']
local author = blame.author
if config_author == author then
author = 'You'
end
local time = os.difftime(os.time(), blame.author_time)
/ (60 * 60 * 24 * 30 * 12)
local time_divisions = {
{ 1, 'years' },
{ 12, 'months' },
{ 30, 'days' },
{ 24, 'hours' },
{ 60, 'minutes' },
{ 60, 'seconds' },
}
local counter = 1
local time_division = time_divisions[counter]
local time_boundary = time_division[1]
local time_postfix = time_division[2]
while time < 1 and counter ~= #time_divisions do
time_division = time_divisions[counter]
time_boundary = time_division[1]
time_postfix = time_division[2]
time = time * time_boundary
counter = counter + 1
end
local commit_message = blame.commit_message
if not blame.committed then
author = 'You'
commit_message = 'Uncommitted changes'
return string.format(' %s • %s', author, commit_message)
end
local max_commit_message_length = 255
if #commit_message > max_commit_message_length then
commit_message = commit_message:sub(1, max_commit_message_length) .. '...'
end
return string.format(
' %s, %s • %s',
author,
string.format(
'%s %s ago',
time >= 0 and math.floor(time + 0.5) or math.ceil(time - 0.5),
time_postfix
),
commit_message
)
end,
},
live_gutter = {
enabled = true,
edge_navigation = true, -- This allows users to navigate within a hunk
},
scene = {
diff_preference = 'unified', -- unified or split
keymaps = {
quit = 'q'
}
},
diff_preview = {
keymaps = {
reset = 'r',
buffer_stage = 'S',
buffer_unstage = 'U',
buffer_hunk_stage = 's',
buffer_hunk_unstage = 'u',
toggle_view = 't',
},
},
project_diff_preview = {
keymaps = {
commit = 'C',
buffer_stage = 's',
buffer_unstage = 'u',
buffer_hunk_stage = 'gs',
buffer_hunk_unstage = 'gu',
buffer_reset = 'r',
stage_all = 'S',
unstage_all = 'U',
reset_all = 'R',
},
},
project_stash_preview = {
keymaps = {
add = 'A',
apply = 'a',
pop = 'p',
drop = 'd',
clear = 'C'
},
},
project_logs_preview = {
keymaps = {
previous = '-',
next = '=',
},
},
project_commit_preview = {
keymaps = {
save = 'S',
},
},
signs = {
priority = 10,
definitions = {
-- The sign definitions you provide will automatically be instantiated for you.
GitConflictCurrentMark = {
linehl = 'GitConflictCurrentMark',
Related Skills
apple-reminders
347.0kManage Apple Reminders via remindctl CLI (list, add, edit, complete, delete). Supports lists, date filters, and JSON/plain output.
gh-issues
347.0kFetch GitHub issues, spawn sub-agents to implement fixes and open PRs, then monitor and address PR review comments. Usage: /gh-issues [owner/repo] [--label bug] [--limit 5] [--milestone v1.0] [--assignee @me] [--fork user/repo] [--watch] [--interval 5] [--reviews-only] [--cron] [--dry-run] [--model glm-5] [--notify-channel -1002381931352]
healthcheck
347.0kHost security hardening and risk-tolerance configuration for OpenClaw deployments
node-connect
347.0kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
