Skip to content

Hooks can't find attestation in git worktrees (hardcoded relative .git/lrc path) #89

@leaft

Description

@leaft

Summary

The lrc-managed git hooks fail to locate an existing attestation when committing inside a linked git worktree (git worktree add). Even after a successful lrc review / lrc review --vouch / lrc review --skip, the commit is rejected with:

LiveReview: review attestation missing for staged changes. Run 'lrc review --staged' (or --skip/--vouch) and retry commit.

lrc_version: v0.3.9 (from the managed hook section header).

Root cause

The hooks locate the attestation using a hardcoded relative path .git/lrc/.... In a linked worktree, .git is not a directory — it is a pointer file whose contents are gitdir: /path/to/main/.git/worktrees/<name>. So .git/lrc/attestations/<tree>.json never resolves, and the [ -f "$ATTEST_FILE" ] test always fails.

Meanwhile lrc review writes the attestation to the per-worktree git dir, i.e. <main>/.git/worktrees/<name>/lrc/attestations/<tree>.json — which is exactly where git rev-parse --git-dir points from inside the worktree. So the file is written to one location and looked up in another.

Notably, the hooks already compute the correct dir but don't use it. In lrc/prepare-commit-msg and lrc/commit-msg:

LRC_DIR=".git/lrc"                 # <-- hardcoded, breaks in worktrees
ATTEST_DIR="$LRC_DIR/attestations"
...
GIT_DIR="$(git rev-parse --git-dir 2>/dev/null || echo .git)"   # computed but never used for ATTEST_DIR
...
TREE_HASH="$(git write-tree 2>/dev/null || true)"
ATTEST_FILE="$ATTEST_DIR/$TREE_HASH.json"

And in lrc/pre-commit:

TREE_HASH="$(git write-tree 2>/dev/null || true)"
ATTEST_FILE=".git/lrc/attestations/$TREE_HASH.json"   # <-- same hardcoded .git

All three hooks (pre-commit, prepare-commit-msg, commit-msg) share this bug.

Reproduction

# main repo
git init main && cd main
echo a > a.txt && git add a.txt
lrc review --skip          # writes attestation, commit works here
git commit -m "init"

# linked worktree on a new branch
git worktree add ../wt -b feature
cd ../wt
echo b > b.txt && git add b.txt
lrc review --skip          # reports success; attestation written to
                           #   <main>/.git/worktrees/wt/lrc/attestations/<tree>.json
git commit -m "change"     # FAILS: "review attestation missing for staged changes"

You can confirm the attestation exists and matches the staged tree:

git write-tree
# -> <tree-hash>   (matches the .json filename under the per-worktree git dir)
cat "$(git rev-parse --git-dir)/lrc/attestations/<tree-hash>.json"
# -> {"action":"vouched",...}   (present and correct)

Expected

Inside a linked worktree, a valid attestation produced by lrc review for the current staged tree should let the commit proceed, exactly as in a normal (non-worktree) checkout.

Actual

The commit is rejected because the hooks look under the literal .git/lrc/... relative path, which is invalid in a worktree (.git is a file, not a directory).

Suggested fix

Derive the lrc dir from git instead of hardcoding .git. The hooks already compute GIT_DIR; just use it:

GIT_DIR="$(git rev-parse --git-dir 2>/dev/null || echo .git)"
LRC_DIR="$GIT_DIR/lrc"
ATTEST_DIR="$LRC_DIR/attestations"

(git rev-parse --git-dir returns the per-worktree git dir, matching where the CLI writes the attestation. If attestations are intended to be shared across worktrees, --git-common-dir would be the alternative — but the CLI currently writes to the per-worktree dir, so --git-dir keeps hook and CLI consistent.) The same substitution is needed in pre-commit (which inlines the literal .git/lrc/attestations/...).

The .git/lrc/disabled check at the top of the hooks has the same hardcoded-path issue and should use $GIT_DIR/lrc/disabled too — otherwise the hook cannot be disabled from within a worktree either.

Workaround note

git commit --no-verify does not help, because the attestation check also runs in prepare-commit-msg, which git does not skip with --no-verify (it only skips pre-commit and commit-msg). A one-shot git -c core.hooksPath=<empty-dir> commit ... after a genuine lrc review/--vouch is the only clean bypass until this is fixed.

Environment

  • OS: macOS
  • git: 2.50.1
  • git-lrc: v0.3.9

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions