This error occurs when Git cannot execute a hook script, typically due to a missing or invalid shebang line, Windows line endings (CRLF), or a corrupted hook file. Fixing the shebang or regenerating the hook resolves most cases.
When Git shows `error: cannot run .git/hooks/<hook-name>: No such file or directory`, it means Git found a hook file but cannot execute it. Despite the misleading message, the file usually exists - the issue is that the system cannot locate the interpreter specified in the script's shebang line. The most common cause is a malformed or missing shebang line at the top of the hook script. The shebang (e.g., `#!/bin/bash` or `#!/bin/sh`) tells the operating system which interpreter to use. If this line is missing, corrupted, has an empty line before it, or references an interpreter that does not exist on your system, you will see this error. On Windows systems using Git Bash or WSL, this error frequently occurs due to CRLF line endings or file encoding issues (UTF-8 with BOM). The carriage return character makes the interpreter path invalid, causing the same 'No such file or directory' message.
First, verify the hook file exists and has execute permissions:
ls -la .git/hooks/pre-pushIf the file exists but is not executable, add execute permission:
chmod +x .git/hooks/pre-pushReplace pre-push with the actual hook name mentioned in your error (e.g., pre-commit, post-receive).
Check the first line of the hook script:
head -1 .git/hooks/pre-pushIt should show something like #!/bin/bash or #!/bin/sh. If it shows nothing, has garbage characters, or starts with an empty line, that is the problem.
You can also check for hidden characters:
cat -A .git/hooks/pre-push | head -3Look for ^M (carriage return) at the end of lines, which indicates Windows line endings.
Open the hook file in a text editor and ensure the very first line (no empty lines before it) contains a valid shebang:
#!/bin/sh
# Rest of your hook scriptOr if the script requires bash features:
#!/bin/bash
# Rest of your hook scriptFor better portability across systems, use #!/usr/bin/env sh or #!/usr/bin/env bash:
#!/usr/bin/env bash
# This works even when bash is not in /bin/If you edited the hook on Windows or see ^M characters, convert to Unix line endings:
# Using dos2unix
dos2unix .git/hooks/pre-push
# Using sed (if dos2unix not available)
sed -i 's/\r$//' .git/hooks/pre-pushOn macOS, the sed command is slightly different:
sed -i '' 's/\r$//' .git/hooks/pre-pushSome editors save files with a UTF-8 Byte Order Mark (BOM), which breaks the shebang:
file .git/hooks/pre-pushIf it shows 'UTF-8 Unicode (with BOM)', re-save the file as plain UTF-8 without BOM.
In VS Code: Open the file, click the encoding in the bottom-right (e.g., 'UTF-8 with BOM'), select 'Save with Encoding', and choose 'UTF-8'.
Ensure the interpreter specified in the shebang actually exists:
# Check for bash
which bash
# Check for sh
which shIf you are using Alpine Linux or a minimal Docker image, /bin/bash may not exist. Use /bin/sh instead:
#!/bin/shOr install bash:
apk add bashIf you use Git LFS and the hooks became corrupted, regenerate them:
git lfs update --forceThis overwrites the existing hooks with fresh copies. If you had custom hooks alongside LFS hooks, you may need to restore them afterward.
If you use SourceTree or another Git GUI that manages hooks, try deleting the problematic hook and letting the application regenerate it:
rm .git/hooks/pre-pushThen restart SourceTree. It will recreate the hook file on next operation.
Alternatively, create a fresh hook from the sample:
cp .git/hooks/pre-push.sample .git/hooks/pre-push
chmod +x .git/hooks/pre-pushIf you need to push urgently while investigating, you can bypass client-side hooks:
# Skip pre-push hook
git push --no-verify
# Skip pre-commit hook
git commit --no-verify -m "Your message"Warning: This bypasses the hook entirely. Use this only as a temporary workaround, not a permanent solution.
Why 'No such file or directory' is misleading: When the kernel parses a shebang line like #!/bin/bash\r (with a carriage return), it looks for an interpreter literally named /bin/bash\r. Since that file does not exist, you get 'No such file or directory' - even though both /bin/bash and the hook file itself exist.
Pre-commit framework hooks: If you use the pre-commit framework (https://pre-commit.com/), hooks are managed by the tool. Run pre-commit install --overwrite to regenerate them. The framework uses Python, so ensure your shebang points to a valid Python interpreter.
Windows WSL considerations: When using Git in WSL (Windows Subsystem for Linux), hooks created in Windows may have the wrong line endings. Always edit hooks from within WSL using a Linux editor, or configure your Windows editor to use LF line endings for files in WSL paths.
Shared hooks with core.hooksPath: If your team uses shared hooks via git config core.hooksPath, ensure the shared directory is accessible and scripts have correct permissions. The path must be absolute or relative to the repository root.
Server-side hooks: For pre-receive, post-receive, and other server-side hooks on remote repositories (like Bitbucket Server), the same principles apply. Check the hook files on the server, not your local machine.
kex_exchange_identification: Connection closed by remote host
Connection closed by remote host when connecting to Git server
fatal: unable to access: Proxy auto-configuration failed
How to fix 'Proxy auto-configuration failed' in Git
fatal: unable to access: Authentication failed (proxy requires basic auth)
How to fix 'Authentication failed (proxy requires basic auth)' in Git
fatal: unable to access: no_proxy configuration not working
How to fix 'no_proxy configuration not working' in Git
fatal: unable to read tree object in treeless clone
How to fix 'unable to read tree object in treeless clone' in Git