Learn Vim at your own pace with my self-study Core Vim Course.

Learn more

Learn Vim at your own pace with my self-study Core Vim Course.

Fugitive.vim - browsing the git object database

#34

Run time:

With the fugitive plugin, you’re not limited to just working with files in your working tree. The :Gedit command allows you to open files in other branches, and to browse any git object, including tags, commits and trees. Plus, if your repository is hosted on github, you can easily bring up the webpage for any git object using the :Gbrowse command.

This is the penultimate of a five part series on fugitive.vim.

Shownotes

Reading a file from any git branch

Fugitive makes it possible to open a read only buffer with the contents of any file, on any local git branch. You can do this using the :Gedit command followed by an argument of the form: branchname:path/to/file. Note that you can use the tab key to auto-complete both the branchname and the filepath.

Remember that the % symbol has special meaning on Vim’s command line: it is a shorthand for the current file’s path. So if you wanted to open the current file on a branch called ‘feature’, you could do so by running :Gedit feature:%.

Exploring the git object database

The :Gedit command allows you to open a buffer containing any git object. There are 4 kinds of git object:

  • blobs - correspond to the content of a file
  • trees - correspond to a directory on the filesystem, representing a list of blobs and trees
  • commits - can reference a tree and one or more parent commits
  • tags - refer to a particular commit by name

Every git object is identified by a SHA code. When you run :Gedit SHA it will open a buffer containing a textual representation of the corresponding git object. This could be a blob, tree, commit or tag.

Commit objects

If you run :Gedit SHA, passing in the id for a commit object, then fugitive will open a buffer containing a textual representation of that commit. This looks just like the what you see when you run git show SHA in the shell, but fugitive makes the buffer interactive in a number of ways. Depending on where your cursor is positioned, pressing the <Enter> key can open a new buffer containing another git object.

  • press <Enter> on a reference to a parent to open that commit object
  • press <Enter> on a reference to a tree to open that tree
  • press <Enter> on a diff summary line to diff the specified file before and after that commit

Tree objects

If you run :Gedit SHA, passing the id for a tree object, then fugitive will open a buffer containing a textual representation of that tree. Again, this looks just like what you see when you run git show SHA in the shell. But you can get more information in the shell by running git ls-tree SHA - this includes the SHA code for every object referenced by that tree.

When fugitive creates a buffer representing a tree object, you can press the a key to toggle between the git show and git ls-tree views.

You can navigate through a fugitive tree buffer just like you would using Vim’s native file explorer (or the NERD tree). Pressing <Enter> when your cursor is on a line representing a file or a directory will open a buffer for that object.

The tree buffer makes it easy to drill down through the directories of your git repository, but it’s not obvious how you could go up a level to the parent directory. Running the following command will open the parent tree:

:edit %:h

If you want, you could create a mapping to make this easier. Here’s an example, which maps .. to the above command, but only for buffers containing a git blob or tree:

autocmd User fugitive 
  \ if fugitive#buffer().type() =~# '^\%(tree\|blob\)$' |
  \   nnoremap <buffer> .. :edit %:h<CR> |
  \ endif

Whenever your current buffer contains a git tree or blob, you can always jump up to the commit object for the current tree by pressing C.

Open the github URL for the current object

If your git repository is hosted on github, then you can open the webpage for the current git object by running the :Gbrowse command. This is pretty smart about doing the right thing for the context. Whether the active buffer contains a blob, tree, commit or tag, fugitive will generate the appropriate URL.

Also, if you trigger :Gbrowse from visual mode in a file, then the selected lines will be highlighted in the github source.

Auto-clean fugitive buffers

Each time you open a git object using fugitive it creates a new buffer. This means that your buffer listing can quickly become swamped with fugitive buffers.

Here’s an autocommand that prevents this from becomming an issue:

autocmd BufReadPost fugitive://* set bufhidden=delete

Add git branch to status line

Fugitive provides a function that you can add to your statusline, and it will show your current git branch. This example is taken from the fugitive documentation (:help fugitive-statusline):

set statusline=%<%f\ %h%m%r%{fugitive#statusline()}%=%-14.(%l,%c%V%)\ %P

Further reading

Comments

Level-up your Vim

Training

Boost your productivity with a Vim training class. Join a public class, or book a private session for your team.

Drew hosted a private Vim session for the shopify team that was one of the best workshops I have ever attended.

John Duff, Director of Engineering at Shopify

Publications

Make yourself a faster and more efficient developer with the help of these publications, including Practical Vim (Pragmatic Bookshelf 2012), which has over 50 five-star reviews on Amazon.

After reading it, I've switched to vim as my default editor on a daily basis with no regrets. ★★★★★

Javier Collado

Learn to use Vim efficiently in your Ruby projects

In association with thoughtbot, one of the most well respected Rails consultancies in the world, I've produced a series of screencasts on how to make navigating your Ruby projects with Vim ultra-efficient. Along the way, you’ll also learn how to make Ruby blocks a first-class text object in Vim. This lets you edit Ruby code at a higher level of abstraction. Available to buy from thoughtbot..