Skip to content

Make git hook installation worktree-safe and transactional #1672

@schickling

Description

@schickling

Problem

Downstream integrations (currently cachix/devenv) need to install hooks in repositories with linked worktrees and preserve existing Git config semantics. Today this requires custom wrapper logic around prek install, which has become complex and fragile.

Context

Reference context:

The downstream wrapper currently has to handle multiple edge cases around core.hooksPath and config scopes (--local vs --worktree), plus rollback on failure.

Desired behavior in prek install

Prek should own this behavior so integrators can call it directly without extra Git-config orchestration:

  1. Worktree-aware hooksPath updates
  • in linked non-bare worktrees, write core.hooksPath in worktree scope (not shared local scope)
  • do not clobber existing shared local hooksPath used by other worktrees
  1. No-op when no actual hook stage is installed
  • if effective stages are manual-only (or otherwise produce no Git hook install), do not rewrite hooksPath
  1. Transactional config mutation
  • if installation fails midway, restore prior Git config state
  • avoid leaving core.hooksPath empty/broken
  • avoid persisting unrelated config mutations introduced during setup
  1. Bare+worktree topology correctness
  • handle repositories where common dir is a bare repo and worktree is elsewhere
  • ensure resulting hooks path resolves correctly

Why this belongs in prek

Prek is the installer and has the most context to apply consistent, safe behavior. If this stays in each integration wrapper, every consumer has to reimplement subtle Git scope and rollback logic.

Proposed acceptance criteria

  • prek install succeeds in normal repo, linked worktree, and bare+worktree setups
  • failed install leaves Git config unchanged from pre-run state
  • manual-only runs do not mutate core.hooksPath
  • behavior is covered by tests in prek

Created on behalf of @schickling.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions