Skip to content

[Bug]: pre-commit hook generated by 'make pre-commit' fails inside git worktrees #1641

@harshitsinghbhandari

Description

@harshitsinghbhandari

I have done the following

  • I have searched the existing issues
  • If possible, I've reproduced the issue using the 'main' branch of this project

Steps to reproduce

  1. Clone the repo and run make pre-commit in the main checkout.
  2. Add a worktree: git worktree add /tmp/wt-test.
  3. From /tmp/wt-test, attempt to make any commit (e.g. git commit --allow-empty -m "test").

Expected: the pre-commit hook runs make check from the worktree.

Actual: the commit fails with bash: ...: Not a directory from the hook wrapper, because the wrapper tries to exec pre-commit.fmt at a path that does not exist inside a worktree.

Problem description

The generated hook line at Makefile:325 is:

PRECOMMIT_NOFMT=${PRECOMMIT_NOFMT} $(git rev-parse --show-toplevel)/.git/hooks/pre-commit.fmt

In a worktree:

  • git rev-parse --show-toplevel resolves to the worktree's checkout path (e.g. /tmp/wt-test).
  • .git inside a worktree is a file containing gitdir: ... (not a directory), so <worktree>/.git/hooks/pre-commit.fmt is invalid.
  • Bash errors with "Not a directory."

The actual pre-commit.fmt lives in the main repo's .git/hooks/, but the wrapper's path computation never finds it.

The same assumption breaks the pre-commit: target itself (Makefile:322-327) — cp scripts/pre-commit.fmt .git/hooks won't work from inside a worktree either, because .git is a file there.

Proposed fix: use git rev-parse --git-path hooks to resolve the shared hooks directory; it works correctly in both the main repo and any worktree.

.PHONY: pre-commit
pre-commit:
	$(eval HOOKS_DIR := $(shell git rev-parse --git-path hooks))
	cp scripts/pre-commit.fmt $(HOOKS_DIR)/
	touch $(HOOKS_DIR)/pre-commit
	cat $(HOOKS_DIR)/pre-commit | grep -v 'hooks/pre-commit\.fmt' > /tmp/pre-commit.new || true
	echo 'PRECOMMIT_NOFMT=$${PRECOMMIT_NOFMT} $$(git rev-parse --git-path hooks/pre-commit.fmt)' >> /tmp/pre-commit.new
	mv /tmp/pre-commit.new $(HOOKS_DIR)/pre-commit
	chmod +x $(HOOKS_DIR)/pre-commit

Verified inside /tmp/wt-test: git rev-parse --git-path hooks/pre-commit.fmt correctly returns the existing file path in the main repo's .git/hooks/.

Happy to send a PR for this.

Environment

  • OS: macOS 26.4 (Darwin 25.4.0)
  • Xcode: Command Line Tools (Swift 6.2.4)
  • Container: 89fa98c (main, debug build)

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    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