Skip to content

docs: make blame.ignoreRevsFile discoverable and automatic - #2275

Open
dlovell wants to merge 3 commits into
mainfrom
docs-blame-ignore-revs
Open

docs: make blame.ignoreRevsFile discoverable and automatic#2275
dlovell wants to merge 3 commits into
mainfrom
docs-blame-ignore-revs

Conversation

@dlovell

@dlovell dlovell commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Problem

The repo has a .git-blame-ignore-revs file, but it does nothing in a fresh clone. Git deliberately refuses to read blame.ignoreRevsFile from repository-tracked config (that would let a repo change local git behavior), so every contributor has to set it by hand — and nothing in the repo says so. GitHub's web blame reads the file automatically, so the local/web mismatch is easy to miss.

Changes

  • CONTRIBUTING.md — document the one-liner (git config --replace-all blame.ignoreRevsFile .git-blame-ignore-revs) right after the existing pre-commit install step, and a "git blame and bulk reformats" subsection covering how the hook sets it, that existing clones must re-run pre-commit install to pick up the new hook type, and the caveat below. This is the one place any of it is written down.
  • .git-blame-ignore-revs — a three-line header saying what the file is and pointing at that subsection, rather than restating it in a file that is mostly machine-read.
  • .pre-commit-config.yaml — a post-checkout hook that sets the config, plus default_install_hook_types: [pre-commit, post-checkout] so pre-commit install wires both. Contributors who follow the setup steps get it without running the extra command.

--replace-all rather than plain git config <name> <value>: the single-value form hard-fails (exit 5, cannot overwrite multiple values with a single value) when a clone's local config already holds more than one blame.ignoreRevsFile entry, which git explicitly supports. The hook would then print Failed on every checkout with no way to recover, since each retry hits the same error. --replace-all collapses the list to the one correct value.

Verification

In a fresh clone of this branch (pre-commit 4.6.0, git 2.55):

  • blame.ignoreRevsFile starts unset.
  • pre-commit install reports installed at .git/hooks/pre-commit and installed at .git/hooks/post-checkout.
  • The next checkout runs configure blame.ignoreRevsFile...Passed, after which git config --get blame.ignoreRevsFile returns .git-blame-ignore-revs.
  • Seeded with two local blame.ignoreRevsFile values, the hook still passes and leaves exactly one value. (With the single-value form it exited 5 and failed on every subsequent checkout.)
  • An existing post-checkout hook (e.g. git-lfs) is preserved — pre-commit migrates it via its .legacy mechanism.

Caveats

  • git blame fails at revs predating this file. Once the config is set, git blame on any file exits 128 with fatal: could not open object name list: .git-blame-ignore-revs whenever the working tree is at a rev older than 14a30475 (2024-05-17) — bisecting into early history, or checking out a tag up to v0.1.2.post. There is no per-command override: blame.ignoreRevsFile is multi-valued, so -c blame.ignoreRevsFile= and --ignore-revs-file=""/=/dev/null all append rather than replace, and blame still tries to open the configured path. The workaround is git config --unset-all blame.ignoreRevsFile for the duration; the next checkout restores it. This is documented in CONTRIBUTING.md.
  • No visible blame difference today. The single rev currently listed (01b9b5aa, the ruff import-order pass) no longer owns any lines in any file. This PR is about the mechanism being in place and correct for the next bulk reformat, not about fixing blame output right now.

Notes

  • default_install_hook_types changes what pre-commit install installs, so existing clones need to re-run pre-commit install once to pick up the post-checkout hook. New clones get it from the documented setup flow.
  • The hook is stages: [post-checkout] only, so it never runs on git commit and pre-commit.ci is unaffected (it doesn't run post-checkout hooks). It does run on file checkouts, though: git checkout -- <file> measured 0.153s with the hook vs 0.004s without, and git restore <file> prints a configure blame.ignoreRevsFile...Passed line each time.
  • Branch is named docs-blame-ignore-revs rather than docs/blame-ignore-revs: origin already has a branch literally named docs, which blocks any docs/* ref.

@codecov

codecov Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #2275      +/-   ##
==========================================
- Coverage   83.35%   83.34%   -0.01%     
==========================================
  Files         165      165              
  Lines       21534    21534              
==========================================
- Hits        17949    17947       -2     
- Misses       3585     3587       +2     
Flag Coverage Δ
catalog-annex 49.42% <ø> (ø)
catalog-git 54.50% <ø> (ø)
core 67.44% <ø> (-0.01%) ⬇️
library 0.43% <ø> (ø)
slow 52.59% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.
see 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

`.git-blame-ignore-revs` has no effect until a clone sets
blame.ignoreRevsFile, and git deliberately never accepts that setting from
the repository itself. Document the one-liner next to the existing
pre-commit setup step, say so in the file's own header, and add a
post-checkout hook so `pre-commit install` sets it going forward.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0111Kwvgt9muBtxQtfr9YdJv
@dlovell
dlovell force-pushed the docs-blame-ignore-revs branch from 2c485c2 to 33cd483 Compare September 2, 2026 13:57
@dlovell
dlovell requested a review from ray1097 September 2, 2026 13:59
@dlovell
dlovell marked this pull request as ready for review September 2, 2026 13:59
dlovell and others added 2 commits September 2, 2026 10:25
`git config <name> <value>` is the single-value form: it exits 5 with "cannot
overwrite multiple values with a single value" when a clone's local config
already holds more than one blame.ignoreRevsFile entry, which git supports.
The post-checkout hook then failed on every checkout with no way to recover,
since each retry hit the same error. --replace-all collapses the list instead.

Also correct the header's claim that `pre-commit install` sets the config (only
the next checkout does), record that enabling it makes `git blame` fatal at revs
predating this file with no per-command override, and tell existing clones to
re-run `pre-commit install` to pick up the new hook type.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S4KruUywAZTsH2Gb56Guyk
…revs file

The header comment had grown into a second copy of the setup instructions and
the caveat, in a file that is mostly machine-read. Keep CONTRIBUTING.md as the
one place that explains it -- a new "git blame and bulk reformats" subsection
next to the setup step it belongs to -- and cut the header to three lines that
say what the file is and where to read the rest.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S4KruUywAZTsH2Gb56Guyk
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant