While this is certainly doable in vanilla
vim, I suggest you take a look at tpope's excellent
vim-fugitive plugin. Then, you simply need to do
:tab Gdiff to get what you want.
If you really don't want to install any plug-ins, the following might work assuming the current file is in buffer no. 1:
:tabnew | r! git show HEAD^:$(git rev-parse --show-prefix)#1:t
- In the newly opened tab,
:vert sb 1 | windo diffthis
- first opens a new tab with
tabnew and loads the contents of the
HEAD^ version of the file in buffer 1 into it.
- opens a vertical split containing buffer 1 with
vert sb 1, then issues
:diffthis to all buffers in the tab to enter diff mode.
The OP asked for some more explanation on step 1.
git show needs an input of the form
<path> has to be relative to the root of the working tree. For example, if the absolute path of the file in buffer 1 is
/a/b/foo.ext so that
b contains your
.git folder (i.e.
b is the root of your repo), in order for
git show to work properly you would have to invoke it with
HEAD^:b/foo.e. Using either
foo.ext won't work. So I used
git rev-parse --show-prefix to obtain the path of the current folder relative to the git root (which would be
b/) in this example.
Then, I used
vim path expansion to append the name of the file (that is
vim to fetch the path of whatever file is loaded in buffer 1, and
:t extracts the "tail", which is everything after the last
/ in the path returned by
#1. In some cases
#1:t are equal, but this is not always the case. For instance, if you ran
vim b/foo.ext then
#1 would return
b/foo.ext instead of just
:help expand for more info.
Of course, you could just enter the path manually, as in
:tabnew | r! git show HEAD^:b/foo.ext, and it would work. But the version above is scriptable or you can assign to a map.