43

是否可以将 PowerShell 脚本作为 git 挂钩运行?

我在 PowerShell 提示符下运行 git,这应该没有任何区别,但我似乎无法让它们工作,因为挂钩的命名没有扩展名,并且 PowerShell 需要(AFAIK).ps1 扩展名。我不确定这是问题所在,还是其他问题。

4

10 回答 10

44

您可以将 PowerShell 脚本直接嵌入到挂钩文件中。pre-commit这是我使用的钩子的示例:

#!/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)。

于 2018-07-08T16:03:37.867 回答
28

在 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'
于 2014-04-24T02:00:35.933 回答
9

由于 Git 的设计,我收集到的唯一选择是调用 PowerShell 的 bash 脚本。不幸的是,但话又说回来,Git 并没有考虑到非 Linux 的兼容性。

于 2011-04-12T05:42:08.623 回答
8

Kim Ki Won上面的答案对我不起作用,但它有赞成票,所以我认为它适用于某些人。

对我有用的是删除 bin/sh 而不是使用 -File 执行,而是直接执行命令:

c:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -ExecutionPolicy RemoteSigned -Command .\.git\hooks\pre-commit.ps1
于 2016-09-30T16:30:20.847 回答
7

这是我在PowerShell Git Hooks阅读 Keith Hill 的回答后一直在使用的起始 PWSH 脚本。非常好。

#!/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生活很好。

于 2018-10-27T06:17:52.290 回答
6

为了完整起见:

如果您只安装了 Windows PowerShell 而没有安装 PowerShell Core,那么 Keith Hill 的简洁答案将不起作用。使用 bash 脚本运行 PowerShell、传递要运行的 PowerShell 脚本的路径的各种答案都是直截了当的,也是我最终选择的方式。但是,我发现还有另一种方法:

为 git 钩子创建两个文件,比如 pre-commit 和 pre-commit.ps1。pre-commit.ps1 文件是 PowerShell 将运行的文件。除了第一行的 PowerShell 解释器指令外,另一个预提交文件(没有文件扩展名)是空的:

#!/usr/bin/env powershell

Git 将运行预提交文件,解析 PowerShell 解释器指令并运行 PowerShell,并传入预提交文件的路径。PowerShell 将假定传入的文件应具有“.ps1”扩展名。它将搜索 pre-commit.ps1,并且由于您创建了具有该名称和扩展名的文件,PowerShell 将找到并运行它。

这种方法既好又简单,但最后我决定反对它,因为它看起来有点“神奇”,并且可能会让维护者对它的工作原理摸不着头脑。

于 2019-05-18T14:28:16.987 回答
5

我自己一直在寻找这个,我发现了以下内容:

Git Powershell 预提交钩子来源

## Editor's note: Link is dead as of 2014-5-2.  If you have a copy, please add it.

PowerShell 中 git 预提交的 PHP 语法检查Soure

##############################################################################
#
# 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

该代码用于预提交挂钩,但您可以对其进行修改以执行几乎任何操作。应该帮助你需要做的事情!

于 2011-10-04T08:24:11.823 回答
3

这是我在 Windows 上的 git 钩子,位于 .\git\hooks 中。

更新后

#!/bin/sh
c:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -ExecutionPolicy Bypass -Command '.\post-update.ps1'

位于项目根文件夹(最初运行 git init 的位置)中的 Powershell 脚本。Powershell 转到另一个存储库并调用 pull,更新该存储库。

更新后.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
于 2018-02-09T12:58:37.450 回答
0

我没有得到西蒙的回答,可能是因为我的路径中的其他东西没有被 windows git 环境和/或使用 bonobo git 服务器正确解析。

我的目标是为托管在 bonobo 中的存储库编写一个预接收挂钩。

我最终得到了以下shebang:

#!/c/Windows/System32/WindowsPowerShell/v1.0/powershell

否则工作方式相同:

  • 仅使用 shebang 创建预接收文件
  • 在 hooks 目录中创建 pre-receive.ps1。Powershell 会加载它。

就我而言,为了保持清洁,我也使用了

mklink <path-to-repo>\hooks\pre-receive.ps1 c:\scripts\hooks\someLibraryScript.ps1

当然,这允许我将脚本保存在中央存储库中。

编辑:值得注意的是,我没有设法让 Powershell 接受预接收挂钩的标准输入流。结果,我仍在使用 shell 脚本来引导 powershell 和管道,而不是将标准输入重定向到 powershell。

在这种情况下,我为我的预接收挂钩使用了以下 shell 脚本:

#!/bin/sh
IFS=
echo `cat -` | powershell.exe -NoProfile -ExecutionPolicy Bypass -File "c:\scripts\hooks\pre-receive.ps1"

Powershell 似乎对此感到满意。

于 2020-07-29T14:31:22.890 回答
0

新时代pwsh更好的解决方案

上面的许多答案都有很多年了,现在有更简单更好的选择。

在 Windows PowerShell 时代,无法使用#! /usr/bin/env powershell,因为它不接受没有扩展名的文件。

解决方法是在目录中创建具有相同名称但扩展名为 的脚本文件.ps1,这在其他人的答案中有所提及。但这利用了可能未记录的内部实现,并且可能会出现意想不到的问题。

但是,在 pwsh 时代,为了跨平台兼容,已经支持运行不带扩展名的脚本文件。即使在windows平台上,只需要添加#! /usr/bin/env pwsh,就可以直接在该文件中编写脚本,无需任何其他额外操作。

于 2021-08-27T23:36:47.357 回答