Can You Still Use Git Blame After Your Linter Reformats the Whole Repo?
Everyone tells you that running a global code formatter is a "point of no return" for your git history. They say once you let Prettier or Black loose on a five-year-old codebase, your git blame is effectively trashed, replaced by a wall of the same developer's name on every single line.
It's a common fear, and for a long time, it was a valid one. But it's also completely wrong.
You don't have to choose between a consistent style guide and knowing who actually wrote that cryptic regex in 2019. Git has a built-in "skip" button for these exact scenarios.
The "Great Reformatting" Disaster
We’ve all been there. You’re trying to debug a race condition, you run git blame, and instead of seeing the original author, you see:
a7b2c3d4 (Jane Doe 2023-10-12 14:00:00) // The actual logic is here
Jane didn't write the logic. Jane just ran npm run format and changed the indentation from two spaces to four. Now, the archaeological record of your project is buried under a layer of whitespace changes.
Most teams just sigh and accept this as the cost of "clean code." But since Git 2.23 (released back in 2019), there has been a better way.
Meet .git-blame-ignore-revs
The solution is a simple text file, usually named .git-blame-ignore-revs. Inside this file, you list the full 40-character commit hashes of any "style-only" commits you want Git to skip over when calculating a blame.
Here is what the file looks like:
# Reformatted the entire codebase with Prettier
# This commit changed 400 files but 0 logic
7d89a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8
# Updated linting rules and fixed all errors
a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0When Git encounters one of these commits during a blame, it ignores the changes made in that commit and looks back further to find the previous person who touched those lines. It's essentially a time machine that hops over the boring stuff.
How to Set It Up
Creating the file isn't enough; you have to tell Git to actually use it. You can do this on your local machine with:
git config blame.ignoreRevsFile .git-blame-ignore-revsBut you don't want to force every developer on your team to run that command manually. Instead, you should check the .git-blame-ignore-revs file into your repository and then set the configuration at the project level.
The best way to "force" this for the whole team is to add it to the repository's local git config, but since .git/config isn't shared, I usually recommend adding a note in the README or, better yet, automating it in a setup script or a Husky hook.
If you want to try it out immediately on a specific command without changing configs:
git blame --ignore-revs-file .git-blame-ignore-revs path/to/file.jsDoes this work in VS Code or GitHub?
This is where it gets really useful.
* GitHub/GitLab: GitHub automatically detects a file named .git-blame-ignore-revs in the root of your repository. If it's there, the web-based "Blame" view will use it by default. No extra configuration required.
* VS Code: The popular "GitLens" extension supports this. It will look for the blame.ignoreRevsFile setting in your git config and respect it when showing those inline "current line blame" annotations.
* JetBrains (IntelliJ/WebStorm): Recent versions also have native support for ignoring specific revisions in the "Annotate" view.
The "Gotcha" with Squash Merges
There is one major caveat. If you use a "Squash and Merge" workflow on platforms like GitHub, the commit hash that ends up on your main branch is not the same as the commit hash you had while working on your feature branch.
If you run a formatter on a branch, commit it, and then squash merge that branch, you need to grab the hash of the *merged* commit from the main branch and add that to your ignore file. If you add the hash from your local branch, it won't do anything because that hash doesn't exist in the main history.
Why you should do this today
I’ve seen teams hold off on fixing embarrassing linting issues for months because they didn't want to "pollute the history."
Don't let the tools hold your code quality hostage. Run the formatter, commit the changes, grab the hash, and toss it into a .git-blame-ignore-revs file. You get the clean, standardized code you want, and you keep the historical context you need. It’s one of the few times in software engineering where you actually get to have your cake and eat it too.