能否将PowerShell脚本用作git挂钩运行?
我在PowerShell提示符中运行git,这不应该有任何区别,但是我似乎无法使它们工作,因为挂钩的名称没有扩展名,而PowerShell需要(据我所知).ps1扩展名。 我不确定是否是这个问题,还是其他什么问题。
能否将PowerShell脚本用作git挂钩运行?
我在PowerShell提示符中运行git,这不应该有任何区别,但是我似乎无法使它们工作,因为挂钩的名称没有扩展名,而PowerShell需要(据我所知).ps1扩展名。 我不确定是否是这个问题,还是其他什么问题。
自从powershell 7.2版本以后,Windows系统的脚本必须使用 .ps1 扩展名。因此,这个答案将不起作用。
您可以直接在挂钩文件中嵌入PowerShell脚本。这是我使用过的一个挂钩的示例:
#!/usr/bin/env pwsh
# Verify user's Git config has appropriate email address
if ($env:GIT_AUTHOR_EMAIL -notmatch '@(non\.)?acme\.com$') {
Write-Warning "Your Git email address '$env:GIT_AUTHOR_EMAIL' is not configured correctly."
Write-Warning "It should end with '@acme.com' or '@non.acme.com'."
Write-Warning "Use the command: 'git config --global user.email <name@acme.com>' to set it correctly."
exit 1
}
exit 0
这个例子需要PowerShell Core,但结果将在跨平台上运行(假设该文件已经在Linux/macOS上进行了chmod +x)。
#!/usr/bin/env pwsh
同样适用于git rebase --exec
和git bisect run
。不幸的是,我注意到当脚本失败时,pwsh
不会以错误代码退出,因此请确保在某些情况下更改您的脚本以使用exit
关键字。 - Mariusz Pawelski/usr/bin/env: 'pwsh': 没有那个文件或目录
,而且我已经安装了 PowerShell Core。 - Bort#!/usr/bin/env -S pwsh -NoProfile
- CubanX将hooks文件夹中的pre-commit.sample重命名为pre-commit。 然后在相同的文件夹中创建一个名为pre-commit.ps1的powershell脚本文件。
#!/bin/sh
c:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -ExecutionPolicy RemoteSigned -File '.git\hooks\pre-commit.ps1'
#!/usr/bin/env pwsh
Process {
Write-Information -MessageData "I Ran" -InformationAction Continue
}
Begin {
Write-Information -MessageData "Beginning" -InformationAction Continue
}
End {
Write-Information -MessageData "Ending" -InformationAction Continue
Exit 0
}
我还应该提到,我在所有存储库中共享一个钩子副本。 我的存储库都位于R:\Git中,我创建了R:\Git \Hooks并全局使用 https://git-scm.com/docs/githooks 将 git config core.hooksPath = R:\ Git \ Hooks 配置为全局。 生活不错。
Kim Ki Won
上面的答案对我没有用,但因为它有赞,所以我会认为它对一些人有效。
对我有用的是删除bin/sh,而不是使用-File执行,直接执行命令:
c:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -ExecutionPolicy RemoteSigned -Command .\.git\hooks\pre-commit.ps1
#!/usr/bin/env powershell
Git会执行pre-commit文件,解析PowerShell解释器指令并启动PowerShell,将pre-commit文件的路径传递给它。 PowerShell会认为传递的文件应该具有“.ps1”扩展名。 它将搜索pre-commit.ps1文件,并且由于您创建了该名称和扩展名的文件,因此PowerShell将找到它并运行它。
这种方法简单明了,但最终我决定放弃它,因为它似乎有点“神奇”,可能会让维护者对其工作方式感到困惑。
我一直在寻找这个内容,最后找到了以下信息:
Git Powershell 预提交挂钩 (源代码)
## Editor's note: Link is dead as of 2014-5-2. If you have a copy, please add it.
PowerShell 中用于 git pre-commit 的 PHP 语法检查 (源代码)
##############################################################################
#
# PHP Syntax Check for Git pre-commit hook for Windows PowerShell
#
# Author: Vojtech Kusy <wojtha@gmail.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:\Program Files (x86)\Zend\ZendServer\bin\php.exe";
# Extensions of the PHP files
$php_ext = "php|engine|theme|install|inc|module|test"
# Flag, if set to 1 git will unstage all files with errors, se 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"
git diff-index --name-only --cached HEAD -- | foreach {
if ($_ -match ".*\.($extensions)$") {
$file = $matches[0];
$errors = & $php_bin -l $file
if ($errors -match "No syntax errors detected in $file") {
write-host $file ": OK" -foregroundcolor "green"
}
else {
write-host $file ":" $errors -foregroundcolor "red"
if ($reset) {
git reset -q HEAD $file
write-host "Unstaging" $file "..." -foregroundcolor "magenta"
}
$err_counter++
}
}
}
if ($err_counter -gt 0) {
exit 1
}
}
### MAIN ###
php_syntax_check $php_exe $php_ext $unstage_on_error
#!/bin/sh
c:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -ExecutionPolicy Bypass -Command '.\post-update.ps1'
在项目根目录中(即您最初运行git init的位置)的PowerShell脚本。 PowerShell转到另一个存储库并调用pull,更新该存储库。
post-update.ps1
Set-Location "E:\Websites\my_site_test"
$env:GIT_DIR = 'E:\Websites\my_site_test\.git';
$env:GIT_EXEC_PATH= 'C:\Program Files (x86)\Git/libexec/git-core';
git pull
以上许多答案都是多年前的,现在有更简单、更好的选择。
在 Windows PowerShell 时代,无法使用 #! /usr/bin/env powershell
,因为它不接受没有扩展名的文件。
解决方法是在同名目录下创建扩展名为 .ps1
的脚本文件,这也被提到在其他人的答案中。但这利用了可能未记录的内部实现,可能会出现意外问题。
然而,在 pwsh 时代,运行没有扩展名的脚本文件已经得到支持以实现跨平台兼容性。即使在 Windows 平台上,只需添加 #! /usr/bin/env pwsh
,就可以直接在此文件中编写脚本,无需任何其他额外操作。
我没有成功实现Simon的答案,可能是因为我的路径中的其他内容没有被Windows Git环境正确解析,或者是因为使用了Bonobo Git服务器。
我的目标是为在Bonobo托管的存储库编写一个pre-receive hook。
最终我得到了以下的shebang:
#!/c/Windows/System32/WindowsPowerShell/v1.0/powershell
否则的话,功能是相同的:
在我的情况下,为了保持整洁,我也使用了以下方法:
mklink <path-to-repo>\hooks\pre-receive.ps1 c:\scripts\hooks\someLibraryScript.ps1
当然,这样我就可以把我的脚本保存在中央仓库中。
编辑:值得注意的是,我没有成功让 Powershell 接受 pre-receive 钩子的 stdin 流。因此,我仍然使用 shell 脚本来引导 powershell 和管道,而不是重定向stdin到powershell。
在这种情况下,我使用以下 shell 脚本作为我的 pre-receive 钩子:
#!/bin/sh
IFS=
echo `cat -` | powershell.exe -NoProfile -ExecutionPolicy Bypass -File "c:\scripts\hooks\pre-receive.ps1"
Powershell 对此似乎很满意。
githooks
manpage. 我不知道Windows版本是否提供了不同的文档。 - intuitedpowershell -file someScript.ps1 args
调用它。 - Joey