@@ -79,6 +79,21 @@ def _has_file_extension(path: str) -> str:
7979 return osp .splitext (path )[1 ]
8080
8181
82+ def _which_from_path (command : str ) -> Union [str , None ]:
83+ """Resolve an executable 'command' from PATH without considering the current directory."""
84+ cwd = osp .normcase (osp .abspath (os .curdir ))
85+ for directory in os .get_exec_path ():
86+ if not directory :
87+ continue
88+ directory = osp .abspath (directory )
89+ if osp .normcase (directory ) == cwd :
90+ continue
91+ candidate = osp .join (directory , command )
92+ if osp .isfile (candidate ) and os .access (candidate , os .X_OK ):
93+ return candidate
94+ return None
95+
96+
8297def run_commit_hook (name : str , index : "IndexFile" , * args : str ) -> None :
8398 """Run the commit hook of the given name. Silently ignore hooks that do not exist.
8499
@@ -112,7 +127,11 @@ def run_commit_hook(name: str, index: "IndexFile", *args: str) -> None:
112127 # an absolute path in this form, although a relative path is preferable
113128 # because it also works with the Windows Subsystem for Linux wrapper.
114129 bash_hp = hp
115- cmd = ["bash.exe" , Path (bash_hp ).as_posix ()]
130+ # Resolve through PATH before spawning. On Windows, CreateProcess searches
131+ # the current and system directories before PATH for a bare executable name,
132+ # which can otherwise select an impostor or the WSL launcher instead of Git
133+ # for Windows' Bash.
134+ cmd = [_which_from_path ("bash.exe" ) or "bash.exe" , Path (bash_hp ).as_posix ()]
116135
117136 process = safer_popen (
118137 cmd + list (args ),
0 commit comments