Skip to content

fix(skills): support git before 2.31 in the worktree hook scripts - #600

Merged
theCodeDrift merged 1 commit into
mainfrom
fix/refuse-main-checkout-old-git
Nov 2, 2026
Merged

theCodeDrift merged 1 commit into
mainfrom
fix/refuse-main-checkout-old-git

Conversation

@theCodeDrift

Copy link
Copy Markdown
Member

git rev-parse --path-format=absolute does not exist before git 2.31, and two worktree hook scripts depended on it.

  • refuse-main-checkout.sh (from chore: refuse commits in the primary checkout #599): under set -e the unknown option failed the pre-commit hook everywhere, worktrees included, so --no-verify, which agents are told never to use, became the only way to commit.
  • worktree-remove.sh: the failure exited 0, so on old git every worktree was silently left in place.

Both now resolve paths physically (cd … && pwd -P). The remove hook resolves --git-common-dir from inside the worktree, since it can print a relative path.

Measured with a git shim that rejects --path-format, through the real Husky runner:

Case Before After
Commit in a worktree exit 128 (blocked) commits
Commit in a worktree subdirectory blocked commits
Commit in the primary checkout blocked refused, exit 1
Primary checkout with CI=true blocked commits
WorktreeRemove payload left in place worktree and merged branch removed

Ported from the cloud repo's fix in taskless/taskless#420, whose review found it. No changeset: repo tooling, nothing ships.

`git rev-parse --path-format=absolute` does not exist before git 2.31.
In refuse-main-checkout.sh that failure, under set -e, failed the
pre-commit hook everywhere, worktrees included, so --no-verify became
the only way to commit. In worktree-remove.sh it exited 0 and silently
left every worktree in place.

Both now resolve paths physically with cd + pwd -P. Measured with a git
shim that rejects --path-format: the guard refuses in the primary
checkout and commits in a worktree, a worktree subdirectory, and under
CI; the remove hook removes the worktree and its merged branch.

Ported from taskless/taskless#420, where the cloud repo's review found it.
@theCodeDrift

Copy link
Copy Markdown
Member Author

@claude /review

@github-actions

github-actions Bot commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @theCodeDrift's task in 1m 24s —— View job


Review complete ✅

Review mode: incremental — read 0 prior review thread(s) before reviewing. .prior-review.json contains no reviewThreads, reviews, or prior top-level comments (other than the trigger comment itself) — this is the first review of this PR. All findings below are therefore [New], though there are none to report.

  • Read prior review data (.prior-review.json) — empty, first review
  • Fetch PR diff via gh pr diff
  • Read full contents of both changed scripts for context
  • Review correctness, security, performance, test adequacy, clarity
  • Post findings

Assessment

Both fixes are correct and narrowly scoped.

refuse-main-checkout.sh: Replacing the single git rev-parse --path-format=absolute --git-dir --git-common-dir call (unsupported before git 2.31) with two separate git rev-parse --git-dir / --git-common-dir calls, each resolved via cd ... && pwd -P, is sound:

  • cd handles both relative and absolute paths from rev-parse correctly.
  • pwd -P resolves symlinks, so the equality check at line 33 compares two canonical physical paths — actually a slight correctness improvement over the old code, which didn't canonicalize symlinks.
  • Under set -eu, a failure in either cd or rev-parse inside the command substitution propagates correctly (the assignment's exit status is the substitution's exit status), so the hook still fails safe rather than silently falling through.
  • Hooks run with CWD at the worktree's top level, so the relative paths --git-dir/--git-common-dir can return are resolved correctly without needing -C.

worktree-remove.sh: Resolving --git-common-dir from inside $worktree_path (via the nested cd "$worktree_path" && cd "$(git rev-parse --git-common-dir ...)") correctly accounts for the documented pre-2.31 behavior where --git-common-dir can print a path relative to the worktree rather than absolute. The nested command substitution executes in the already-cd'd subshell, so the relative path resolves against the worktree, not the caller's original CWD. The || exit 0 preserves the "err toward leaving things in place" contract described in the file's header comment. dirname on the resolved common dir correctly yields the main repo root for the standard (non-bare) layout this tool operates on.

No test harness exists for these hook scripts (checked .agents/skills/worktrees-pnpm/scripts/ — no test files for any of the three scripts), so the manual verification table in the PR description is consistent with existing practice in this area; not flagging missing tests as a gap.

Checked worktree-create.sh for the same --path-format=absolute pattern — it only uses --show-toplevel, which has always returned an absolute path, so it isn't affected by this git-version issue and needs no corresponding change.

No correctness, security, or clarity issues found.

@theCodeDrift

Copy link
Copy Markdown
Member Author

Re: @github-actions — "Claude finished @theCodeDrift's task in 1m 24s … Review complete"
#600 (comment)

Thanks. No findings, so nothing changed; merging once green.

— AI Coding Agent

@theCodeDrift
theCodeDrift merged commit 0907f20 into main Nov 2, 2026
8 checks passed
@theCodeDrift
theCodeDrift deleted the fix/refuse-main-checkout-old-git branch November 2, 2026 02:22
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