Skip to content

Fix: prevent hook reinstall loop when luca install runs inside a git worktree#12

Merged
albertodebortoli merged 1 commit intomainfrom
fix/worktree-hook-reinstall-loop
Apr 10, 2026
Merged

Fix: prevent hook reinstall loop when luca install runs inside a git worktree#12
albertodebortoli merged 1 commit intomainfrom
fix/worktree-hook-reinstall-loop

Conversation

@albertodebortoli
Copy link
Copy Markdown
Member

@albertodebortoli albertodebortoli commented Apr 8, 2026

Problem

When luca install is run from within a git worktree, the post-checkout hook triggers a failure cascade:

How git worktrees work

In a normal repository, .git is a directory. When you use git worktree add, each worktree gets a .git that is a regular file containing a pointer like gitdir: /path/to/main/repo/.git/worktrees/<name>. The actual hooks live only in the main repo's .git/hooks/ and are shared across all worktrees.

The failure cascade

  1. A developer switches branches in a worktree — git fires the post-checkout hook from the main repo's .git/hooks/post-checkout.
  2. The hook runs luca install --quiet, which (without this fix) attempts to re-install the post-checkout hook.
  3. luca install calls GitHookInstaller.installPostCheckoutHook(), which tries to write to .git/hooks/post-checkout — but in a worktree .git is a file, not a directory, so the path .git/hooks/post-checkout is invalid and the write fails.
  4. luca install exits non-zero, the hook logs a warning, and tool synchronisation may be skipped or incomplete.

This happens on every branch switch in every worktree, making the hook unreliable for anyone using git worktree.

Root Cause

The post-checkout hook calls luca install unconditionally without telling it to skip hook (re-)installation. Since the hook is already installed (it's the thing running right now), trying to install it again on every checkout is both unnecessary and broken in worktrees.

Fix

Pass --no-install-post-checkout-git-hook to the luca install invocation in the post-checkout script. This tells the CLI not to attempt hook installation during a hook-triggered run — the hook is already in place.

# Before
luca install --quiet

# After
luca install --quiet --no-install-post-checkout-git-hook

Note: A companion fix LucaTools/Luca#57 is required in the Luca CLI itself (GitHookInstaller.swift) to:

  1. Support the --no-install-post-checkout-git-hook flag.
  2. Independently guard against worktrees by checking that .git is a directory (not just that it exists) before attempting hook installation.
    This PR addresses the script side; the CLI side should be handled in the luca repository.

Test Plan

  • Existing bats test luca install: called with correct args on happy path updated to assert the new flag is passed — all 13 tests in post_checkout.bats pass.
  • Manually switch branches in a git worktree and confirm no hook-installation warning appears.
  • Confirm tool synchronisation still works correctly in a normal (non-worktree) checkout.

Pass --no-install-post-checkout-git-hook to `luca install` invoked by
the post-checkout hook, so that hook execution never triggers a
redundant re-installation of itself.
@albertodebortoli
Copy link
Copy Markdown
Member Author

Accidentally closed by LucaTools/Luca#57.
Proceeding with the merge.

@albertodebortoli albertodebortoli merged commit c1be19b into main Apr 10, 2026
4 checks passed
@albertodebortoli albertodebortoli deleted the fix/worktree-hook-reinstall-loop branch April 10, 2026 11:37
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.

1 participant