4. Add Git Support Through a Plugin Manager
Tags: neovim, vim
Published: 2024-07-06 15:20:41

Now that I have some changes in my `init.lua`, I want them under version control. To do that, I want to have a _plugin_ to support git. But before I do that I want a plugin manager.

While you don't _need_ a plugin manager, it makes life much easier. Btw, most of the time, we talk about a neovim _plugin_, it is actually a neovim _package_. For more information, see `:help packages`.

I will use lazy.nvim as a plugin manager. It seems to be the most widely used currently, and supports
- Lock files, allowing you to go back to a previously working configuration, e.g. when a plugin update broke your config
- Lazy loading non-essential plugins for faster load times.

But it doesn't natively support my desire of being able to reload the configuration ad-hoc. But I can deviate from the standard configuration to help support this use case.
## Bootstrapping Lazy.nvim

Most package managers takes care of downloading plugins from github repositories. But we cannot use the plugin manager to install itself, so first I bootstrap lazy.nvim by explicitly fetching it from git. The code is copy/paste from the installation instructions.

```lua
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
  local lazyrepo = "https://github.com/folke/lazy.nvim.git"
  local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath })
  if vim.v.shell_error ~= 0 then
    vim.api.nvim_echo({
      { "Failed to clone lazy.nvim:\n", "ErrorMsg" },
      { out, "WarningMsg" },
      { "\nPress any key to exit..." },
    }, true, {})
    vim.fn.getchar()
    os.exit(1)
  end
end
vim.opt.rtp:prepend(lazypath)
```

The code clones lazy.nvim from the GitHub repository, and then adds it to the _runtime path_, a list of folders where vim searches for plugins (see `:help runtimepath`)

I use vim-fugitive by the awesome Tim Pope. Remember that name, over the time he has been the author of some of the most amazing vim plugins. Despite fugitive being a very old plugin for legacy vim, it is still _the_ git plugin to use[^1].

```lua
require("lazy").setup({
  "tpope/vim-fugitive"
})
```

I save my configuration (with <kbd>&lt;Ctrl&gt;+s</kbd>) and re-source my configuration with <kbd>&lt;space&gt;vs</kbd>, and lazy will run. It will open the lazy UI showing that fugitive was installed, and lazy loaded ;) It was already _installed_, as we did that from git.

![Screenshot showing lazy.nvim has installed vim-fugitive](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/utk58kich1myws7il18c.png)

Now, I can run `:Git`, or even shorter, `:G`, to open a git status windows, from where you can stage files, hunks, commit, append, etc. Further more, you can postfix the `:Git` command with any valid command line git command. As I have been using git from back when the command line was the only real option, I am very comfortable with this, and I can use that to execute any git command.

Learn about the available commands from the help, `:help fugitive`. Here, I've added the changed and new files, and writing the commit message. As you can see, lazy.nvim created a lock file, pointing to the commit hashes of the packages. As lazy.nvim is a vim package itself, lazy.nvim also keeps track of it's own version. We just needed special code to bootstrap it, but now it's a package maintained by lazy, like any other package.

![Screenshot showing the commit message being written for a new git commit](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uyh0ckiyv0b45ycqjpkq.png)

## Viewing Changes in the Current Buffer

Fugitive is awesome for interacting with git, if you want so see changed lines in buffers, a great plugin to install is gitsigns.

The documentation suggests that I should call `require('gitsigns').setup()` after installation, so I add it to the list of plugins, add that line.

```lua
require("lazy").setup({
  "tpope/vim-fugitive",
  "lewis6991/gitsigns.nvim"
})

require("gitsigns").setup()
```

I re-source the configuration, but that generates a warning and an error.

![Screenshot showing lazy.nvim warning, and a gitsigns initialisation error](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/09dd517xzt7wx9kwt5kd.png)

The warning is that lazy.nvim doesn't support that we re-source the configuration. The error is the configuration of gitsigns, as it hasn't been installed yet.

For now, I will exit and reopen neovim (sigh). Gitsigns gets installed, and now I see the changed and added lines of code directly in my buffer.

![Screenshot showing lines that were modified and added](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b6f6qbv0nlpaae05297p.png)

As always, read the help file for the new plugin to see how you use it, `:help gitsigns`

## Signcolumn configuration

Gitsigns show their symbol in the "signcolumn", a special column shown next to the line numbers. By default, the signcolumn is shown if it contains any content. So after I committed the file, it is now clean, the signs are removed, the column disappear, and all text moves left. As this screenshot shows to buffers not aligned because of uncommitted changes in one buffer.

![Screenshot showing how two buffers are not aligned when one buffer has a uncommitted changes, and the other does not](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rlatu5enj0sfrhsu3xit.png)

I find this jerking around to be annoying, so I want the signcolumn to always be present:

```lua
vim.g.signcolumn="yes"
```

See `:help signcolumn` to learn about the different options.

Note: the signcolumn can be configured differently for each buffer, so reloading the configuration may not have an effect immediately on loaded buffers.
## Coming up

I obviously need to handle new plugins being added, but to do that effectively, I really need to modularise my configuration, so that will be the topic of the next post.

[^1]: You may also want to check out lazygit.nvim[[lazygit.nvim]]lazygit.nvim, which adds more fancy UI than fugitive, but I haven't tried that out myself. First, while the UI is fancier, it doesn't really appear to _solve any problems_, and to me, the simpler UI from fugitive seems more efficient. AFAIK, lazygit also depends on an external program being installed. So to me, fugitive is still _the_ plugin to use.