Show the git object for the current line or selection. Different from git log -L
as I'm only interested in the current text (also I don't deem line based ancerstory particularly intersting).
Commit hashes are pulled from git blame
. We need to pass -f
and --show-email
to ensure the time is always shown as the forth field. This is considered important as I want to sort upon the time to ensure the commits passed to git show
are in chronological order.
I "prime" less
with a search pattern to allow me to quickly page though the interesting bits of the output. I do this along with passing the -R
flag via the LESS
environment variable as to override other options that may be set there that could potentially interfere, such as -F
.
The use of a UNIX pipeline is a little ugly but it is far more concise than the equivalent Vim script.
function! Gshow() range
let blame = 'git blame --root -f --show-email --date=unix -L'
let args = a:firstline . ',' . a:lastline . ' ' . expand('%')
let pipeline = '| sort -r -n -k 4 | cut -f 1 -d " " | uniq'
let commits = systemlist(blame . args . pipeline)
if !empty(filter(commits, "v:val !~ '00000000'"))
call execute('!LESS=-R+/"^(commit|diff)" git show' . ' ' . join(commits))
redraw!
else
echo 'Not committed'
endif
endfunction
command! -range Gshow <line1>,<line2> call Gshow()
nnoremap gs :Gshow<CR>
xnoremap gs :Gshow<CR>