Skip to content

fix: respect core.hooksPath set at worktree scope - #152

Open
anandghegde wants to merge 2 commits into
toplenboren:masterfrom
anandghegde:fix/worktree-scoped-hookspath
Open

anandghegde wants to merge 2 commits into
toplenboren:masterfrom
anandghegde:fix/worktree-scoped-hookspath

Conversation

@anandghegde

@anandghegde anandghegde commented Sep 14, 2026 •

Copy link
Copy Markdown

Credit to @thomastaillefer for tracking this down and proposing the approach in #150; this PR implements it with tests.

_getHooksDirPath() read core.hooksPath with git config --local, which can't see the worktree scope (.git/worktrees/<name>/config.worktree, used when extensions.worktreeConfig is on). If the path was set there, the hook was written to the default .git/hooks while git read hooks from the configured directory, so the hook never ran and nothing reported a problem.

Fix

Read core.hooksPath from the two repo-level scopes in the order git applies them: --worktree first, then --local. Errors are ignored and the next scope is tried. --worktree fails in a linked worktree when extensions.worktreeConfig is off, and --get exits 1 when the key isn't set. Global and system config are still never consulted, so #130 stays fixed. Relative paths and the default <gitRoot>/hooks fallback are handled as before.

Tests

Added to the existing "Git worktree support" block:

  • worktree-scoped absolute path is used, and wins over a local one
  • worktree-scoped relative path resolves inside the linked worktree
  • local path is used when extensions.worktreeConfig is off
  • extension on but nothing set falls back to the default hooks dir
  • a global core.hooksPath (via GIT_CONFIG_GLOBAL) is ignored

The first two fail without the fix. The global-config test fails if the scope flags are dropped.

Verified

  • yarn test: 60 passed. yarn lint: clean. Both run on Node 22 with git 2.50.1 on macOS.
  • Ran the repro script from Follow-up to #149: worktree-scoped core.hooksPath is invisible to --local, so hooks install where git never reads #150, using the local cli.js. Before the fix, the commit went through, customhooks/ stayed empty and the hook landed in main/.git/hooks. After the fix, HOOK_FIRED printed, the commit was blocked and the hook was in customhooks/.
  • Manually set a relative core.hooksPath at worktree scope and committed from a subdirectory of the worktree. The hook installed in <worktree>/.rel-hooks fired.

Includes a patch changeset.

Fixes #150

Summary by CodeRabbit

  • Bug Fixes
    • Hook installation now respects core.hooksPath configured specifically for a Git worktree.
    • Worktree-level settings take precedence over repository-level settings, including support for relative and absolute paths.
    • When no repository-scoped path is configured, hooks use the shared repository hooks directory.
    • Global and system-level core.hooksPath settings are ignored to prevent unintended hook placement.

core.hooksPath was read with `git config --local`, which does not see
the worktree scope (config.worktree). When it was set there, hooks were
written to the default directory while git ran them from the configured
one, so they never ran.

Read the worktree scope first, then the local scope. Global and system
config stay ignored.
@coderabbitai

coderabbitai Bot commented Sep 14, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

Understand this PR’s impact

Explore downstream dependencies and potential security impact with Blast Radius.

View blast radius →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 28cd7311-f308-41e8-96c0-b36eb2e6f9c2

📥 Commits

Reviewing files that changed from the base of the PR and between 8c88517 and 3b21a9c.

📒 Files selected for processing (1)
  • simple-git-hooks.js

Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review.


📝 Walkthrough

Walkthrough

The hook directory lookup now checks Git worktree scope before local scope. It ignores global and system configuration, preserves default path handling, and adds tests for linked worktrees and a patch changeset.

Changes

Hooks path resolution

Layer / File(s) Summary
Repository-scoped hooks lookup
simple-git-hooks.js
_getHooksDirPath checks core.hooksPath with --worktree before --local. Unset or unavailable scopes are skipped. Global and system scopes are not checked.
Worktree scope validation and release record
simple-git-hooks.test.js, .changeset/worktree-scoped-hooks-path.md
Tests cover worktree-scoped absolute and relative paths, local configuration, the default shared hooks directory, and ignored global configuration. The changeset declares a patch release.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: jounqin

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: honoring core.hooksPath configured at worktree scope.
Linked Issues check ✅ Passed The implementation satisfies the coding requirements in #150. _getRepoScopedHooksPath() checks git config --worktree --get core.hooksPath before --local, ignores command errors and empty values,…
Out of Scope Changes check ✅ Passed The changed source implements #150. The tests verify the required hook-path behavior. The patch changeset records the same fix. No unrelated production behavior or unrelated file change appears in the…
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 2 files.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@changeset-bot

changeset-bot Bot commented Sep 14, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 3b21a9c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
simple-git-hooks Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@anandghegde

Copy link
Copy Markdown
Author

Thanks for the review, @JounQin. Nothing outstanding on my side — the fix and its test are in a single commit, and CI is green. Happy to rebase or squash differently if that helps when you're ready to merge.

Comment thread simple-git-hooks.js Outdated
_getRepoScopedHooksPath falls through to undefined when no repo-scoped
core.hooksPath is set, which the caller's !customHooksDirPath check
already handles. JSDoc updated to match.
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.

Follow-up to #149: worktree-scoped core.hooksPath is invisible to --local, so hooks install where git never reads

2 participants