Better git diffs with FZF
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.
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!
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'
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
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!