Problem
Git hooks are shared by linked worktrees, but ignored build state such as node_modules is not. A clean release worktree can therefore reach pre-push without the executables required by that hook.
This happened while publishing v6.4.0: the first signed-tag push stopped locally because eslint was unavailable in the release worktree. Nothing reached the remote, and the retry passed after dependencies were made available, but the failure exposed an avoidable and poorly diagnosed worktree bootstrap gap.
Native Git behavior
Git has no dedicated post-worktree-add hook. It does run post-checkout after git worktree add unless --no-checkout is used:
https://git-scm.com/docs/githooks#_post_checkout
Because post-checkout also runs for ordinary checkout/switch operations and clone, any bootstrap must be idempotent and cheap when current.
Proposed contract
Add a repository-owned linked-worktree bootstrap path:
- a
post-checkout hook delegates to a tested bootstrap command;
- the command distinguishes a linked worktree by comparing the absolute Git directory and common Git directory;
- bootstrap state is recorded per worktree, not in the shared common directory;
- the state fingerprints
pnpm-lock.yaml so unchanged worktrees are a no-op and changed dependency graphs are refreshed;
- dependency hydration uses
pnpm install --frozen-lockfile --prefer-offline, preserving branch-correct links while reusing pnpm's content-addressed package store;
git worktree add --no-checkout and an explicit opt-out are documented;
- failures explain the exact recovery command and do not imply that Git rolled back an already-created worktree;
- the security posture around automatically running package lifecycle scripts after checkout is explicit.
Do not solve this by permanently symlinking one worktree's entire node_modules into another. That couples branches to one dependency layout and can become incorrect when lockfiles diverge.
Acceptance criteria
Release impact
This is developer tooling and release-process hardening. It is not a blocker for the already reviewed v6.4.0 artifact and should land independently.
Problem
Git hooks are shared by linked worktrees, but ignored build state such as
node_modulesis not. A clean release worktree can therefore reachpre-pushwithout the executables required by that hook.This happened while publishing v6.4.0: the first signed-tag push stopped locally because
eslintwas unavailable in the release worktree. Nothing reached the remote, and the retry passed after dependencies were made available, but the failure exposed an avoidable and poorly diagnosed worktree bootstrap gap.Native Git behavior
Git has no dedicated
post-worktree-addhook. It does runpost-checkoutaftergit worktree addunless--no-checkoutis used:https://git-scm.com/docs/githooks#_post_checkout
Because
post-checkoutalso runs for ordinary checkout/switch operations and clone, any bootstrap must be idempotent and cheap when current.Proposed contract
Add a repository-owned linked-worktree bootstrap path:
post-checkouthook delegates to a tested bootstrap command;pnpm-lock.yamlso unchanged worktrees are a no-op and changed dependency graphs are refreshed;pnpm install --frozen-lockfile --prefer-offline, preserving branch-correct links while reusing pnpm's content-addressed package store;git worktree add --no-checkoutand an explicit opt-out are documented;Do not solve this by permanently symlinking one worktree's entire
node_modulesinto another. That couples branches to one dependency layout and can become incorrect when lockfiles diverge.Acceptance criteria
git worktree addcan leave a linked worktree ready to run repository hooks and tests.post-checkoutinvocations with an unchanged lockfile perform no install.--no-checkout, opt-out, failure, and recovery behavior are documented.Release impact
This is developer tooling and release-process hardening. It is not a blocker for the already reviewed v6.4.0 artifact and should land independently.