91

If you see the accepted answer in: 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?

anthony sottile
  • 61,815
  • 15
  • 148
  • 207
Josh Smith
  • 14,674
  • 18
  • 72
  • 118

9 Answers9

119

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/*
Roman
  • 19,236
  • 15
  • 93
  • 97
  • 2
    Yeah, only this worked for me. – Arslan Shahab Oct 08 '21 at 07:54
  • From *"[What is Husky?](https://www.freecodecamp.org/news/how-to-add-commit-hooks-to-git-with-husky-to-automate-code-tasks/#what-is-husky)"*: *"Husky is a tool that allows us to easily wrangle Git hooks and run the scripts we want at those stages."* – Peter Mortensen Nov 24 '21 at 20:46
  • 3
    An explanation would be in order. E.g., what is the idea/gist? Why does it work? Why is *group* required? What is this *"husky"* thingy (for instance, I only have *dot* folders *".git"* and *".vscode"* in my repository)? What are the security implications of this change? What was context - some kind web development? Node.js? Please respond by [editing (changing) your answer](https://stackoverflow.com/posts/66757359/edit), not here in comments (***without*** "Edit:", "Update:", or similar - the answer should appear as if it was written today). – Peter Mortensen Nov 24 '21 at 20:47
55

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.

Dave Newton
  • 158,873
  • 26
  • 254
  • 302
  • I'm running git v1.7.6 on Mac OS X Lion. I'd done `git init` to reinitialize the repo and that still didn't work. I edited the file in TextMate, which might be the problem, but still doesn't explain why `git init` wouldn't do the `chmod u+x` properly. – Josh Smith Dec 22 '11 at 02:07
  • @JoshSmith `git init` only creates sample hooks, not actual ones. I'm running 1.7.5.4 on Lion, and 1.7.0 on Ubuntu--they both create the sample files as `u+x`--I guess I'm a little skeptical it isn't on yours. – Dave Newton Dec 22 '11 at 02:10
  • If nothing else I discovered my Linux box is running an old-ish version of git. – Dave Newton Dec 22 '11 at 02:11
  • So am I going to have to `chmod` every single time I modify the hook? – Josh Smith Dec 22 '11 at 02:12
  • @JoshSmith Uh, no, once it's set, you shouldn't need to change it again. – Dave Newton Dec 22 '11 at 02:13
  • I meant more when I do such a hook in any new git repo. That's going to get annoying. – Josh Smith Dec 22 '11 at 02:14
  • @JoshSmith Then change your `umask` setting, and hope you never accidentally execute something you didn't mean to. Not that typing "chmod u+x" is all that onerous. Or copy the samples that are already set. – Dave Newton Dec 22 '11 at 02:15
  • the bit 2 is for write permission, the only thing that `umask` set to `022` does is to prevent new files to be writable by the group and other user, nothing to do with the execute bit which is 1. – Jean Paul Aug 04 '22 at 15:15
  • @JeanPaul If you re-read you’ll see that the “umask” example is to show example defaults, which are the defaults for new files. – Dave Newton Aug 04 '22 at 15:23
  • @DaveNewton Sorry I don't get the point, with a umask of 022 new files won't be g+w and o+w, that's all. I don't see the link with the executable permission. – Jean Paul Aug 04 '22 at 15:44
  • @JeanPaul There *is* no link with *my* umask results; I showed how to get the current `umask`. – Dave Newton Aug 04 '22 at 15:53
  • ok but why talking about umask if umask has nothing to do with the problem? the problem can only happen if the user executable bit is set in the umask like `0133`, but i wonder who sets a umask like this and we don't understand this from your explanations – Jean Paul Aug 06 '22 at 08:27
31

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.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
8

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?

Dhaval L.
  • 319
  • 5
  • 7
4

I was able to solve it by just running the command below.

chmod ug+x .husky/*

I init husky in Windows. After that, the problem occurred in WSL, and it is probably a problem that was not created considering the file permissions of Linux at the time of init in Windows.

Kyungeun Park
  • 113
  • 1
  • 10
3

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ato
  • 854
  • 1
  • 6
  • 9
1

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jakub Wagner
  • 428
  • 1
  • 5
  • 15
1

I've resolved this issue by running the below command

chmod ug+x .husky/*
venky royal
  • 1,860
  • 2
  • 11
  • 19
0

The original template hook file must be executable.

In my case, it was a custom hook missing the executable bit:

$ git config init.templateDir
~/.git_template
$ stat -c "%A" ~/.git_template/hooks/pre-commit 
-rw-r--r--
$ chmod u+x ~/.git_template/hooks/pre-commit

Now the pre-commit hook created on git init or git clone is properly set as executable:

$ git init hook-exec
$ stat -c "%A" hook-exec/.git/hooks/pre-commit 
-rwxrwxr-x

See https://git-scm.com/docs/git-init#_template_directory

Julien Carsique
  • 3,915
  • 3
  • 22
  • 28