Skip to content

Instantly share code, notes, and snippets.

@g0xA52A2A
Last active April 10, 2020 20:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save g0xA52A2A/c34e5549a130f519cfaa4e387de9efdd to your computer and use it in GitHub Desktop.
Save g0xA52A2A/c34e5549a130f519cfaa4e387de9efdd to your computer and use it in GitHub Desktop.

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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment