Skip to content

Commit ba08995

Browse files
feat: fall back to main worktree config in linked worktrees
When using `git worktree add`, the linked worktree inherits `core.hooksPath` (pointing at the common git dir's hooks) but not the untracked `.pre-commit-config.yaml` symlink — that symlink is only created on shell entry via `installationScript`. Until then every `git commit` in the linked worktree fails with "No .pre-commit-config.yaml file was found". After `pre-commit install` writes the hook scripts, patch each one to splice a prelude after the shebang and rewrite the `--config=` literal in the `ARGS=` line to read from a variable resolved by that prelude. At hook runtime the prelude resolves the config path: 1. The current toplevel's `cfg.configPath` if present. 2. Otherwise, only in a linked worktree (detected by comparing `git rev-parse --git-dir` against `--git-common-dir`), the main worktree's config. 3. Otherwise `exit 0`. Behavior in the main worktree is unchanged: a missing config there still produces pre-commit's normal error. A marker comment makes the patch idempotent across repeated shell entries. Fixes #710 Assisted-by: Claude:claude-sonnet-4-6
1 parent 61ab0e8 commit ba08995

1 file changed

Lines changed: 31 additions & 0 deletions

File tree

modules/pre-commit.nix

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,37 @@ in
543543
# Convert the absolute path to a path relative to the toplevel working directory.
544544
common_dir=''${common_dir#''$GIT_WC/}
545545
546+
# Patch installed hook scripts to fall back to the main worktree's config in linked worktrees.
547+
_prelude=$(mktemp)
548+
cat > "$_prelude" <<'PRELUDE'
549+
# git-hooks.nix: worktree-config-fallback
550+
_git=${lib.getExe cfg.gitPackage}
551+
_cfg_rel=${cfg.configPath}
552+
_top=$("$_git" rev-parse --show-toplevel)
553+
_config="$_top/$_cfg_rel"
554+
if [ ! -e "$_config" ]; then
555+
_dir=$("$_git" rev-parse --git-dir)
556+
_common=$("$_git" rev-parse --path-format=absolute --git-common-dir)
557+
if [ "$_dir" != "$_common" ]; then
558+
_alt="$(dirname "$_common")/$_cfg_rel"
559+
if [ -e "$_alt" ]; then
560+
_config="$_alt"
561+
else
562+
exit 0
563+
fi
564+
fi
565+
fi
566+
PRELUDE
567+
for hook in ${concatStringsSep " " (remove "manual" supportedHooksLib.supportedHooks)}; do
568+
hook_file="''${GIT_WC}/''${common_dir}/hooks/''${hook}"
569+
[ -f "''${hook_file}" ] || continue
570+
if ! grep -qF '# git-hooks.nix: worktree-config-fallback' "''${hook_file}"; then
571+
sed -i "1r ''${_prelude}" "''${hook_file}"
572+
sed -i 's|--config=${cfg.configPath}|--config="$_config"|' "''${hook_file}"
573+
fi
574+
done
575+
rm -f "$_prelude"
576+
546577
${lib.getExe cfg.gitPackage} config --local core.hooksPath "''$common_dir/hooks"
547578
fi
548579
fi

0 commit comments

Comments
 (0)