Git Integration

Version control is woven into nearly every moment of a developer's day, and constantly switching between your editor and a terminal for git commands creates friction that adds up. By bringing Git directly into Neovim, you can see what's changed at a glance, stage hunks with precision, resolve conflicts in context, and browse history -- all without breaking your editing flow.

Neovim has excellent Git integration through plugins. This chapter covers the most essential tools for a Git workflow without leaving your editor.

What you'll learn in this chapter:

  • Configure gitsigns.nvim to display inline diff markers and perform hunk-level staging

  • Use fugitive.vim or Neogit to run Git commands without leaving Neovim

  • Browse file history and view side-by-side diffs with diffview.nvim

  • Build an efficient end-to-end Git workflow entirely within your editor

  • Navigate between changed hunks and use the hunk text object for precise edits

gitsigns.nvim: Inline Git Information

gitsigns.nvimarrow-up-right shows git diff markers in the sign column and provides hunk-level operations. All Git plugins in this chapter are installed through a plugin manager (see Plugin Management).

-- lua/plugins/git.lua
return {
    {
        'lewis6991/gitsigns.nvim',
        event = { 'BufReadPre', 'BufNewFile' },
        opts = {
            signs = {
                add          = { text = '' },
                change       = { text = '' },
                delete       = { text = '_' },
                topdelete    = { text = '' },
                changedelete = { text = '~' },
            },
            on_attach = function(bufnr)
                local gs = package.loaded.gitsigns
                local map = function(mode, l, r, desc)
                    vim.keymap.set(mode, l, r, { buffer = bufnr, desc = desc })
                end

                -- Navigation between hunks
                map('n', ']h', gs.next_hunk, 'Next hunk')
                map('n', '[h', gs.prev_hunk, 'Previous hunk')

                -- Actions
                map('n', '<leader>hs', gs.stage_hunk, 'Stage hunk')
                map('n', '<leader>hr', gs.reset_hunk, 'Reset hunk')
                map('v', '<leader>hs', function()
                    gs.stage_hunk({ vim.fn.line('.'), vim.fn.line('v') })
                end, 'Stage selected hunk')
                map('v', '<leader>hr', function()
                    gs.reset_hunk({ vim.fn.line('.'), vim.fn.line('v') })
                end, 'Reset selected hunk')
                map('n', '<leader>hS', gs.stage_buffer, 'Stage buffer')
                map('n', '<leader>hu', gs.undo_stage_hunk, 'Undo stage hunk')
                map('n', '<leader>hR', gs.reset_buffer, 'Reset buffer')
                map('n', '<leader>hp', gs.preview_hunk, 'Preview hunk')
                map('n', '<leader>hb', function()
                    gs.blame_line({ full = true })
                end, 'Blame line')
                map('n', '<leader>tb', gs.toggle_current_line_blame, 'Toggle line blame')
                map('n', '<leader>hd', gs.diffthis, 'Diff this')

                -- Text object: select hunk
                map({ 'o', 'x' }, 'ih', ':<C-U>Gitsigns select_hunk<CR>', 'Select hunk')
            end,
        },
    },
}

Key Features

  • Sign column markers: See added, modified, and deleted lines at a glance

  • Hunk navigation: Jump between changes with ]h and [h

  • Stage/unstage hunks: Stage individual changes without leaving Neovim

  • Inline blame: See who changed each line and when

  • Hunk text object: ih lets you operate on a hunk (e.g., dih to delete a hunk)

fugitive.vim or neogit: Git Commands

vim-fugitive (Works in Vim and Neovim)

vim-fugitivearrow-up-right by Tim Pope is the classic Git plugin:

Common commands:

Command
What it does

:Git or :G

Open git status (interactive)

:Git add %

Stage current file

:Git commit

Commit

:Git push

Push

:Git blame

Inline blame for entire file

:Gdiffsplit

Side-by-side diff

:GBrowse

Open file on GitHub

neogit (Neovim-native, Magit-inspired)

Neogitarrow-up-right provides a Magit-like interface:

diffview.nvim: Visual Diffs

diffview.nvimarrow-up-right provides a beautiful diff viewer and file history browser:

Common Workflows

Git Workflow in Neovim

A typical Git workflow using these plugins:

  1. Check status: <leader>gg (Neogit) or :Git (fugitive)

  2. Review changes: ]h / [h to navigate hunks, <leader>hp to preview

  3. Stage changes: <leader>hs to stage hunks, or <leader>hS for entire buffer

  4. View full diff: <leader>gd to open diffview

  5. Commit: :Git commit or use Neogit's commit interface

  6. Push: :Git push or from Neogit

Tip: You can also run Git commands directly in Neovim's built-in terminal (see Terminal & External Commands) or use a dedicated tool like Lazygit in a floating terminal window.

Useful Git Keybindings Summary

Action
Keybinding
Plugin

Next changed hunk

]h

gitsigns

Previous changed hunk

[h

gitsigns

Stage hunk

<leader>hs

gitsigns

Reset hunk

<leader>hr

gitsigns

Preview hunk

<leader>hp

gitsigns

Toggle line blame

<leader>tb

gitsigns

Open git status

<leader>gg

neogit/fugitive

Open diff view

<leader>gd

diffview

File history

<leader>gh

diffview

Summary

With gitsigns.nvim, fugitive.vim (or Neogit), and diffview.nvim, Neovim provides a complete Git workflow where you can inspect changes, stage hunks with precision, browse history, and resolve conflicts -- all without leaving your editor. The hunk-level operations and inline blame make code review and version control feel like a natural part of editing.

Key takeaways:

  • gitsigns.nvim provides sign-column markers and hunk-level operations (]h/[h to navigate, <leader>hs to stage, ih text object to select).

  • fugitive.vim is the battle-tested Git plugin for both Vim and Neovim, while Neogit offers a Magit-inspired Neovim-native alternative.

  • diffview.nvim gives you a visual, side-by-side diff viewer and file history browser that surpasses the built-in diff mode.

  • Combining all three plugins creates a seamless workflow from reviewing changes to committing and pushing.

Exercises

  1. Navigate and preview hunks -- Make a few changes to a Git-tracked file, then use hunk navigation to review each change before staging.

  2. Stage individual hunks -- Make changes in multiple places within a file, then selectively stage only some hunks while leaving others unstaged.

  3. View a side-by-side diff -- Use diffview.nvim to compare your working tree changes against the index, then compare against a specific branch.

  4. View file history -- Browse the commit history of a specific file to see how it evolved over time.

  5. Use inline blame to trace a change -- Enable inline blame to see who last modified the current line, then view the full commit details.

Last updated

Was this helpful?