fix(cli): install git hooks from the repository root only - #861
Merged
Conversation
In a linked worktree git exports GIT_DIR into every hook. A pre-commit or pre-push job that runs pnpm inside cli/ (`cd cli && pnpm lint`, `pnpm --dir cli test`, ...) lets pnpm 12 install missing dependencies first, which ran cli's `"prepare": "lefthook install"`. With GIT_DIR set and no GIT_WORK_TREE, git took cli/ for the work tree root: lefthook found no config there, wrote its example into cli/lefthook.yml and reinstalled the hooks every worktree shares. Reproduced in throwaway repos with lefthook 2.1.12 and pnpm 12.3.4. The root package's `prepare` already installs the hooks, so cli drops its own along with its lefthook devDependency, which nothing else used (knip flagged it once the script was gone). An architecture test asserts that no script of this package calls lefthook; it failed on the old package.json. Fixes #860 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011x4ms5qcGuZgYhCxfdHMUb AIDD-Session-Id: 4acc9a1c-19bc-4468-b8b6-e86644bcba60
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🎯 What & why
A stray
cli/lefthook.ymlholding lefthook's example config kept appearing untracked in linked worktrees (#860). Worse, whatever wrote it also reinstalled the git hooks that every worktree shares.🛠️ How it works
The chain, reproduced in throwaway repos with lefthook 2.1.12 and pnpm 12.3.4:
GIT_DIRinto every hook; the main checkout gets onlyGIT_INDEX_FILE.cli/(cd cli && pnpm lint,pnpm test:arch,pnpm typecheck,pnpm --dir cli knip,pnpm --dir cli test). Whencli/node_modulesis missing or stale, pnpm 12 installs first and runscli/package.json's"prepare": "lefthook install".GIT_DIRset and noGIT_WORK_TREE, git takescli/for the work tree root. lefthook finds no config there, writes its example, and installs hooks into the shared hooks directory.The fix:
cli/package.jsondropsprepareand itslefthookdevDependency. The root package'spreparealready installs the hooks, and theMakefiledoes too, from the root. Nothing else incliused lefthook: knip flagged the dependency once the script was gone. The lockfile loses the lefthook entries.cli/tests/architecture/hooks-install-from-the-root.arch.test.tsasserts that no script of this package calls lefthook. It lives inarchitecturebecause that project runs in pre-commit on anycli/**change, so it catches the exact edit that would bring the bug back.🧪 How to verify
package.json(prepare: lefthook install); green after.cd cli && GIT_DIR=<root>/.git lefthook installgivesAdded config: .../cli/lefthook.yml. WithoutGIT_DIRthere is no file. The pre-commit jobcd cli && pnpm lintin a linked worktree creates it. With cli'sprepareremoved, it does not.cli/lefthook.yml.pnpm installonly insidecli/no longer gets hooks installed;scripts/doctor.shalready warns when they are missing. Installing from the root is the supported path.|| truewould not have helped: the file still appears with it. A.gitignoreentry would only hide it while the shared hooks keep being reinstalled.cli/package.jsonis a harness file, so CI runs every mutation scope.🔗 Linked issue
Closes #860
✅ I certify
🤖 Generated with Claude Code
https://claude.ai/code/session_011x4ms5qcGuZgYhCxfdHMUb