20

I'm having trouble executing Git hooks on Windows. I have a bare repo and in it's "hooks" folder I put the following into both the "update" and "pre-push" files but the PHP script is never being executed:

"c:/Programs/PHP/php.exe" c:/Data/Scripts/git-pre-push.phpcli %1

Any ideas as to why the PHP script isn't executed?

In the Git console window I see the following when I try to push something to the bare repo:

POST git-receive-pack (437 bytes)
remote: error: hook declined to update refs/heads/master
To https://myuser@mydomain/samplerepo
! [remote rejected] master -> master (hook declined)
error: failed to push some refs to 'https://myuser@mydomain/samplerepo'

...so I know that the "update" is somehow being executed. When I remove that file the push works just fine.

TheStoryCoder
  • 3,403
  • 6
  • 34
  • 64
  • When I rename the hook file to a .bat file and execute it, everything works just fine! – TheStoryCoder Aug 16 '13 at 15:58
  • Which file are you referring to when you say you "renamed a file"? Are you hooks implemented as bash, php, or batch scripts? May we see the contents? –  Aug 16 '13 at 15:59

4 Answers4

31

By default, Git for Windows executes hook scripts using its own Windows port of the bash shell. Certainly, a Unix shell has no idea about %1. Supposedly, Git for Windows has extra hacks in place to detect "common" filename extensions — such as .bat — and take an alternate route in such a case.

I think your fix to your own program is the best, but another approach would be to rewrite your script to read

#!/bin/sh
c:/Programs/PHP/php.exe c:/Data/Scripts/git-pre-push.phpcli "$@"

(the shebang line has no real special sense under Windows other than hinting the next person to edit the script about the meaning of its content).

kostix
  • 51,517
  • 14
  • 93
  • 176
  • 11
    `c:/` should probably be `/c/` instead. – Micha Wiedenmann Aug 16 '13 at 17:44
  • Argh, it only works on 'pre-commit'. On 'pre-receive' and 'update' it just says the following no matter what I write: POST git-receive-pack (449 bytes) To https://username@mydomain/samplerepo ! [remote rejected] master -> master (pre-receive hook declined) error: failed to push some refs to 'https://username@mydomain/samplerepo' – TheStoryCoder Aug 19 '13 at 20:27
  • And even if I write only an echo statement in the hook file it gives that same error... – TheStoryCoder Aug 19 '13 at 20:31
  • @TheStoryCoder, I would say this indicates a hook exited with a non-zero exit code for some reason. What if you place explicit `exit 0` at the end? Also, contrary to `pre-commit`, `pre-receive` and `update` hooks are run on the server, so is your server running Windows as well? If no, are you sure the ownership/permissions on your scripts are okay to run by a process with whatever credentials your Git server process runs with? – kostix Aug 20 '13 at 15:00
  • Can you tell me where to find docs or apis of the "Git's bash port on Windows"? I've searched but got no useful result, thank you. – Xieranmaya May 10 '14 at 08:41
  • @Xieranmaya, two things: bash does not have any API -- neither "standard" nor its Windows port -- it's an interpreter which executes a script supplied to it. As to how to write bash scripts, the answer is "get any doc on Unix shell scripting", so google using these three last words to google. "Advanced bash scripting guide" is a well-known one piece of such documentation. – kostix May 10 '14 at 09:36
  • @kostix Thank you very much for explanation my confusion. I've found that the git client has installed a git-bash on my Windows, and I can easily invoke it in the context menu, and I think it must be the 'git port of bash' on Windows or at least just a bash on Windows. I'm trying my thought in that bash and it looks fine so far~ – Xieranmaya May 11 '14 at 05:01
2

On Windows, normally the special '#!' (called shebang) first line in PHP script has no effect . However, Git on Windows is able to recognize the shebang first line. You can write a commit-msg hook as below using PHP, it will be running on Windows properly.

#!D:/php/php.exe

<?php
echo 'commit-msg';
exit( 0 );    

See more on git hooks on windows

zhangyu12
  • 151
  • 1
  • 3
1
#!/bin/sh
echo "executing pre-commit"

# Instructions:

# Put this file into your .git/hooks folder and set as executable 

 #- for Windows (attrib +x pre-commit)
 #- for ubuntu (chmod +x pre-commit)

# If you want to skip the hook just add the --no-verify: git commit --no-verify

# ---------------------------------------------

# Modify this
# LIST='list\|of\|words\|splitted\|by\|slash\|and\|pipe'
LIST="puts\|debugger;\|binding.pry\|alert(\|console.log("

if git rev-parse --verify HEAD >/dev/null 2>&1; then
    against=HEAD
else
    against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi

for FILE in `git diff-index --name-status --cached $against -- | cut -c3-` ; do
    # Check if the file contains one of the words in LIST
    if grep -w $LIST $FILE; then
      echo $FILE." has unwanted word. Please remove it. If you want to skip that then run git commit -m '"your comment"' --no-verify"
      exit 1
    fi
      done
exit
Rohit Jangid
  • 2,291
  • 1
  • 11
  • 9
0

I believe the secret is in the shebang part - on windows you will need to give the full path to your sh.exe like this:

#!/bin/sh; C:/path/to/Git/bin/sh.exe

If you have cygwin installed you can also point to sh.exe or bash.exe located in cygwin/bin You can even utilize other scripting languages supported via cyqwin - e.g. ruby:

#!/usr/bin/env ruby; C:/path/to/cygwin/bin/ruby.exe
puts "RUBY HOOK RUNNING"
Arleth
  • 51
  • 1
  • 6