A better git blame with --ignore-rev

11 May 2021 in TIL

One of the biggest arguments against running automatic formatters against a codebase is that we lose the benefits that git blame gives us.

Fortunately as of v2.23, git gained the ability to ignore specific revisions. This allows us to run our automatic formatters without losing any information:

bash
git blame --ignore-rev <sha1>

If the blame for any single line resolves to the ignored commit, it will be skipped and the previous commit that changed that line will be shown.

Keeping track of all of the commits to skip can be difficult, but thankfully git provides a way to store them in a file and pass that filename in to git blame.

Searching around, the convention for this filename seems to be .git-blame-ignore-revs. It expects one commit hash per line, and all commits in the file will be ignored by git blame.

You can add comments to this file by prefixing it with a #, and I'd recommend commenting each sha to explain why it's being skipped.

bash
$ cat .git-blame-ignore-revs
# Upgrade to Prettier 2.0
0ea947095f9e7a085302f26a51901e1962fb085e

Once the file exists, you can run git blame --ignore-revs-file .git-blame-ignore-revs to see a useful git blame output.

Remembering to pass that flag each time you run git blame is a bit too much, but you can set a global ignoreRevsFile in your config. By naming the file .git-blame-ignore-revs consistently, it will be used to skip any useless commits in a repo.

bash
git config --global blame.ignoreRevsFile .git-blame-ignore-revs

Finally, there are some config options that you may find useful:

bash
# Mark any lines that have had a commit skipped using --ignore-rev with a `?`
git config --global blame.markIgnoredLines true
# Mark any lines that were added in a skipped commit and can not be attributed with a `*`
git config --global blame.markUnblamableLines true