Want to see the full-length video right now for free?
Git and Vim: two focused tools that work even better together. You're probably familiar with using Vim to compose commit messages, and maybe even a rebase sequence. But there are a few other ways we can combine Vim and Git for even greater productivity.
Fugitive.vim is a Vim plugin by the one and only tpope that brings Git into Vim, allowing us to explore and interact with our git repo from within Vim. In tpope's own words, Fugitive is:
a Git wrapper so awesome, it should be illegal
Fugitive is impressively complete in the features and commands it exposes, so we won't cover all of them, but as an introduction, we can touch on a few of the commands and workflows that we use every day here at thoughtbot.
:Gblame
is a wrapper around the existing git blame
command. When run at the
command line, git blame <file>
will dump out a wall of text displaying the
most recent modifier (commit author) for each line. Unfortunately, this is a
bit hard to work with:
$ git blame Gemfile
fda9ecd3 (Joe Ferris 2014-11-05 13:33:52 -0700 1) source "https://rubygems.org"
ccc4d709 (Chad Pytel 2011-04-29 12:13:58 -0400 2)
875272fa (Arun Agrawal 2015-04-24 13:31:46 +0200 3) ruby "2.2.2"
72a6c828 (Trevor O'Reilly 2012-10-24 13:10:32 -0400 4)
48bbd7b6 (Arun Agrawal 2015-01-20 10:20:34 -0500 5) gem "active_model_serializers", "0.8.3"
48bbd7b6 (Arun Agrawal 2015-01-20 10:20:34 -0500 6) gem "acts_as_list", "~> 0.6.0"
fda9ecd3 (Joe Ferris 2014-11-05 13:33:52 -0700 7) gem "airbrake"
6562f830 (Dan Croak 2014-10-01 13:34:07 -0700 8) gem "analytics-ruby", "~> 2.0.0", require: "segment/analytics"
Instead, with :Gblame
from Fugitive, a new split will open beside the
current file that displays a highlighted version of the git blame
output
aligned with each of the source lines in our file.
Even better, rather than this being a static text dump, as with the default
git blame
output, :Gblame
's output is interactive. Specifically, we can
put our cursor over a commit hash in the blame window and hit <cr>
to jump
to that commit. From there we can read the commit message and see a complete
diff of when this line was updated to its current form.
:Gdiff
wraps the normal git diff
command, but embraces Vim's very nice
split diff display with syntax highlighting and all of the comforts of Vim.
When working on a given file, we can start it with just :Gdiff
and it will
display the diff against the current commit, using Vim's split diff display.
In addition, we can use :Gdiff
to diff against any revision. For instance,
:Gdiff master
will diff against master rather than the most recent commit.
:Gdiff
even supports tab completion of the relevant refs you might want to
use as an argument.
One additional benefit of working within Vim's diff view is that we have
available specific commands for working with the :diffget
and :diffput
commands. These work by pulling or pushing diff sections between the two
versions of the file, allowing you to easily revert changes you've made.
:Gread
will update our buffer to match what the file looked like in the
HEAD commit. This essentially acts as a git checkout <file>
, but while
working within Vim.
Similar to the :Gdiff
command, :Gread
can take an argument of any revision
or branch specifier to pull in the version of the current file as it is in that
revision. For example, using :Gread master
will pull in the version of of the
file on master, essentially resetting our changes on a feature branch.
:Gremove
is a shortcut that performs three actions:
git rm
command to stage the removal of the file.While the first two are straightforward, the git rm
is something I always
forget and have to follow up on later. :Gremove
gives us a single command
that takes care of all three.
:Gmove
also combines multiple actions into a single
command, in this case the steps needed to rename a file.
Specifically, :Gmove full/path/to/new-name.rb
will simultaneously:
git mv
command to inform Git of the rename.:Gstatus
is one of Fugitive's most powerful commands, providing a full
Vim-based interface for viewing and interacting with our status. To start, just
run :Gstatus
and Fugitive will open a split below the current file that
displays the current status. We can then interact with this buffer using a
handful of custom key mappings specific to the status window.
Mapping | Operation |
---|---|
D |
Opens the file in a split diff to review changes. |
- |
git add for unstaged files, or git reset for stage files. |
<C-n> |
Jumps to the next file in the status list |
<C-p> |
Jumps to the previous file in the status list. |
cc |
Composes a commit message to commit the staged changes. |
These are the primary key mappings you'll want to use, but there are many
more which you can review by running :h gstatus
, or using the key mapping
g?
when in the status window.
The above commands will certainly get you started, and may be all you ever need with fugitive, but they are really just scratching the surface. If you want to dive deeper into all that Fugitive has to offer, be sure to check out the [five part Fugitive series on Vimcasts][].
[five part fugitive series on Vimcasts]: http://vimcasts.org/blog/2011/05/the-fugitive-series/
[Conflicted][] is a Vim plugin that wraps Fugitive's :Gdiff
functionality,
specifically optimizing for resolving merge and rebase conflicts. Conflicted
provides multiple views for conflicted files, specifically showing:
master
).While the typical view of a single file with the conflict markers Git provides can often be very confusing, the multiple views provided by Conflicted provide as much detail as we need to fully understand and resolve conflicts.
In addition, while giving us the three-way diff view to resolve the conflict,
Conflicted also provides mappings to perform a :diffget
from either the
upstream or local versions of the file and then displays them on the side:
Mapping | Operation |
---|---|
dgu |
:diffget from our upstream (typically master ) |
dgl |
:diffget from our local (typically our feature branch) |
Finally, Conflicted also provides a command, :GitNextConflict
, which will
write the file, perform a git add
to stage the resolved version, and either move
on to the next Conflicted file if there is one, or quit back to the terminal.
One additional enhancement shown in the video is the use of a shell command,
conflicted
, to open Vim with the Conflicted plugin active. This is provided
by the following shell function:
conflicted() {
vim +Conflicted
}
[Conflicted]: https://github.com/christoomey/vim-conflicted
Now you've seen a few of the ways to combine Vim and Git for even greater productivity. Both are focused Unix tools that do their one thing well, but provide a clean interface that makes combining them even better. If you're a Vim and Git user but have yet to combine them, there is no better time to give it a shot!