Skip to content

Instantly share code, notes, and snippets.

@kyokley
Last active February 4, 2018 21:00
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 kyokley/c10ff97148a6533116ac714ad6fb5ac2 to your computer and use it in GitHub Desktop.
Save kyokley/c10ff97148a6533116ac714ad6fb5ac2 to your computer and use it in GitHub Desktop.
Useful VCS commands in VIM

Keyboard Shortcuts for Blame and Show

git blame and git show are useful commands for giving context of the code you're viewing. Since I spend the majority of my time in Vim, they become even more useful if they are executable from inside the editor. Of course, Vim makes this easy by giving a way to call external commands.

Vim (vimrc)

Git

Blame

For git blame, I wanted the ability to either blame the entire file or just part of one. By default, I blame the entire file but take advantage of Vim's visual mode to filter for only the selected lines.

nnoremap <leader>gb :<C-U>!git blame <C-R>=expand("%:p") <CR> \| color_git_blame \| less +<C-R>=line("w0") <CR><CR>
vnoremap <leader>gb :<C-U>!git blame <C-R>=expand("%:p") <CR> \| sed -n <C-R>=line("'<") <CR>,<C-R>=line("'>") <CR>p \| color_git_blame \| less <CR><CR>

The above assigns <leader>gb (gb => git blame, get it?) to normal and visual modes.

NOTE: I'm using a script called color_blame to colorize the git output. If you're not interested, feel free to remove those sections from the mapping commands

Show

In addition to being able to blame a file, I wanted the ability to get the commit message from the current line.

nnoremap <leader>gl :<C-U>!git blame <C-R>=expand("%:p") <CR> \| sed -n <C-R>=line(".") <CR>p \| awk '{print $1}' \| xargs git show <CR><CR>

Here, <leader>gl will first run git blame to get the sha hash of the current line and pass that to git show to get information specific to that commit.

Subversion

I sometimes find myself working on repositories that are based in subversion. Below are the same commands as above but for svn

nnoremap <leader>sb :<C-U>!svn blame <C-R>=expand("%:p") <CR> \| color_svn_blame \| less +<C-R>=line("w0") <CR><CR>
vnoremap <leader>sb :<C-U>!svn blame <C-R>=expand("%:p") <CR> \| sed -n <C-R>=line("'<") <CR>,<C-R>=line("'>") <CR>p \| color_svn_blame \| less <CR><CR>
nnoremap <leader>sl :<C-U>!svn blame <C-R>=expand("%:p") <CR> \| sed -n <C-R>=line(".") <CR>p \| awk '{print $1}' \| xargs svn log -r<CR><CR>

Altogether

nnoremap <leader>gb :<C-U>!git blame <C-R>=expand("%:p") <CR> \| color_git_blame \| less +<C-R>=line("w0") <CR><CR>
vnoremap <leader>gb :<C-U>!git blame <C-R>=expand("%:p") <CR> \| sed -n <C-R>=line("'<") <CR>,<C-R>=line("'>") <CR>p \| color_git_blame \| less <CR><CR>
nnoremap <leader>gl :<C-U>!git blame <C-R>=expand("%:p") <CR> \| sed -n <C-R>=line(".") <CR>p \| awk '{print $1}' \| xargs git show <CR><CR>
nnoremap <leader>sb :<C-U>!svn blame <C-R>=expand("%:p") <CR> \| color_svn_blame \| less +<C-R>=line("w0") <CR><CR>
vnoremap <leader>sb :<C-U>!svn blame <C-R>=expand("%:p") <CR> \| sed -n <C-R>=line("'<") <CR>,<C-R>=line("'>") <CR>p \| color_svn_blame \| less <CR><CR>
nnoremap <leader>sl :<C-U>!svn blame <C-R>=expand("%:p") <CR> \| sed -n <C-R>=line(".") <CR>p \| awk '{print $1}' \| xargs svn log -r<CR><CR>

Neovim (init.vim)

In Vim, ! executes an external command. However, because Neovim allows an actual terminal inside the editor, it's best to replace the ! with a call to te.

nnoremap <leader>gb :<C-U>te git blame <C-R>=expand("%:p") <CR> \| color_git_blame \| less +<C-R>=line("w0") <CR><CR>
vnoremap <leader>gb :<C-U>te git blame <C-R>=expand("%:p") <CR> \| sed -n <C-R>=line("'<") <CR>,<C-R>=line("'>") <CR>p \| color_git_blame \| less <CR><CR>
nnoremap <leader>gl :<C-U>te git blame <C-R>=expand("%:p") <CR> \| sed -n <C-R>=line(".") <CR>p \| awk '{print $1}' \| xargs git show <CR><CR>
nnoremap <leader>sb :<C-U>te svn blame <C-R>=expand("%:p") <CR> \| color_svn_blame \| less +<C-R>=line("w0") <CR><CR>
vnoremap <leader>sb :<C-U>te svn blame <C-R>=expand("%:p") <CR> \| sed -n <C-R>=line("'<") <CR>,<C-R>=line("'>") <CR>p \| color_svn_blame \| less <CR><CR>
nnoremap <leader>sl :<C-U>te svn blame <C-R>=expand("%:p") <CR> \| sed -n <C-R>=line(".") <CR>p \| awk '{print $1}' \| xargs svn log -r<CR><CR>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment