我们有一个开发团队,使用50/50分割的GitHub for Windows和Bash shell进行Git管理。
我们已经实现了一个预提交钩子(用于运行单元测试并在测试失败时失败)。作为一个简化版本,我附上了一个简化版本,下面将演示我们的问题。
#!/bin/sh
exit 1
如果我们尝试从bash shell提交,则预期的提交失败。但是,如果我们从GitHub for Windows应用程序执行相同的提交,它将成功提交到本地存储库。
那么有谁知道我们如何从GitHub应用程序中获得相同的功能?不幸的是,我们无法将用户从应用程序中移除,现在它已成为一个明显的漏洞。
感谢您的帮助。
答案 0 :(得分:22)
很抱歉成为坏消息的承载者,但GitHub for Windows不支持预提交挂钩,因为它使用libgit2提交。
答案 1 :(得分:2)
使用Git shell,您可以拥有提交挂钩。我有一些使用PowerShell的提交钩子。我发现了一个powerShell脚本做了lint我扩展为运行phpunit和phpcs(路径是硬编码所以你需要调整):
预提交文件:
#!/bin/sh
echo
exec powershell.exe -ExecutionPolicy RemoteSigned -File '.\.git\hooks\pre-commit-hook.ps1'
exit
pre-commit.ps1文件:
###############################################################################
#
# PHP Syntax Check for Git pre-commit hook for Windows PowerShell
#
# Author: Vojtech Kusy <wojtha@gmail.com>
# Author: Chuck "MANCHUCK" Reeves <chuck@manchuck.com>
#
###############################################################################
### INSTRUCTIONS ###
# Place the code to file "pre-commit" (no extension) and add it to the one of
# the following locations:
# 1) Repository hooks folder - C:\Path\To\Repository\.git\hooks
# 2) User profile template - C:\Users\<USER>\.git\templates\hooks
# 3) Global shared templates - C:\Program Files (x86)\Git\share\git-core\templates\hooks
#
# The hooks from user profile or from shared templates are copied from there
# each time you create or clone new repository.
### SETTINGS ###
# Path to the php.exe
$php_exe = "C:\php\php.exe";
# Path to the phpcs
$php_cs = "C:\Includes\PEAR\phpcs.bat";
# Path to the phpunit
$php_unit = "C:\Includes\PEAR\phpunit.bat";
# Path to the phpunit bootstrap file
$bootstrap = "tests\bootstrap.php";
# Flag, if set to 1 require test file to exist, set to 0 to disable
$requireTest = 1;
# Extensions of the PHP files
$php_ext = "php|phtml"
# Flag, if set to 1 git will unstage all files with errors, set to 0 to disable
$unstage_on_error = 0;
### FUNCTIONS ###
function php_syntax_check {
param([string]$php_bin, [string]$extensions, [int]$reset)
$err_counter = 0;
write-host "Pre-commit PHP syntax check:" -foregroundcolor "white" -backgroundcolor "black"
git diff-index --name-only --cached HEAD -- | foreach {
if ($_ -match ".*\.($extensions)$") {
$file = $matches[0];
$errors = & $php_bin -l $file
$testFileExists = (Test-Path $file -PathType Leaf)
write-host $file ": " -foregroundcolor "gray" -backgroundcolor "black" -NoNewline
if ($testFileExists) {
if ($errors -match "No syntax errors detected in $file") {
write-host "OK!" -foregroundcolor "green" -backgroundcolor "black"
}
else {
write-host "ERROR! " $errors -foregroundcolor "red" -backgroundcolor "black"
if ($reset) {
git reset -q HEAD $file
write-host "Unstaging ..." -foregroundcolor "magenta" -backgroundcolor "black"
}
$err_counter++
}
} else {
write-host "OK! (file deleted)" -foregroundcolor "green" -backgroundcolor "black"
}
}
}
if ($err_counter -gt 0) {
write-host "Some File(s) have syntax errors. Please fix then commit" -foregroundcolor "red" -backgroundcolor "black"
exit 1
}
}
function php_cs_check {
param([string]$php_cs, [string]$extensions, [int]$reset)
$err_counter = 0;
write-host "Pre-commit PHP codesniffer check:" -foregroundcolor "white" -backgroundcolor "black"
git diff-index --name-only --cached HEAD -- | foreach {
if ($_ -match ".*\.($extensions)$") {
$file = $matches[0];
write-host $file ": " -foregroundcolor "gray" -backgroundcolor "black" -NoNewline
if ($file -match "tests\/") {
write-host "PASSED! (test file)" -foregroundcolor "green" -backgroundcolor "black"
} else {
$errors = & $php_cs --standard=Zend $file
if ($LastExitCode) {
write-host "FAILED! (contains errors)" -foregroundcolor "red" -backgroundcolor "black"
if ($reset) {
git reset -q HEAD $file
write-host "Unstaging ..." -foregroundcolor "magenta" -backgroundcolor "black"
}
$err_counter++
} else {
write-host "PASSED!" -foregroundcolor "green" -backgroundcolor "black"
}
}
}
}
if ($err_counter -gt 0) {
write-host "Some File(s) are not following proper codeing standards. Please fix then commit" -foregroundcolor "red" -backgroundcolor "black"
exit 1
}
}
function php_unit_check {
param([string]$php_unit, [string]$bootstrap, [string]$extensions, [int]$reset, [int]$requireTest)
$err_counter = 0;
write-host "Pre-commit PHP unit check:" -foregroundcolor "white" -backgroundcolor "black"
git diff-index --name-only --cached HEAD -- | foreach {
if ($_ -match ".*\.($extensions)$") {
$file = $matches[0];
write-host $file ": " -foregroundcolor "gray" -backgroundcolor "black" -NoNewline
if ($file -match "tests\/") {
write-host "SKIPPED! (test file)" -foregroundcolor "green" -backgroundcolor "black"
} elseif ($file -match ".*Bootstrap.php") {
write-host "SKIPPED! (bootstrap file)" -foregroundcolor "green" -backgroundcolor "black"
} elseif ($file -match "([application|library\\NDX].*)(.($extensions))$") {
$testFile = 'tests/' + $matches[1] + "Test.php";
$testFileExists = (Test-Path $testFile -PathType Leaf)
if ($testFileExists) {
$errors = & $php_unit --bootstrap $bootstrap $testFile
if ($LastExitCode) {
write-host "FAILED! (" $testFile ")" -foregroundcolor "red" -backgroundcolor "black"
if ($reset) {
git reset -q HEAD $file
write-host "Unstaging ..." -foregroundcolor "magenta" -backgroundcolor "black"
}
$err_counter++
} else {
write-host "PASSED!" -foregroundcolor "green" -backgroundcolor "black"
}
} elseif($requireTest) {
write-host "FAILED! Test file Not found: (" $testFile ")" -foregroundcolor "red" -backgroundcolor "black"
if ($reset) {
git reset -q HEAD $file
write-host "Unstaging ..." -foregroundcolor "magenta" -backgroundcolor "black"
}
$err_counter++
} else {
write-host "PASSED! (Test file not found and not required)" -foregroundcolor "darkGreen" -backgroundcolor "black"
}
} else {
write-host "IGNORED!" -foregroundcolor "darkGreen" -backgroundcolor "black"
}
}
}
if ($err_counter -gt 0) {
write-host "Some File(s) failed unit testing. Please fix then commit" -foregroundcolor "red" -backgroundcolor "black"
exit 1
}
}
### MAIN ###
php_syntax_check $php_exe "php|phtml" $unstage_on_error
write-host
php_cs_check $php_cs "php" $unstage_on_error
write-host
php_unit_check $php_unit $bootstrap "php" $unstage_on_error $requireTest
答案 2 :(得分:0)
您可以考虑使用Visual Studio(或构建器)预构建事件,但如果需要完全自动化,那么也存在问题。 Here is an example use.现在,该解决方案在路径上也需要git.exe
,但用户无需与其进行交互。如果比我更聪明的人能够解决写作中提到的反斜杠问题,那就太好了。
答案 3 :(得分:0)
添加答案作为当前选择的答案不再是这种情况。我能够编写一个预提交的钩子,该钩子可在Windows的GitHub Desktop,Windows的SourceTree和Windows的Git Bash中使用。
我不确定Windows提交钩子是否有硬性要求,但是我像下面这样包含了对sh.exe的确切引用:
#!C:/Program\ Files/Git/usr/bin/sh.exe
运行正常!