← 返回首页
Fix commit hooks to respect core.hooksPath configuration by MirrorDNA-Reflection-Protocol · Pull Request #2090 · gitpython-developers/GitPython · GitHub
Skip to content

Navigation Menu

Toggle navigation
Sign in
Appearance settings
Search or jump to...

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Resetting focus

Fix commit hooks to respect core.hooksPath configuration#2090

Draft
MirrorDNA-Reflection-Protocol wants to merge 4 commits into
gitpython-developers:mainfrom
MirrorDNA-Reflection-Protocol:fix-core-hookspath-support
Draft

Fix commit hooks to respect core.hooksPath configuration#2090
MirrorDNA-Reflection-Protocol wants to merge 4 commits into
gitpython-developers:mainfrom
MirrorDNA-Reflection-Protocol:fix-core-hookspath-support

Conversation

Copy link
Copy Markdown

Summary

Fixes #2083

The run_commit_hook() function was hardcoded to look for hooks in $GIT_DIR/hooks, ignoring the core.hooksPath configuration option that Git has supported since v2.9.

Changes

  • Add _get_hooks_dir() helper function that reads core.hooksPath from config
  • Handle both absolute and relative paths per git-config documentation:
    • Absolute paths: used as-is
    • Relative paths: resolved relative to the working tree root (or git_dir for bare repos)
    • Not set: defaults to $GIT_DIR/hooks
  • Update run_commit_hook() to use the new helper
  • Add comprehensive tests for both absolute and relative hooksPath configurations

Testing

  • All existing hook tests pass
  • Added 2 new tests:
    • test_run_commit_hook_respects_core_hookspath - tests absolute path
    • test_run_commit_hook_respects_relative_core_hookspath - tests relative path

Backwards Compatibility

The existing hook_path() function is preserved for backwards compatibility and has been documented to note that it does not respect the config. Code that directly uses hook_path() will behave as before. Only code using run_commit_hook() (including index.commit()) will benefit from the new behavior.

References

Fixes gitpython-developers#2083 The run_commit_hook() function was hardcoded to look for hooks in $GIT_DIR/hooks, ignoring the core.hooksPath configuration option that Git has supported since v2.9. Changes: - Add _get_hooks_dir() helper that reads core.hooksPath from config - Handle both absolute and relative paths per git-config documentation - Update run_commit_hook() to use the new helper - Add comprehensive tests for both absolute and relative hooksPath Per git-config documentation: - Absolute paths are used as-is - Relative paths are resolved relative to the working tree root (or git_dir for bare repos) - If not set, defaults to $GIT_DIR/hooks The existing hook_path() function is preserved for backwards compatibility and documented to note it does not respect the config.
Byron requested a review from Copilot December 7, 2025 15:52
Byron marked this pull request as draft December 7, 2025 15:53
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality Hide comment

Pull request overview

This PR fixes issue #2083 by adding support for Git's core.hooksPath configuration option to the run_commit_hook() function. Previously, GitPython hardcoded the hooks directory to $GIT_DIR/hooks, ignoring any custom hooks path configured by users.

Key Changes:

  • Introduced _get_hooks_dir() helper function to read and resolve core.hooksPath configuration
  • Updated run_commit_hook() to use the new helper for determining the hooks directory
  • Added comprehensive tests for both absolute and relative core.hooksPath configurations

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
git/index/fun.py Added _get_hooks_dir() helper function that respects core.hooksPath config; updated run_commit_hook() to use new helper; added documentation note to hook_path() function about config limitations
test/test_index.py Added two new test cases covering absolute and relative core.hooksPath configurations with appropriate Windows-specific xfail decorators

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread test/test_index.py
Comment on lines +1109 to +1136
def test_run_commit_hook_respects_relative_core_hookspath(self, rw_repo):
"""Test that run_commit_hook() handles relative core.hooksPath correctly.

Per git-config docs, relative paths for core.hooksPath are relative to
the directory where hooks are run (typically the working tree root).
"""
index = rw_repo.index

# Create a custom hooks directory with a relative path
custom_hooks_dir = Path(rw_repo.working_tree_dir) / "relative-hooks"
custom_hooks_dir.mkdir()

# Create a hook in the custom location
custom_hook = custom_hooks_dir / "fake-hook"
custom_hook.write_text(HOOKS_SHEBANG + "echo 'ran from relative hooks path' >output.txt")
custom_hook.chmod(0o744)

# Set core.hooksPath to a relative path
with rw_repo.config_writer() as config:
config.set_value("core", "hooksPath", "relative-hooks")

# Run the hook - it should resolve the relative path correctly
run_commit_hook("fake-hook", index)

output_file = Path(rw_repo.working_tree_dir) / "output.txt"
self.assertTrue(output_file.exists(), "Hook should have created output.txt")
output = output_file.read_text(encoding="utf-8")
self.assertEqual(output, "ran from relative hooks path\n")
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality Hide comment

The test only covers non-bare repositories (bare=False). Consider adding test coverage for bare repositories with relative core.hooksPath, since the logic in _get_hooks_dir() falls back to git_dir for bare repos when resolving relative paths (line 98 of git/index/fun.py).

Copilot uses AI. Check for mistakes.
Comment thread git/index/fun.py Outdated
- If not set: defaults to $GIT_DIR/hooks
"""
# Import here to avoid circular imports
from git.repo.base import Repo
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality Hide comment

The import statement from git.repo.base import Repo is only used for type hinting in the function signature on line 71. This import is already conditionally imported at the module level within the TYPE_CHECKING block (see lines 48-52), making this local import unnecessary. Consider removing this local import and relying on the string annotation "Repo" which is already being used.

Suggested change
from git.repo.base import Repo

Copilot uses AI. Check for mistakes.
Comment thread test/test_index.py
Comment on lines +1069 to +1096
def test_run_commit_hook_respects_core_hookspath(self, rw_repo):
"""Test that run_commit_hook() respects core.hooksPath configuration.

This addresses issue #2083 where commit hooks were always looked for in
$GIT_DIR/hooks instead of respecting the core.hooksPath config setting.
"""
index = rw_repo.index

# Create a custom hooks directory outside of .git
custom_hooks_dir = Path(rw_repo.working_tree_dir) / "custom-hooks"
custom_hooks_dir.mkdir()

# Create a hook in the custom location
custom_hook = custom_hooks_dir / "fake-hook"
custom_hook.write_text(HOOKS_SHEBANG + "echo 'ran from custom hooks path' >output.txt")
custom_hook.chmod(0o744)

# Set core.hooksPath in the repo config
with rw_repo.config_writer() as config:
config.set_value("core", "hooksPath", str(custom_hooks_dir))

# Run the hook - it should use the custom path
run_commit_hook("fake-hook", index)

output_file = Path(rw_repo.working_tree_dir) / "output.txt"
self.assertTrue(output_file.exists(), "Hook should have created output.txt")
output = output_file.read_text(encoding="utf-8")
self.assertEqual(output, "ran from custom hooks path\n")
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality Hide comment

The test only covers non-bare repositories (bare=False). Consider adding test coverage for bare repositories with core.hooksPath set, since the existing test_run_commit_hook test on line 1050 uses a bare repository. This is important because the logic in _get_hooks_dir() falls back to git_dir for bare repos when resolving relative paths (line 98 of git/index/fun.py).

Copilot uses AI. Check for mistakes.
Also clean up whitespace and move type import to TYPE_CHECKING block.
Place hooks inside git_dir to avoid path resolution issues on Windows where absolute paths outside the repo directory fail the relative_to check.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Commit hooks don't respect core.hooksPath in config.

2 participants

Footer

© 2026 GitHub, Inc.