Open-source project
tanvirtin/vgit.nvim avatar
tanvirtin/vgit.nvim

vgit.nvim: a visual git layer for Neovim

Visual git plugin for Neovim

847 stars24 forksLuaMIT

At a glance

What is it?
VGit turns Neovim into a git client with a set of floating preview windows for diffs, logs, stashes, blame and conflict resolution, written in Lua on top of plenary.nvim. It is MIT licensed and needs Neovim 0.10 or newer, but it only runs on Linux and macOS and it does not do anything a terminal git client does not already do.
Who is it for?
Adopt vgit.nvim if you already live in Neovim, want to review diffs, stashes and history without leaving the editor, and run on Linux or macOS with Neovim 0.10 or newer. Do not adopt it on Windows, since the supported operating systems are listed as linux-gnu variants and Darwin, and skip it if you want git push, pull or branch management, because the feature set is entirely about viewing and reviewing.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Lua, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A git client that lives inside the editor

VGit is a visual git plugin for Neovim, written in Lua, and the pitch in the README is that its feature views are designed to be lightning-fast whether you are diving into a file's history, comparing changes or managing stashes.

The problem it addresses is narrow and real. Git's default interfaces are a terminal, a pager and a diff tool, and all three pull you out of the editor. A review session in a real project is not one diff, it is a sequence: look at what changed in the working tree, check a suspicious file against the index, look at when a line was last touched, see what is in the stash, then resolve a conflict. Each of those steps in stock git means leaving your buffer and re-entering later with your place in the file lost.

VGit's answer is a set of preview surfaces rather than a new mental model. There is a project diff preview that shows modified files and highlights the changes. A project logs preview for viewing and filtering the logs of the current branch, where you select a log and open a detailed commit preview. A project stash preview for managing stashed changes in one place. A buffer diff preview comparing the current buffer with its version in the Git index, which zooms into the relevant changes when a hunk is focused. A buffer blame preview giving the author and commit history of a line. A buffer history preview showing all the Git iterations of a file across commits.

Two features go beyond viewing. Conflict management highlights the different segments of a conflict and lets you choose the changes you want, so a merge conflict is resolved inside a buffer. And live blame puts author and commit annotations directly in the editor, updating in real time, so you can read code and its provenance at once without opening anything.

None of this is git functionality that does not exist elsewhere. It is the same git, presented through Neovim's buffer and floating window model, which is a legitimate choice for people whose entire working day happens in one application.

Requirements narrow the audience on purpose

The requirements are stated compactly and they cut in specific directions.

Neovim 0.10 or newer is required, and the README badge states Neovim 0.8+, so the badge is out of date relative to the documented requirement. Git 2.18.0 or newer is the other hard floor, which is a fairly recent version number and suggests the plugin relies on git features that older releases do not have.

The supported operating systems are listed as linux-gnu variants and Darwin. That is a genuine limit, not an oversight, and it means there is no Windows support. For a plugin that spawns git and parses its output, the platform differences on Windows are the usual reason for such a list, but the consequence for a user is simple: this does not run on Windows.

The two plugins the project depends on are nvim-lua/plenary.nvim and nvim-tree/nvim-web-devicons. Plenary is a general utility library for Neovim plugins and is where the async and job control come from, and nvim-web-devicons provides the file type icons you see in the file trees inside the preview windows. Depending on devicons means the preview windows look like the rest of a modern Neovim setup rather than showing generic file names.

The installation section also carries a note that package managers with lazy loading is necessary for installation, and the reason is given in the configuration snippets themselves: lazy loading on the VimEnter event is necessary. The plugin's own code comments say so in both the packer.nvim and lazy.nvim examples.

That constraint has a rationale. VGit shells out to git and renders results, and doing that work on startup for a plugin whose features are invoked rarely would be wasted. Deferring the load to VimEnter is the plugin author's way of keeping the cost off the critical path, and the instruction to use a lazy loading package manager is really a statement that a plain copy-paste into init.lua is not the supported path.

Installing with lazy.nvim and calling setup

The lazy.nvim snippet is the shortest of the two documented installs:

lua
{
  '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,
}

The packer.nvim form is the same idea with packer's own syntax, using use with a requires key for the dependencies and the same event and config.

The setup call is mandatory in a way that is unusual for Neovim plugins. The documentation says you must instantiate the plugin in order for the features to work, and the minimal form is:

lua
require('vgit').setup()

That line is not a formality. The advanced configuration block in the README is a single call with a table argument, and the default call enables the defaults, so skipping it means the keymaps and highlights the plugin relies on are never created and nothing happens when you press the keys.

The default experience is therefore a set of keymaps already bound by the plugin, which the documentation confirms by pointing out that highlights, signs and keymappings are a few examples of what can be configured, and that advanced settings should only be used if you intend to change functionality provided by default. That last sentence is a warning worth respecting. The default keymap set is what the screenshots in the README show, and a large table of custom mappings is the most common way to end up with a plugin that behaves differently from the documentation you read.

What the advanced setup actually changes

The advanced configuration is worth reading even if you never use it, because it documents what the plugin is doing to your editor.

The keymaps table maps a mode and key to either a function or a named handler. The examples show a function form, where the key is written inline with the mode prefix, and a table form with separate mode, key, handler and desc fields, which is the form that gives you a description in the which-key style popup. The handlers visible in the example are hunk_up, hunk_down, buffer_hunk_stage, buffer_hunk_reset, buffer_hunk_preview, buffer_diff_preview, buffer_history_preview, buffer_reset, project_diff_preview and toggle_diff_preference, alongside buffer_blame_preview given as a plain string handler name.

That set tells you the operating model. Hunk level operations move up and down between hunks, stage and reset hunks individually, and preview the hunk under the cursor. Buffer level operations diff the buffer against the index, show its history, blame it, or reset it. Project level operations show the whole project diff. And toggle_diff_preference switches the diff algorithm the preview uses, which is the kind of control that only matters to people who have strong opinions about diff output.

The settings table is mostly visual, and it is long enough that copying it wholesale is a mistake. The hls group defines highlight groups, each mapped to an existing Neovim highlight by default, and the comment explains that you can either allow the corresponding mapping for an existing hl or redefine them entirely. The named groups cover the app chrome, GitCount, GitSymbol, GitTitle, GitSelected, GitBackground, GitAppBar, GitHeader, GitFooter, GitBorder, GitLineNr and GitComment, plus the conflict markers GitConflictCurrent, GitConflictAncestor, GitConflictMiddle and GitConflictIncoming, which are mapped to DiffAdd, Visual, Visual and DiffChange respectively.

The sign definitions are the part most likely to clash with an existing colorscheme. GitSignsAdd, GitSignsChange and GitSignsDelete each carry a gui, fg, bg, sp and override field, and the defaults set explicit hex foreground colors such as '#d7ffaf' for added lines, '#7AA6DA' for changed and '#e95678' for deleted. The word diff adds and deletes carry background colors '#5d7a22' and '#960f3d'. If your theme already defines these, the override flag decides who wins, and getting that wrong is how a plugin ends up with invisible text in a diff.

The live_blame group has an enabled flag and a format function taking the blame and the git config, which is where you control what annotation text is produced.

Where the plugin stops, and what to compare it against

The scope is entirely review, and that is a limit rather than a gap.

There is no push, no pull, no fetch, no branch creation, no staging of whole files at project level, no rebase, no stash creation. The feature list is about viewing, comparing and resolving. If your git workflow involves a lot of porcelain, VGit does not cover it, and you would keep a terminal open beside the editor anyway.

The dependency on plenary is worth understanding. Plenary provides the job control and async primitives the plugin uses to run git and stream results. That is a reasonable choice, since writing a portable async job runner in Lua is a project in itself. It also means the plugin inherits plenary's version compatibility, so a plenary update is a potential vgit update in practice.

The platform limit is the harder constraint. Linux and macOS only, and the reason the documentation does not give is simply that the supported list stops there.

The alternatives fall into three groups. The first is the stock terminal, which is what vgit.nvim is a replacement for, and the comparison is not really about features but about context switching. The second is fugitive.nvim, the long established Neovim git plugin, which covers a much wider set of git operations through Vim-style commands and buffers rather than through graphical previews. The third is the newer wave of Neovim git UIs that render diffs and logs in a floating panel with a status bar and keymap hints, which is the closest thing to a direct comparison in approach. The difference between VGit and that group is mostly in the surface: VGit's previews are themed panels with configurable highlight groups and signs rather than a single unified dashboard, and its conflict handling is buffer oriented, so you resolve a conflict in the file itself.

There is also the option of not adding a plugin at all. If you already live in a terminal multiplexer with a good pager, a diff tool and lazygit, you have the same workflow with less configuration and no Neovim version floor to worry about.

Maintenance, licence and the project layout

The repository is not archived and the last push was on 2026-10-18, so the project is being worked on. The listed releases are v1.0.6 from 2025-02-06, v1.0.5 from 2025-02-05 and v1.0.4 from 2025-02-05, three patch releases within two days of each other, which is the pattern of a bug fix round rather than a feature release.

That combination, a 1.x version line, regular commits and infrequent tagged releases, is typical of a Neovim plugin. The version number in the plugin manager is what matters for reproducibility, and pinning to a tag is the way to avoid a plugin change arriving mid session.

The licence is MIT, with the LICENSE file at the repository root, and the README carries the badge. MIT is the norm for Neovim plugins and carries no obligation for a user.

The layout is the interesting part for anyone reading the source. The lua directory holds the plugin code in the conventional Neovim layout, with the doc directory holding the vim help documentation, and tests alongside. There is a .luacheckrc, which is the Lua linter configuration, and a stylua.toml plus a .styluaignore, which is the formatter configuration, so the code is checked and formatted automatically. The .github directory holds the workflows, and the CI badge in the README confirms that the test suite runs on pushes.

The type information is the other notable choice. The setup configuration passes functions and tables of Lua values rather than a schema, and the README notes that highlights, signs and keymappings are a few examples of what can be configured. There is no JSON schema or typed configuration in the documentation, so your editor cannot validate the settings table for you, and a typo in a highlight group name fails silently. That is the main practical cost of the open ended configuration approach, and it is why starting from the defaults is the safer path.

Editorial conclusion

Adopt vgit.nvim if you already live in Neovim, want to review diffs, stashes and history without leaving the editor, and run on Linux or macOS with Neovim 0.10 or newer. Do not adopt it on Windows, since the supported operating systems are listed as linux-gnu variants and Darwin, and skip it if you want git push, pull or branch management, because the feature set is entirely about viewing and reviewing. Verify first that your git version is 2.18.0 or newer, that you install it with a lazy loading package manager as the documentation insists, and that the highlight groups it sets do not fight the ones your colorscheme already defines.

Frequently asked questions

What are the requirements for vgit.nvim?

Neovim 0.10 or newer, Git 2.18.0 or newer, and a supported operating system, which the README lists as linux-gnu variants and Darwin. The plugin also depends on nvim-lua/plenary.nvim and nvim-tree/nvim-web-devicons.

How do I install vgit.nvim with lazy.nvim?

Add the plugin spec with 'tanvirtin/vgit.nvim', the dependencies list, event = 'VimEnter' for lazy loading and a config function calling require("vgit").setup(). The README notes that lazy loading on the VimEnter event is necessary and that a lazy loading package manager is required.

Do I have to call setup() for vgit.nvim to work?

Yes. The documentation says you must instantiate the plugin in order for the features to work, and the minimal form is `require('vgit').setup()`, which enables the default keymaps and highlights.

Can vgit.nvim resolve merge conflicts?

Yes. The conflict management feature highlights the different segments of a conflict and lets you choose the changes you need, so conflicts are resolved in the buffer rather than in an external tool.

Does vgit.nvim work on Windows?

No. The supported operating systems listed in the requirements are the linux-gnu variants and Darwin, so Windows is outside the supported set.

What license is vgit.nvim released under?

MIT, with the LICENSE file at the repository root and the badge in the README.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. tanvirtin/vgit.nvim on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/tanvirtin-vgit-nvim.svg)](https://hysenlabs.com/projects/tanvirtin-vgit-nvim)

Was this useful?