Omer Bin SaleemBuild with AI Subscribe
← All hacks Git3 min read

Why commits in a git worktree ran no husky hooks

In a linked worktree, husky’s runner folder was missing, so commits ran no hooks at all. Copying it in exposed a second trap, and a local clone fixed both.

How to do it

  1. Check first whether hooks run at all. Husky’s runner folder `.husky/_` is generated and gitignored, and `core.hooksPath=.husky/_` resolves per worktree. A linked worktree has no such folder, so commits there ran no pre-commit, commit-msg or pre-push hook.
  2. Copying `.husky/_` in makes the hooks run, but a hook that falls back to Docker can still fail. Our gitleaks step mounted only the worktree, whose `.git` file points at `<main>/.git/worktrees/<name>`, outside the mount, so it stopped with "not a git repository".
  3. Commit from a local clone instead: `git clone -q --no-checkout <main repo> <dir>`. A local clone hardlinks the objects, so the container can read them. Do not use `--shared`, because its alternates point at host paths.
  4. In the clone, run `checkout --detach <origin/branch SHA>` and `remote set-url origin <remote URL>`, copy user.name and user.email, `cp -R .husky/_`, set `core.hooksPath .husky/_`, and symlink `node_modules`. Commit and push from there, and delete the clone once `git ls-remote` shows the SHA.
  5. Read the working tree after each commit. The clone’s local main was 114 commits behind, so lint-staged’s `nx format:write` reformatted 30 app files that were never staged. The commit held only the staged files; `git show --name-only HEAD`, `git status` and `git restore --worktree -- .` cleared the rest.
  6. Keep the guard rails while you fix it: never `--no-verify`, and do not quietly install a local gitleaks, since every future commit would move off the pinned Docker version.
Prompt to copy
I commit from a linked git worktree in a repo that uses husky. Check whether hooks really run here: read `git config core.hooksPath`, check that folder exists in this worktree, and list the hooks that would fire. Never use --no-verify or install a tool. If the runner is missing or a Docker hook cannot see the repo, set up a local clone with `git clone --no-checkout` (never --shared) at my branch SHA, copy the hooks folder and git identity, symlink node_modules, and show each command before running it. After the commit, show `git status` so I can restore files a formatter touched outside the commit.