Better git diffs with FZF

Rafael Mendiola
4 min readApr 15, 2020

--

The setup instructions in this article are for Mac, but you should be able to do this on Linux and Windows Subsystem for Linux. Hat tip to Kevin LaFlamme for showing what’s possible with FZF. You should follow him here.

Sometimes I find the git diff command a little inconvenient. It can throw a lot of information at the screen at once. I use git diff not only for verifying my changes before a commit, but also to review pull requests, or for finding bugs introduced between two commits. In the situations when you’re looking at a lot of changed files, having to scroll up and down so much is tedious.

what git diff normally shows you

I want to have an IDE experience, but I don’t want to leave the terminal. I want to see a list of files on the left, and a diff on the right. I thought that in order to have this, I would have to write some complicated bash script. As it turns out, we can do this easily with a tool called fzf.

The good stuff: FZF and how to set it up.

FZF is a powerful fuzzy finder. It takes a list of strings and makes it searchable. You can check it out here: https://github.com/junegunn/fzf. The basic installation is:

brew install fzf

When you run fzf without parameters, it will show the list of files in the current directory, and typing filters the list!

a basic demo of fzf

An additional neat feature of FZF is that it can show a preview window to display the results of a command. For example, we can use fzf with bat to pretty-print the contents of a file, like in the command below. Bat is an alternative tocat that supports syntax highlighting. The {-1} stands for the selected file.

fzf --preview 'bat {-1} --color=always'
fzf with bat preview

What if we could pipe the output of git diff in to fzf? In case you haven’t done it before, piping is using the | (pipe) operator to feed the output from the command on the left, into the input of the command on the right. With git diff, fzf and | as our ingredients, we can cook up something interesting. Here’s what we’ll do:

  • Generate a list of modified files with git diff --name-only
  • Pipe that into fzf
  • Preview the file's diff with git diff --color=always

Mixing these together, we end up with the neat function below. $@ is the special value for “all the parameters”, letting us retain the ability of using other git diff parameters. The preview part is also on its own line to make it a little bit more readable. Put this in your .bashrc or .zshrc and reload your shell.

fd() {
preview="git diff $@ --color=always -- {-1}"
git diff $@ --name-only | fzf -m --ansi --preview $preview
}

Now you can simply run fd and get that IDE experience 🎉🥳.

Because we retained the ability to use it like a regulargit diff, we can still do things like:

# comparing your current branch to master
fd master...
# comparing the changes between two commits
fd 4c674950..6d88a7bfd8
isn’t it nice to be able to use fzf for this?

Note: this command will only work from the root of your git project. git diff --name-only returns project-level paths and there’s some weirdness with that.

I hope you find this useful. It’s certainly made my git experience a little bit cooler. If you have any issues with the script, or you feel you could improve something about it, let me know in the comments!

--

--

Rafael Mendiola

Startup survivor, drinker of the MIT firehose. React Native developer. geosocial.io is my startup dream. If at first you don’t succeed, sudo bang bang.