| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
On Windows, `run_commit_hook` runs an extensionless hook through Bash and passes the hook's path relative to the working tree (`os.path.relpath`). Bash resolves that path in its own view of the filesystem, which differs from the Windows one across a mount point. Git for Windows mounts the user's temporary directory as `/tmp` (`none /tmp usertemp` in its `/etc/fstab`). For a repository under `%TEMP%` and a `core.hooksPath` outside it, such as a global `~/.config/git/hooks`, Bash starts in `/tmp/tmpXXXX/repo`, and `../../../../../.config/git/hooks/pre-commit`, correct on the Windows side, leads to `/.config/git/hooks/pre-commit`. Every commit then fails with exit code 127 and `No such file or directory`. A relative path that stays inside the working tree cannot cross such a mount, so it is kept. A path that leaves the working tree (one starting with `..`) is now passed as the absolute path in POSIX form (`C:/...`), as is already done for a hook on another drive, when the Bash is Git for Windows' own or one found on `PATH`: both accept it. The bare `bash.exe` fallback may be the WSL launcher, which cannot open a Windows absolute path, so it keeps the relative path as before. `test_run_commit_hook_outside_worktree_on_windows` now checks the three cases (outside the working tree with a found Bash, inside it, outside it with the bare fallback), and `test_pre_commit_hook_outside_worktree` runs a real hook through a `core.hooksPath` outside the working tree. Validated on Windows 11 with Git for Windows 2.50.1 and Python 3.14: `test/test_index.py` passes with an empty global Git configuration (183 passed, 3 skipped, 1 xpassed), and the new command-construction assertion fails without the change; `ruff` 0.16.9 and `mypy` report no issues on the changed files; a commit in a repository under `%TEMP%`, with a global `core.hooksPath` holding a `pre-commit` hook, succeeds instead of failing with exit code 127. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
The focused fix preserves existing fallback behavior, includes regression coverage, and has no identified blocking issues.
0 open findings
What changed in this PRThis PR fixes Windows hook execution when core.hooksPath points outside a working tree under %TEMP%, addressing #2287.
Review by GitHub Copilot.
Changes:
| File | Description |
|---|---|
| test/test_index.py | Tests path selection and external-hook execution. |
| git/index/fun.py | Adjusts Windows hook paths while preserving fallback behavior. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Sorry, something went wrong.
|
Double checked with Codex on Windows, and WSL support as well. |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Fixes #2287.
On Windows, a hook found through a core.hooksPath outside the working tree is passed to Bash by a path relative to the working tree. Git for Windows mounts the user's temporary directory as /tmp, so from a repository under %TEMP% that relative path leads elsewhere in Bash, and the hook fails with exit code 127 (details in #2287).
Change
In run_commit_hook (git/index/fun.py):
Tests
Validation
On Windows 11 with Git for Windows 2.50.1 and Python 3.14:
Not run here: Linux and macOS (the command-construction test mocks sys.platform, so CI runs it there too) and a WSL bash.exe.
A related observation, outside the scope of this PR: with a global core.hooksPath set, some hook tests in test/test_index.py (for example test_pre_commit_hook_fail and test_commit_msg_hook_fail) fail even with this change, because they expect the hook from the repository's own hooks directory while Git's configuration points elsewhere. They pass with an empty global configuration.
🤖 Generated with Claude Code