With vim-fugitive you can perform
almost any Git command from within Vim with :Git
. (realizing full-well that you can shell
out to Git with :!git
and :read !git
) The Fugitive is nicer, and turns commits
into hyperlinks (it's more intuitive to browse interactively).
GitGutter is a Vim plugin that
provides markers in the sign column that marks modified lines. It also provides hunk
text objects ic
and ac
for operating on hunks.
Use ]c
and [c
for jumping between hunks, or use
:GitGutterQuickFix
for loading all hunks into the quickfix list. Hunks can be previewed,
staged, or undone with <leader>hp
, <leader>hs
, or
<leader>hu
respectively.
You can also use :Git add --patch
from Fugitive to stage hunks interactively from within
Vim.
You can use :Git commit
from within Vim, which will open a new window. I don't normally do
this, because I usually keep one or more terminal panes set aside for Git.
I think everyone should set the
commit.verbose
config option, which adds the staged diff to the commit editor. This can really slow down vim for large
commits (but you shouldn't have large commits in the first place!) If you really need to
disable showing this diff in the commit editor, you can commit with
git -c commit.verbose=false commit
.
I highly recommend making commits that touch submodules do nothing but touch the submodule. In the case of adding a new submodule, it should be
git submodule add $REMOTE_URL
git commit
Updating a submodule to a new hash should also be done in its own commit. I do make the concession, however, that this is a questionable practice if you value independently buildable commits (as in, each commit builds and passes the pipeline). Use your best judgment, based on your team's Git values (hopefully they do have values).
# Update the submodule locally
cd $SUBMODULE_PATH
git switch $GIT_BRANCH
git pull
cd -
# Commit the submodule update by itself
git add $SUBMODULE_PATH
git commit
When committing a submodule update like this (as opposed to rewording a commit that updates a submodule as would be common in an interactive rebase) I believe you should always add the submodule changes to the commit for traceability. This can be done from within Vim by
:read !git diff --submodule --staged $SUBMODULE_PATH
Technically, you can leave off the $SUBMODULE_PATH
if you followed my advice that changes
to submodule should be committed by themselves.
:read !git
when squashing two
submodule update commits during an interactive rebase.
You can use gq
to reflow the text in a commit message. Use visual-line mode to select
text to reflow or gqip
to reflow the current paragraph.
Fugitive provides :Git log
(which can accept any of the usual commandline arguments).
Pressing <CR>
on any of the commit hashes will open that commit in a new buffer (a
fancier git-show
).
fzf.vim provides :Commits
and :BCommits
that opens an interactive commit
browser that you can search. Again, pressing <CR>
on a selected commit (or multiple
commits, selected with TAB
in their own buffers.
git-gl
because then I can trigger special sauce on keybinds. See
https://github.com/Notgnoshi/dotfiles/issues/13.
:BCommits
is similar to running :Git log %
. Additionally, you can make a
visual selection. Then, running :BCommits
shows commits that touched that range of lines.
This is an easier-to-browse :Git blame
.
Fugitive provides :Git blame
which nicely wraps git-blame
in a
scroll-synchronized window opened to the side of the current buffer. Pressing <CR>
on
the selected commit will open that commit in a new buffer. Pressing -
will reblame at the
selected commit.
When you open a commit with :Git blame
or similar, you'll see something like
tree d80fb1c28a89bcdf6798dd26f986e1745e207525
parent 4e4ea6709c08807b1d769e89a582720d4e11ebfb
author Austin Gill <Notgnoshi@gmail.com> Sun Jul 25 13:46:12 2021 -0500
committer Austin Gill <Notgnoshi@gmail.com> Mon Aug 30 14:50:15 2021 -0500
which, notably, doesn't include the hash of the displayed commit. To get the hash, do
y<C-G>
to yank the hash. Or, possibly more helpful, as long as you have
system clipboard support, you can do "+y<C-G>
.
Use :Gedit master:%
to open the current file as of the master
revision in a
new buffer. You can do the same with :Git diff master:% %
to the current file against
master
.
TODO: This is something I still have to learn. I typically do
git status
followed by git diff $FILE_WITH_CONFLICTS
in one terminal pane,
and resolve the conflicts manually with Vim in another pane. This isn't a terrible experience, but I
bet it could be better.