/gitsigns.nvim

Git signs written in pure lua

Primary LanguageLuaMIT LicenseMIT

gitsigns.nvim

CI Version License: MIT Gitter

Super fast git decorations implemented purely in lua/teal.

Preview

Hunk Actions Line Blame

Features

  • Signs for added, removed, and changed lines
  • Asynchronous using luv
  • Navigation between hunks
  • Stage hunks (with undo)
  • Preview diffs of hunks (with word diff)
  • Customisable (signs, highlights, mappings, etc)
  • Status bar integration
  • Git blame a specific line using virtual text.
  • Hunk text object
  • Automatically follow files moved in the index.
  • Live intra-line word diff
  • Support for yadm

Requirements

  • Neovim >= 0.5.0
  • Newish version of git. Older versions may not work with some features.

Installation

packer.nvim:

use {
  'lewis6991/gitsigns.nvim',
  requires = {
    'nvim-lua/plenary.nvim'
  }
}

vim-plug:

Plug 'nvim-lua/plenary.nvim'
Plug 'lewis6991/gitsigns.nvim'

Usage

For basic setup with all batteries included:

require('gitsigns').setup()

If using packer.nvim gitsigns can be setup directly in the plugin spec:

use {
  'lewis6991/gitsigns.nvim',
  requires = {
    'nvim-lua/plenary.nvim'
  },
  config = function()
    require('gitsigns').setup()
  end
}

Configuration can be passed to the setup function. Here is an example with most of the default settings:

require('gitsigns').setup {
  signs = {
    add          = {hl = 'GitSignsAdd'   , text = '', numhl='GitSignsAddNr'   , linehl='GitSignsAddLn'},
    change       = {hl = 'GitSignsChange', text = '', numhl='GitSignsChangeNr', linehl='GitSignsChangeLn'},
    delete       = {hl = 'GitSignsDelete', text = '_', numhl='GitSignsDeleteNr', linehl='GitSignsDeleteLn'},
    topdelete    = {hl = 'GitSignsDelete', text = '', numhl='GitSignsDeleteNr', linehl='GitSignsDeleteLn'},
    changedelete = {hl = 'GitSignsChange', text = '~', numhl='GitSignsChangeNr', linehl='GitSignsChangeLn'},
  },
  numhl = false,
  linehl = false,
  keymaps = {
    -- Default keymap options
    noremap = true,
    buffer = true,

    ['n ]c'] = { expr = true, "&diff ? ']c' : '<cmd>lua require\"gitsigns.actions\".next_hunk()<CR>'"},
    ['n [c'] = { expr = true, "&diff ? '[c' : '<cmd>lua require\"gitsigns.actions\".prev_hunk()<CR>'"},

    ['n <leader>hs'] = '<cmd>lua require"gitsigns".stage_hunk()<CR>',
    ['v <leader>hs'] = '<cmd>lua require"gitsigns".stage_hunk({vim.fn.line("."), vim.fn.line("v")})<CR>',
    ['n <leader>hu'] = '<cmd>lua require"gitsigns".undo_stage_hunk()<CR>',
    ['n <leader>hr'] = '<cmd>lua require"gitsigns".reset_hunk()<CR>',
    ['v <leader>hr'] = '<cmd>lua require"gitsigns".reset_hunk({vim.fn.line("."), vim.fn.line("v")})<CR>',
    ['n <leader>hR'] = '<cmd>lua require"gitsigns".reset_buffer()<CR>',
    ['n <leader>hp'] = '<cmd>lua require"gitsigns".preview_hunk()<CR>',
    ['n <leader>hb'] = '<cmd>lua require"gitsigns".blame_line(true)<CR>',

    -- Text objects
    ['o ih'] = ':<C-U>lua require"gitsigns.actions".select_hunk()<CR>',
    ['x ih'] = ':<C-U>lua require"gitsigns.actions".select_hunk()<CR>'
  },
  watch_index = {
    interval = 1000,
    follow_files = true
  },
  current_line_blame = false,
  current_line_blame_delay = 1000,
  current_line_blame_position = 'eol',
  sign_priority = 6,
  update_debounce = 100,
  status_formatter = nil, -- Use default
  word_diff = false,
  use_decoration_api = true,
  use_internal_diff = true,  -- If luajit is present
}

For information on configuring neovim via lua please see nvim-lua-guide.

Status Line

Use b:gitsigns_status or b:gitsigns_status_dict. b:gitsigns_status is formatted using config.status_formatter. b:gitsigns_status_dict is a dictionary with the keys added, removed, changed and head.

Example:

set statusline+=%{get(b:,'gitsigns_status','')}

For the current branch use the variable b:gitsigns_head.

TODO

  • Add ability to show staged hunks with different signs (maybe in a different sign column?)
  • Add ability to show commit in floating window of current line
  • Allow extra options to be passed to git diff
  • Folding of text around hunks
  • Show messages when navigating hunks similar to '/' search
  • Stage partial hunks
  • Add hunks to quickfix/location list

Comparison with vim-gitgutter

Feature gitsigns gitgutter Note
Shows signs for added, modified, and removed lines
Asynchronous
Runs diffs in-process (no IO or pipes) ✅ * * Via FFI and soon via lua
Only adds signs for drawn lines ✅ * * Via Neovims decoration API
Updates immediately * * Triggered on CursorHold
Ensures signs are always up to date ✅ * * Watches the git index to do so
Never saves the buffer ✅ ❗ * * Writes buffer (and index) to short lived temp files
Quick jumping between hunks
Stage/reset/preview individual hunks
Stage/reset hunks in range/selection ✅ ❗ * * Only stage
Stage/reset all hunks in buffer
Undo staged hunks
Word diff in buffer
Word diff in hunk preview
Stage partial hunks
Hunk text object
Diff against index or any commit
Folding of unchanged text
Fold text showing whether folded lines have been changed
Load hunk locations into the quickfix or location list
Optional line highlighting
Optional line number highlighting
Optional counts on signs
Customizable signs and mappings
Customizable extra git-diff arguments
Can be toggled globally or per buffer ✅ * * Through the detach/attach functions
Statusline integration
Works with yadm
Live blame in buffer (using virtual text)
Blame preview
Automatically follows open files moved with git mv
CLI with completion * * Provides individual commands for some actions
Open diffview with any revision/commit

As of 2021-07-05

Similar plugins