Fugitive.vim - exploring the history of a git repository


Run time:

Git provides tools for searching the contents of files, commit messages, and even whether text was added or removed by a commit. In this episode, we’ll see how fugitive’s Ggrep and Glog commands wrap this functionality up so that we can search the contents and history of a git repo from right inside of Vim.

This is the last of our five part series on fugitive.vim.


Browsing past revisions of a file

The Glog command makes it easy to examine all previous revisions of a file. It does this by loading each revision into its own buffer, and queuing them in the quickfix list in chronological order.

You can filter the results

command action
:Glog load all previous revisions of the current file into the quickfix list
:Glog -10 load the last ten previous revisions of the current file into the quickfix list
:Glog -10 --reverse load the first ten revisions of the current file into the quickfix list (in reverse chronological order)
:Glog -1 --until=yesterday load the last version of the current file that was checked in before midnight last night

Browsing past commits

You can also use the :Glog command to review past commit objects, by appending a trailing -- argument. By default, this will load all ancestral commit objects into the quickfix list. If you supply a filepath after the -- argument, then the list will be filtered to only include commit objects that touched the specified file.

command action
:Glog -- load all ancestral commit objects into the quickfix list
:Glog -- % load all ancestral commit objects that touched the current file into the quickfix list

Note that when fugitive loads a commit object into a buffer, it is interactive in a number of ways. See episode 34 for more details.

Working with the quickfix list

I recommend installing unimpaired.vim, another plugin by Tim Pope. This provides lots of useful pairs of mappings, including a handful that make working with the quickfix list much easier:

unimpaired Vim action
[q :cprev jump to previous quickfix item
]q :cnext jump to next quickfix item
[Q :cfirst jump to first quickfix item
]Q :clast jump to last quickfix item

Searching the working tree with Ggrep

The Ggrep command is a wrapper for git grep. It uses the results to populate the quickfix list, so you can easily navigate the result list from inside Vim.

If you want to search your working tree for the text ‘find me’, simply run:

:Ggrep 'find me'

The git grep command only looks inside files that are tracked by the git repository. The fact that it only looks inside tracked files means that it skips over any files or directories listed in the .gitignore file.

Searching branches, tags and commits with Ggrep

git grep is not just limited to reading files on the filesystem. It can look inside any git object. So using git grep, you can search all files in any of your git branches without first having to switch to the branch.

command action
:Ggrep findme search for ‘findme’ in working copy files (excluding untracked files)
:Ggrep --cached findme search for ‘findme’ in the index
:Ggrep findme branchname search for ‘findme’ in branch ‘branchname’
:Ggrep findme tagname search for ‘findme’ in tag ‘tagname’
:Ggrep findme SHA search for ‘findme’ in the commit/tag identified by SHA

When you open a file that belongs on another branch, fugitive will automatically create a read only buffer for it.

Searching for text in a commit message

If you want to search the text of commit messages, you can do so by passing the --grep option to the git log command. For example, if you wanted to find commit messages containing the text ‘findme’, you could run:

git log --grep=findme

You can also do this from inside of Vim using the :Glog wrapper. This table summarizes a couple of ways you might use this:

command action
:Glog --grep=findme -- search for ‘findme’ in all ancestral commit messages
:Glog --grep=findme -- % search for ‘findme’ in all ancestral commit messages that touch the currently active file

Searching for text added or removed by a commit

Git also makes it possible to search for text that was added or removed by a commit using the pickaxe option. This is activated with the -S switch as follows:

git log -Sfindme

This tells git to go through every commit, comparing the before and after state of each file that was changed by that commit. If the specified string is present in the file before, but absent from the file after the commit, then it counts as a match. The converse is also true, so if the specified string was either added or removed by the commit, then it will appear the git log results.

Here are a couple of examples demonstrating how the pickaxe option can be used with :Glog:

command action
:Glog -Sfindme -- search for ‘findme’ in the diff for each ancestral commit
:Glog -Sfindme -- % search for ‘findme’ in the diff for each ancestral commit that touches the currently active file

Further reading


Level-up your Vim


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


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..