Skip to content

fix(git): drop global core.hooksPath; rely on init.templateDir + per-repo install#272

Open
JacobPEvans-personal wants to merge 1 commit into
mainfrom
fix/git-remove-hookspath
Open

fix(git): drop global core.hooksPath; rely on init.templateDir + per-repo install#272
JacobPEvans-personal wants to merge 1 commit into
mainfrom
fix/git-remove-hookspath

Conversation

@JacobPEvans-personal
Copy link
Copy Markdown
Member

Summary

  • Drops core.hooksPath from the home-manager git config so it no longer cascades to every repo
  • Keeps init.templateDir = ~/.git-templates so new clones / git init still get template hooks (passive — no override of per-repo .git/hooks/)
  • Updates inline docs in hooks.nix + precommit-tools/default.nix to describe the new template + per-repo install model

Why

A globally-set core.hooksPath makes pre-commit's installer refuse:

[ERROR] Cowardly refusing to install hooks with `core.hooksPath` set.
hint: `git config --unset-all core.hooksPath`

Reproduces consistently on every direnv activation in repos that use cachix/git-hooks.nix (e.g. nix-claude-code), where installationScript runs pre-commit install in the dev shellHook. Result: pre-commit framework hooks never install, and the user gets cryptic stderr on every cd.

Per-repo Nix dev shells already invoke pre-commit install correctly. Removing the global override hands hook ownership back to them, which is what the cachix/git-hooks.nix design assumes. Layer 1 of the 3-layer defense (per hooks.nix docs) shifts from "active on ALL repos via core.hooksPath" to "seeded into new clones via templateDir, installed per-repo via dev shell" — same coverage in practice, no conflict with pre-commit framework.

Migration

Existing repos with a stale local core.hooksPath (one was left behind in nix-claude-code) need a one-time:

git config --local --unset core.hooksPath

after darwin-rebuild switch. Then cd re-fires direnv and pre-commit install populates .git/hooks/ cleanly.

Test plan

  • nix flake check passes on the worktree
  • After local darwin-rebuild switch, git config --global --get core.hooksPath returns empty
  • cd ~/git/public/nix-claude-code/main triggers direnv with no "Cowardly refusing" errors
  • ls -la ~/git/public/nix-claude-code/main/.git/hooks/ shows pre-commit framework hooks installed
  • New git init test repo still receives template hooks via init.templateDir

Refs: cachix/git-hooks.nix design (per-repo installationScript)

…repo install

Setting core.hooksPath globally makes pre-commit's installer refuse with
"Cowardly refusing to install hooks with core.hooksPath set", breaking
every Nix dev shell that calls pre-commit install via shellHook (e.g.
cachix/git-hooks.nix installationScript). nix-claude-code reproduces this
twice per direnv activation.

Drop the core.hooksPath setting. ~/.git-templates/hooks files (pre-commit,
pre-push, prepare-commit-msg) are still populated by hooks.nix and now
flow into new clones via init.templateDir's native template mechanism —
passive, no override. Per-repo Nix dev shells handle pre-commit install
into .git/hooks/ for existing repos.

Migration for existing repos with a stale local core.hooksPath:

  git config --local --unset core.hooksPath

After rebuild, re-fire direnv in any Nix-dev-shell repo to let
installationScript populate the hooks normally.

Updates comments in hooks.nix + precommit-tools/default.nix to describe
the new template/per-repo split instead of the old global override.

Assisted-by: Claude <noreply@anthropic.com>
JacobPEvans-personal added a commit to dryvist/nix-claude-code that referenced this pull request May 31, 2026
…lock (#31)

Pre-commit's installer refuses with "Cowardly refusing to install hooks
with core.hooksPath set" when any scope sets the value. The root cause
(global core.hooksPath in nix-home) is being removed in dryvist/nix-home#272,
but a defensive guard here surfaces a clear, actionable warning if any
future regression — global, local, or per-machine drift — sets the value
again. Without the guard the user sees the raw stderr twice per direnv
activation with no hint that the fix is `git config --unset core.hooksPath`.

The guard runs before installationScript; if hooksPath is empty it is a
single grep-and-exit, so no perceptible startup cost.

Refs: dryvist/nix-home#272

Assisted-by: Claude <noreply@anthropic.com>
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