Why is my Git pre-commit hook not executable by default?
GitGithooksGit Problem Overview
If you see the accepted answer in:
https://stackoverflow.com/questions/8598246/aggregating-and-uglifying-javascript-in-a-git-pre-commit-hook, you'll see that I had to do a chmod +x
on my pre-commit hook to get it to work.
Why is this not executable by Git by default?
Git Solutions
Solution 1 - Git
My context - web development Node.js. I needed to add husky functionality, but got an error, probably to the disk access. This helped in my situation:
chmod ug+x .husky/*
chmod ug+x .git/hooks/*
Solution 2 - Git
Because files are not executable by default; they must be set to be executable.
The sample files from a git init
are all executable; if it's copied or renamed to a non-sample file, it will retain the original file's x
flag.
New files will be created with current defaults. In your case, view those defaults with umask
:
$ umask
0022
By default, new files won't be u+x
unless explicitly set to be.
Solution 3 - Git
> I had to do a chmod +x
on my pre-commit hook to get it to work
The problem is to realize that it was not executable in the first place.
That will be easier with Git 2.15.x/2.16 (Q1 2018)
See commit f805a00 (06 Oct 2017) by Damien MariƩ (mdamien
).
(Merged by Junio C Hamano -- gitster
-- in commit 130b512, 06 Nov 2017)
> ## run-command
: add hint when a hook is ignored
> When an hook is present but the file is not set as executable then git will
ignore the hook.
For now this is silent which can be confusing.
> This commit adds this warning to improve the situation:
hint: The 'pre-commit' hook was ignored because it's not set as executable.
hint: You can disable this warning with `git config advice.ignoredHook false`
> To allow the old use-case of enabling/disabling hooks via the executable flag a new setting is introduced: advice.ignoredHook
.
Solution 4 - Git
Just as a reference, after making the file executable, if that appears in git file changes because of file mode changes, the following would work: (tried in Ubuntu/Linux)
chmod ug+x .husky/pre-commit # make file executable
git config core.filemode false # to ignore file mode changes
Reference: How do I remove files saying "old mode 100755 new mode 100644" from unstaged changes in Git?
Solution 5 - Git
I had the same symptoms, but a totally different cause:
In addition to setting the right permission bits via chmod +x .git/hooks/pre-commit
, please make sure your file system is mounted in a way that allows those changes. This can, e.g., be an issue when you have a dual-boot system where you are working on an ntfs-3g
mounted Windows drive under Linux.
You can fix it by changing the default permissions in /etc/fstab
or the systemd equivalent.
Solution 6 - Git
Just as an add-on answer, here is the function, you can use for initializing a Git repository, which automatically makes hooks executables; you should put it in .bashrc
or a file you source when you start your terminal. The story is below :)
ginit () {
git init
gitpath=`git rev-parse --show-superproject-working-tree --show-toplevel | head -1`
chmod u+x "$gitpath"/.git/hooks/*
for submodule in "$gitpath"/.git/modules/*; do
chmod u+x "$submodule"/hooks/*
done
}
I was annoyed by the same thing as you. I do not want to remember that I have to make all hooks executables every time I initialize a repository. Plus, when you use submodules, their hooks are not in .git/hooks
, but in .git/modules/NameOfSubmodule/hooks
, and these should be made executables too.