Most powerful git tool vimmer ever created...
Why
This is just a simple tutorial to features I found useful in Fugitive.vim.
In my experience, Fugitive is like a surgery tool directly operating on those SHA objects in .git
. There's basically nothing it cannot do and it sounds so illegal. However, it's not foolproof type of product, instead, you need to dive deeper into its documents and tutorial to find your own way. So this blog is just to summarize my way. But I hope it's also useful for you.
Basic Concept
First, you need to understand what's fugitive object
. We have 3 types of object: tree
, blob
and commit
. tree
is folder structure; blob
is file; and commit
is the commit object. All of them are coded in SHA to refer to.
Here's the example for how Fugitive refers to these objects. But it's much more than you could use in daily life though! What I found useful are:
**HEAD~2** HEAD's previous 2 commit object and @ equals HEAD if you like to type short
**master~2** master current commit's previous 2 commit object
**branch:filename** e.g. master:% current file blob, or just give branch name master for current file
**branch:** branch tree object
**@~2:filename** HEAD's grandparent's file blob
In following, I'll just call them object with this context. Together with normal git version syntax, it's easy enough to identify files of different branch and commits. Let's see how powerful it is.
Fugitive Swiss Knife
Git
Type :G
and you get interactive git status
, where you could staged/unstaged (-), revert (X), and check diff (dv). Do you still remember the painful git add -p
command? When you diff you can directly edit the staged version to partially stage your changes!
This single interface alone is very satisfying already and probably cover 60% of your git usage.
Git diff(tool)
You can directly diff two version e.g. :G d object1 object2
(diff object now has issue). It returns you the list of diff files. Use [q and ]q to move between hotspot. To view file line by line diff, you can add this temporary fix. I personally bind it to a key so that we could diff lines anytime.
Git log (Following Files)
You can trace historical changes through :0Gclog -- %
to get all commits containing current file. Of course %
is just vim's syntax sugar for current file. You can put any file after the --
. To diff any 2 versions in the quickfix window, I open a version (in current buffer) and use key to select another version to diff against current buffer.
Git mergetool
You can directly merge the conflicting file using Gvdiffsplit!
. Conflicting file will open as three way merge style. 3-way merge windows looks confusing but it's actually straightforward: From left to right is Merge Target
or Ours
➡ Working Copy
➡ Feature Branch
or Theirs
.
:diffget
is the same as normal vimdiff mode except that you need to give buffer name. For example, for buffers like:
Ours: ......//2/demo.js
Working: ....../demo.js
Theirs: ......//3/demo.js
Then you 3-way merge will refer to these buffer with the name 2
, demo
and 3
. For example, to get from Ours
, we type :diffget 2
. To conclude your merge, just :Gwrite
.
Gedit
You can get any version in git like God using :Gedit object
. For example, if I want to see the file in a feature branch, I just do :Gedit branchname:/path/to/file
. Or if not sure about the filename, I'll just :Gedit branchname:
to open tree object or folder.
Run :Gedit
without any parameters will take you back to working copy. Combining with Gvdiffsplit
you can diff with any version as well manually.
Gwrite
Write/save your working one and also update to staged. It's somewhat useful when you do merging and want to use purely from Ours
or Theirs
.