mini.git documentation
Generated from the main
branch of ‘mini.nvim’
mini.git Git integration
MIT License Copyright (c) 2024 Evgeni Chasnovski
Module
Features:
Automated tracking of Git related data: root path, status, HEAD, etc. Exposes buffer-local variables for convenient use in statusline. See MiniGit.enable() and MiniGit.get_buf_data() for more information.
:Git command for executing any
git
call inside file’s repository root with deeper current instance integration (show output as notification/buffer, use to edit commit messages, etc.).Helper functions to inspect Git history:
MiniGit.show_range_history() shows how certain line range evolved.
MiniGit.show_diff_source() shows file state as it was at diff entry.
MiniGit.show_at_cursor() shows Git related data depending on context.
What it doesn’t do:
- Replace fully featured Git client. Rule of thumb: if feature does not rely on a state of current Neovim (opened buffers, etc.), it is out of scope. For more functionality, use either mini.diff or fully featured Git client.
Sources with more details:
Setup
This module needs a setup with require('mini.git').setup({})
(replace {}
with your config
table). It will create global Lua table MiniGit
which you can use for scripting or manually (with :lua MiniGit.*
).
See MiniGit.config for config
structure and default values.
Comparisons
-
Mostly a dedicated Git client, while this module is not (by design).
Provides buffer-local Git data only through fixed statusline component, while this module has richer data in the form of a Lua table.
Both provide :Git command with ‘vim-fugitive’ treating some cases extra specially (like
:Git blame
, etc.), while this module mostly treats all cases the same. See MiniGit-examples for how they can be manually customized. Also this module provides slightly different (usually richer) completion suggestions.
-
- Similar to ‘tpope/vim-fugitive’, but without
:Git
command.
- Similar to ‘tpope/vim-fugitive’, but without
-
- Provides buffer-local Git data with emphasis on granular diff status, while this module is more oriented towards repository and file level data (root, HEAD, file status, etc.). Use mini.diff for diff tracking.
Disabling
To prevent buffer(s) from being tracked, set vim.g.minigit_disable
(globally) or vim.b.minigit_disable
(for a buffer) to true
. Considering high number of different scenarios and customization intentions, writing exact rules for disabling module’s functionality is left to user. See mini.nvim-disabling-recipes for common recipes.
Examples
Statusline component
Tracked buffer data can be used in statusline via vim.b.minigit_summary_string
buffer-local variable. It is expected to be used as is. To show another info, tweak buffer-local variable directly inside MiniGitUpdated
User
event:
-- Use only HEAD name as summary string
local format_summary = function(data)
-- Utilize buffer-local table summary
local summary = vim.b[data.buf].minigit_summary
vim.b[data.buf].minigit_summary_string = summary.head_name or ''
end
local au_opts = { pattern = 'MiniGitUpdated', callback = format_summary }
vim.api.nvim_create_autocmd('User', au_opts)
Tweaking command output
Buffer output of :Git command can be tweaked inside autocommand for MiniGitCommandSplit
User
event (see MiniGit-command-events). For example, to make :vertical Git blame -- %
align blame output with the current window state, use the following code:
local align_blame = function(au_data)
if au_data.data.git_subcommand ~= 'blame' then return end
-- Align blame output with source
local win_src = au_data.data.win_source
vim.wo.wrap = false
vim.fn.winrestview({ topline = vim.fn.line('w0', win_src) })
vim.api.nvim_win_set_cursor(0, { vim.fn.line('.', win_src), 0 })
-- Bind both windows so that they scroll together
vim.wo[win_src].scrollbind, vim.wo.scrollbind = true, true
end
local au_opts = { pattern = 'MiniGitCommandSplit', callback = align_blame }
vim.api.nvim_create_autocmd('User', au_opts)
:Git
The :Git
user command runs git
CLI call with extra integration for currently opened Neovim process:
Command is executed inside repository root of the currently active file (or current-directory if file is not tracked by this module).
Command output is shown either in dedicated buffer in window split or as notification via vim.notify(). Which method is used depends on whether particular Git subcommand is supposed to show data for user to inspect (like
log
,status
, etc.) or not (likecommit
,push
, etc.). This is determined automatically based on the data Git itself provides. Split window is made current after command execution.Use split-related :command-modifiers (:vertical, :horizontal, or :tab) to force output in a particular type of split. Default split direction is controlled by
command.split
in MiniGit.config.Use :silent command modifier to not show any output.
Errors and warnings are always shown as notifications.
See MiniGit-examples for the example of tweaking command output.
Editor for tasks that require interactive user input (like
:Git commit
or:Git rebase --interactive
) is opened inside current session in a separate split. Make modifications as in regular buffer, :write changes followed by :close / :quit for Git CLI command to resume.
Examples of usage:
:Git log --oneline
- show compact log of current repository.:vert Git blame -- %
- show latest commits per line in vertical split.:Git help rebase
- show help page forrebase
subcommand.:Git -C <cwd> status
- executegit status
inside current-directory.
There is also a context aware completion which can be invoked with <Tab>
:
If completed word starts with “-”, options for the current Git subcommand are shown. Like completion at
:Git log -
will suggest-L
,--oneline
, etc.If there is an explicit ” – ” to the cursor’s left, incremental path suggestions will be shown.
If there is no recognized Git subcommand yet, show list of subcommands. Otherwise for some common subcommands list of its targets will be suggested: like for
:Git branch
it will be list of branches, etc.
Notes:
Paths are always treated as relative to command’s execution directory (file’s repository root or current-directory if absent).
Don’t use quotes for entries containing space, escape it with
\
directly. Like:Git commit -m Hello\ world
and not:Git commit -m 'Hello world'
(which treats'Hello
andworld'
as separate arguments).
Events
There are several User
events triggered during command execution:
MiniGitCommandDone
- after command is done executing. For Lua callbacks it provides a specialdata
table with the following fields:<cmd_input>
(table)
- structured data about executed command. Has same structure as Lua function input in nvim_create_user_command().<cwd>
(string)
- directory path inside which Git command was executed.<exit_code>
(number)
- exit code of CLI process.<git_command>
(table)
- array with arguments of full executed command.<git_subcommand>
(string)
- detected Git subcommand (like “log”, etc.).<stderr>
(string)
-stderr
process output.<stdout>
(string)
-stdout
process output.
MiniGitCommandSplit
- after command showed its output in a split. Triggered afterMiniGitCommandDone
and provides similardata
table with extra fields:<win_source>
(number)
- window identifier of “source” window (current at the moment before command execution).<win_stdout>
(number)
- window identifier of command output.
setup()
MiniGit.setup
({config})
Module setup
Besides general side effects (see mini.nvim), it also:
Sets up auto enabling in every normal buffer for an actual file on disk.
Creates :Git command.
Parameters
{config} (table|nil)
Module config table. See MiniGit.config.
Usage
require('mini.git').setup() -- use default config
-- OR
require('mini.git').setup({}) -- replace {} with your config table
config
MiniGit.config
Defaults
MiniGit.config = {
-- General CLI execution
job = {
-- Path to Git executable
git_executable = 'git',
-- Timeout (in ms) for each job before force quit
timeout = 30000,
},
-- Options for `:Git` command
command = {
-- Default split direction
split = 'auto',
},
}
Job
config.job
contains options for customizing CLI executions.
job.git_executable
defines a full path to Git executable. Default: “git”.
job.timeout
is a duration (in ms) from job start until it is forced to stop. Default: 30000.
Command
config.command
contains options for customizing :Git command.
command.split
defines default split direction for :Git command output. Can be one of “horizontal”, “vertical”, “tab”, or “auto”. Value “auto” uses :vertical if only ‘mini.git’ buffers are shown in the tabpage and :tab otherwise. Default: “auto”.
show_at_cursor()
MiniGit.show_at_cursor
({opts})
Show Git related data at cursor
If inside mini.deps confirmation buffer, show in split relevant commit data.
If there is a commit-like <cword>, show it in split.
If possible, show diff source via MiniGit.show_diff_source().
If possible, show range history via MiniGit.show_range_history().
Otherwise throw an error.
Parameters
{opts} (table|nil)
Options. Possible values:
<split>
(string)
- split direction. One of “horizontal”, “vertical”, “tab”, or “auto” (default). Value “auto” uses :vertical if only ‘mini.git’ buffers are shown in the tabpage and :tab otherwise.Fields appropriate for forwarding to other functions.
show_diff_source()
MiniGit.show_diff_source
({opts})
Show diff source
When buffer contains text formatted as unified patch (like after :Git log --patch
, :Git diff
, or MiniGit.show_range_history()), show state of the file at the particular state. Target commit/state, path, and line number are deduced from cursor position.
Notes:
Needs current-directory to be the Git root for relative paths to work.
Needs cursor to be inside hunk lines or on “—” / “+++” lines with paths.
Only basic forms of
:Git diff
output is supported::Git diff
,:Git diff --cached
, and:Git diff <commit>
.
Parameters
{opts} (table|nil)
Options. Possible values:
<split>
(string)
- split direction. One of “horizontal”, “vertical”, “tab”, or “auto” (default). Value “auto” uses :vertical if only ‘mini.git’ buffers are shown in the tabpage and :tab otherwise.<target>
(string)
- which file state to show. One of “before”, “after”, “both” (both states in vertical split), “auto” (default). Value “auto” shows “before” state if cursor line starts with “-”, otherwise - “after”.
show_range_history()
MiniGit.show_range_history
({opts})
Show range history
Compute and show in split data about how particular line range in current buffer evolved through Git history. Essentially a git log
with -L
flag.
Notes:
Works well with MiniGit.diff_foldexpr().
Does not work if there are uncommited changes, as there is no easy way to compute effective range line numbers.
Parameters
{opts} (table|nil)
Options. Possible fields:
<line_start>
(number)
- range start line.<line_end>
(number)
- range end line. If both <line_start> and <line_end> are not supplied, they default to current line in Normal mode and visual selection in Visual mode.<log_args>
(table)
- array of options to append togit log
call.<split>
(string)
- split direction. One of “horizontal”, “vertical”, “tab”, or “auto” (default). Value “auto” uses :vertical if only ‘mini.git’ buffers are shown in the tabpage and :tab otherwise.
diff_foldexpr()
MiniGit.diff_foldexpr
({lnum})
Fold expression for Git logs
Folds contents of hunks, file patches, and log entries in unified diff. Useful for filetypes “diff” (like after :Git diff
) and “git” (like after :Git log --patch
or :Git show
for commit). Works well with MiniGit.show_range_history().
General idea of folding levels (use zr and zm to adjust interactively):
At level 0 there is one line per whole patch or log entry.
At level 1 there is one line per patched file.
At level 2 there is one line per hunk.
At level 3 there is no folds.
For automated setup, set the following for “git” and “diff” filetypes (either inside FileType autocommand or ftplugin):
setlocal foldmethod=expr foldexpr=v:lua.MiniGit.diff_foldexpr()
Parameters
{lnum} (number|nil)
Line number for which fold level is computed. Default: v:lnum.
Return
(number|string)
Line fold level. See fold-expr.
enable()
MiniGit.enable
({buf_id})
Enable Git tracking in a file buffer
Tracking is done by reacting to changes in file content or file’s repository in the form of keeping buffer data up to date. The data can be used via:
MiniGit.get_buf_data(). See its help for a list of actually tracked data.
vim.b.minigit_summary
(table) andvim.b.minigit_summary_string
(string) buffer-local variables which are more suitable for statusline.vim.b.minigit_summary_string
contains information about HEAD, file status, and in progress action (see MiniGit.get_buf_data() for more details). See MiniGit-examples for how it can be tweaked and used in statusline.
Note: this function is called automatically for all new normal buffers. Use it explicitly if buffer was disabled.
User
event MiniGitUpdated
is triggered whenever tracking data is updated. Note that not all data listed in MiniGit.get_buf_data() can be present (yet) at the point of event being triggered.
Parameters
{buf_id} (number)
Target buffer identifier. Default: 0 for current buffer.
disable()
MiniGit.disable
({buf_id})
Disable Git tracking in buffer
Parameters
{buf_id} (number)
Target buffer identifier. Default: 0 for current buffer.
toggle()
MiniGit.toggle
({buf_id})
Toggle Git tracking in buffer
Enable if disabled, disable if enabled.
Parameters
{buf_id} (number)
Target buffer identifier. Default: 0 for current buffer.
get_buf_data()
MiniGit.get_buf_data
({buf_id})
Get buffer data
Parameters
{buf_id} (number)
Target buffer identifier. Default: 0 for current buffer.
Return
(table|nil)
Table with buffer Git data or nil
if buffer is not enabled. If the file is not part of Git repo, table will be empty. Table has the following fields:
<repo>
(string)
- full path to ‘.git’ directory.<root>
(string)
- full path to worktree root.<head>
(string)
- full commit of current HEAD.<head_name>
(string)
- short name of current HEAD (like “master”). For detached HEAD it is “HEAD”.<status>
(string)
- two character file status as returned bygit status
.<in_progress>
(string)
- name of action(s) currently in progress (bisect, merge, etc.). Can be a combination of those separated by “,”.