将 PowerShell 脚本作为 git hook 运行

发布于 2024-10-31 16:29:16 字数 155 浏览 5 评论 0原文

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

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

Is it possible to run PowerShell scripts as git hooks?

I am running git in a PowerShell prompt, which shouldn't make any difference, but I can't seem to get them to work, as the hooks are named without extensions, and PowerShell needs (AFAIK) the .ps1 extension. I am not sure if that is the issue, or something else.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

冷情 2024-11-07 16:29:16

powershell 7.2 起,脚本必须具有 .ps1 扩展名视窗。所以这个答案不会起作用。


您可以将 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

此示例需要 PowerShell Core,但因此它将跨平台运行(假设此文件已在 Linux/macOS 上 chmod +x )。

) { 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 <[email protected]>' to set it correctly." exit 1 } exit 0

此示例需要 PowerShell Core,但因此它将跨平台运行(假设此文件已在 Linux/macOS 上 chmod +x )。

Since powershell 7.2 the script must have .ps1 extension on Windows. So this answer will not work.


You can embed PowerShell script directly inside the hook file. Here is an example of a pre-commit hook I've used:

#!/usr/bin/env pwsh

# Verify user's Git config has appropriate email address
if ($env:GIT_AUTHOR_EMAIL -notmatch '@(non\.)?acme\.com

This example requires PowerShell Core but as a result it will run cross-platform (assuming this file has been chmod +x on Linux/macOS).

) { 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 <[email protected]>' to set it correctly." exit 1 } exit 0

This example requires PowerShell Core but as a result it will run cross-platform (assuming this file has been chmod +x on Linux/macOS).

遥远的绿洲 2024-11-07 16:29:16

将 pre-commit.sample 重命名为 hooks 文件夹中的预提交。
然后在同一文件夹中制作 pre-commit.ps1 powershell 脚本文件。

#!/bin/sh
c:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -ExecutionPolicy RemoteSigned -File '.git\hooks\pre-commit.ps1'

Rename pre-commit.sample to pre-commit in hooks folder.
Then make pre-commit.ps1 powershell script file in same folder.

#!/bin/sh
c:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -ExecutionPolicy RemoteSigned -File '.git\hooks\pre-commit.ps1'
清引 2024-11-07 16:29:16

Kim Ki Won 的上述答案对我来说不起作用,但它得到了赞成票,所以我假设它对某些人有用。

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

c:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -ExecutionPolicy RemoteSigned -Command .\.git\hooks\pre-commit.ps1

Kim Ki Won's answer above didn't work for me, but it has upvotes so I'll assume it works for some people.

What worked for me was dropping the bin/sh and instead of executing using -File, executing the command directly:

c:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -ExecutionPolicy RemoteSigned -Command .\.git\hooks\pre-commit.ps1
儭儭莪哋寶赑 2024-11-07 16:29:16

这是一个起始 PWSH 脚本,自从阅读 Keith Hill 的回答以来,我一直将其用于我的 PowerShell Git Hooks。很不错。

#!/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 。生活是美好的。

Here's a starting PWSH script that I've been using for my PowerShell Git Hooks since reading Keith Hill's answer. Very nice.

#!/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
}

I should also mention I share a single copy of hooks across all my repos. My repos all live in R:\Git and I created R:\Git\Hooks and used https://git-scm.com/docs/githooks to git config core.hooksPath=R:\Git\Hooks globally. Life is good.

内心激荡 2024-11-07 16:29:16

为了完整起见:

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

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

#!/usr/bin/env powershell

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

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

For the sake of completeness:

If you only have Windows PowerShell and not PowerShell Core installed then Keith Hill's neat answer doesn't work. The various answers that use a bash script to run PowerShell, passing in the path to the PowerShell script to run, are straight-forward and the way I chose to go in the end. However, I discovered there is another way:

Create two files for the git hook, say pre-commit and pre-commit.ps1. The pre-commit.ps1 file is the file that PowerShell will run. The other pre-commit file (without a file extension) is empty apart from a PowerShell interpreter directive on the first line:

#!/usr/bin/env powershell

Git will run the pre-commit file, parse the PowerShell interpreter directive and run up PowerShell, passing in the path to the pre-commit file. PowerShell will assume the file passed in should have a ".ps1" extension. It will search for pre-commit.ps1 and, since you created a file with that name and extension, PowerShell will find it and run it.

This approach is nice and simple but, in the end, I decided against it because it seemed a little "magical" and might have maintainers scratching their heads about how it works.

ヅ她的身影、若隐若现 2024-11-07 16:29:16

据我所知,由于 Git 的设计,唯一的选择是调用 PowerShell 的 bash 脚本。不幸的是,Git 并没有考虑到非 Linux 兼容性。

From what I gather the only option due to Git's design here would be a bash script calling PowerShell. Unfortunate, but then again, Git didn't place any thought on non-Linux compatibility.

§普罗旺斯的薰衣草 2024-11-07 16:29:16

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

Git Powershell pre-commit hook (来源)

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

PowerShell 中 git 预提交的 PHP 语法检查 (Soure< /a>)

##############################################################################
#
# PHP Syntax Check for Git pre-commit hook for Windows PowerShell
#
# Author: Vojtech Kusy <[email protected]>
#
###############################################################################

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

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

I have been looking for this myself, and i found the following:

Git Powershell pre-commit hook (Source)

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

PHP Syntax check for git pre-commit in PowerShell (Soure)

##############################################################################
#
# PHP Syntax Check for Git pre-commit hook for Windows PowerShell
#
# Author: Vojtech Kusy <[email protected]>
#
###############################################################################

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

The code is for a pre-commit hook, but you could modify it to do pretty much anything. Should help what you need to do!

兔姬 2024-11-07 16:29:16

这是我在 Windows 上的 git hook,位于 .\git\hooks。

更新后

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

Powershell 脚本位于项目根文件夹(您最初运行 git init 的位置)。 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

This is my git hook on Windows located in .\git\hooks.

post-update

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

Powershell script located in the project root folder (where you initially run git init). Powershell goes to another repository and calls pull, updating that repository.

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
日暮斜阳 2024-11-07 16:29:16

新时代更好的 pwsh 解决方案

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

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

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

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

Better solutions for pwsh in the new era

Many of the answers above are many years old, and there are now simpler and better options.

In the days of Windows PowerShell, it was not possible to use #! /usr/bin/env powershell, because it did not accept files without extensions.

The workaround was to create script files in the directory with the same name but with the extension .ps1, which was mentioned in someone else's answer. But this takes advantage of a possible undocumented internal implementation, and unexpected problems may occur.

However, in the pwsh era, running script files without extensions has been supported for cross-platform compatibility. Even on windows platforms, it is only necessary to add #! /usr/bin/env pwsh, you can write scripts directly in this file without any other additional actions.

旧故 2024-11-07 16:29:16

我没有得到西蒙的答案,可能是因为我的路径中的其他东西没有被 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 和管道,而不是将 stdin 重定向到 powershell。

在本例中,我使用以下 shell 脚本作为我的预接收挂钩:

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

Powershell 似乎对此感到满意。

I didn't get Simon's answer to work, potentially because of other things in my path not being parsed properly by the windows git environment and/or using bonobo git server.

My objective was writing a pre-receive hook for a repository hosted in bonobo.

I ended up with the following shebang:

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

Otherwise works identically:

  • Create pre-receive file with only shebang
  • Create pre-receive.ps1 in hooks directory. Powershell loads this instead.

In my case, for some cleanliness, i also used

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

This allows me to keep my scripts in a central repository, of course.

EDIT: It's worth noting i did not manage to get Powershell to accept the stdin stream for the pre-receive hook. As a result, i'm still using a shell script to bootstrap powershell and pipe, rather than redirect, stdin to powershell.

In this case, i used the following shell script for my pre-receive hook:

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

Powershell seems satisfied with that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文