Git 预提交挂钩未在 Windows 上运行

Posted

技术标签:

【中文标题】Git 预提交挂钩未在 Windows 上运行【英文标题】:Git pre-commit hook is not running on Windows 【发布时间】:2014-01-03 18:41:09 【问题描述】:

我刚刚开始研究 Git 挂钩,但我似乎无法让它们运行。

我设置了一个本地存储库,所以我的项目文件夹中现在有一个“.git”目录。我在名为“pre-commit.cmd”的 C:/path/to/my/project/.git/hooks 目录中添加了一个“.cmd”文件。这是这个文件的内容:

echo "HOOK RUNNING"
echo. 2>C:/path/to/my/project/.git/hooks/EmptyFile.txt

这应该回显文本“HOOK RUNNING”并在该目录中创建一个空文本文件。但是,如果我通过我的 IDE (NetBeans) 提交更改或使用 Git Bash 提交,它们似乎都没有运行我的预提交挂钩,因为没有创建文件。

我的理解是,要让钩子运行,您所要做的就是添加一个带有钩子名称的可执行文件(正如我所做的那样)。我做错了吗?

注意:这是在 Windows 7 PC 上。

【问题讨论】:

相关(部分答案的主题):Why is my Git pre-commit hook not executable by default? 【参考方案1】:

将你的钩子命名为pre-commit(不带任何文件扩展名)。

并在第一行添加#!/bin/sh#!/bin/bash

【讨论】:

感谢您的建议。刚刚尝试过,现在当我尝试提交时出现错误:“错误:无法生成 .git/hooks/pre-commit:没有这样的文件或目录”。 已编辑以添加第二条建议(在 ***.com/questions/5697210/… 中找到)。如果不是这样,我也无能为力了,我对 windows shell 问题不是很熟悉 就是这样!你的第二个建议使它起作用。不知道为什么它不能只是一个普通的 Windows '.bat' 或 '.cmd' 文件...... 试试chmod +x pre-commit 我必须使用 #!/bin/bash 而不是 #!/bin/sh 才能在 Windows 下运行它。【参考方案2】:

您可能没有运行pre-commit 文件的权限

在终端中运行:

chmod +x .git/hooks/pre-commit

感谢@vaughan 提出这个想法

【讨论】:

也是一个钩子无法运行的正当理由:D,在我的情况下是真的,谢谢 这让我发疯并解决了我的问题。谢谢! @DaneMacaulay 你能告诉我在哪里写这个吗? 确实,我的回答不清楚,你需要在终端运行,我编辑了我的答案 在运行该命令之前,您需要进入项目所在的目录【参考方案3】:

TL;DR

默认情况下,Git 挂钩 work 在 Git for Windows 上,假设 Git 挂钩 脚本很简单

Git 和 Windows 的背景

请注意:Git 是为 shell interpretation 制作的;因此,在 Windows 命令提示符或 Windows 制造的 PowerShell 上使用 Git 钩子本来就有缺陷,并且无法预期完整的 interoperability。

在 Windows 上使用 Git 挂钩是可能的,但它有很多缺点。

Git for Windows 使用了一个 shell 模拟器,使 Bash 和 shell 命令成为可能。这意味着当 Git 激活 Git 挂钩时,Windows 版本将使用 shell 模拟器运行命令。反过来,这会将这些 shell 命令转换为 Windows 操作系统可以理解的命令。这意味着,简单的 shell 脚本可以立即运行。例如,Git 钩子 pre-commit 附带一个 Git 存储库的初始化,无需任何修改即可运行。

默认行为示例

    使用命令git init初始化一个Git仓库

    使用命令 cd .git\hooks 导航到 Git hooks 目录

    此目录包含所有 Git 挂钩脚本。创建一个名为pre-commit 的文件。注意:

    文件名很重要

    将内容替换为以下shell脚本

    #!/bin/sh
    
    echo "Hello, World!"
    
    

    导航回项目的根目录并使用命令echo "something" > text.txt创建一个名为test.txt的文件

    使用命令 git add test.txt 暂存文件以提交

    提交更改并使用命令git commit -m "test commit"观察预提交挂钩激活

    验证输出如下所示

    git commit -m "test commit"
    Hello, World!
    [master f00ccea] test commit
    

不良行为示例

当使用非常高级的 shell 脚本在 Git 挂钩中执行操作时,Windows shell 解释并不总是叠加。例如,当使用 NPM 的 Husky Git 挂钩插件以及 Prettier 格式化程序时,命令不会映射 1-1。这意味着您的预提交 Git 挂钩将在 Windows 上失败。

回复user1578653's question

Git 钩子是一个可执行脚本;但是,您使用的是命令提示符脚本 (.cmd) 而不是 shell 脚本 (.sh)。如果您想要在 Windows 操作系统上描述的这种行为,则创建名为 pre-commit 的文件并将其放置在 .git\hooks 目录中(相对于您正在处理的项目)。然后将以下内容放入该文件中。

.git\hooks\pre-commit

#!/bin/sh

echo "HOOK RUNNING"
thisCausesError 2> .git/hooks/EmptyFile.txt

您会注意到 Git 挂钩起作用并将单词 HOOK RUNNING 输出到控制台,thisCauseError 将向标准错误打印一条错误消息,该错误消息将打印到文件 EmptyFile.txt

【讨论】:

【参考方案4】:

就我而言,我将core.hooksPath 设置为错误的目录。

git config --global core.hooksPath '~/.githooks' 重置它解决了这个问题:)

【讨论】:

我为 Cygwin 启用了钩子,方法是将它们放入子目录 ./hooks 并使用 cd .git; ln -sf ../hooks hooks 使它们对 git 可见。因此,git 钩子在 Cygwin 的 git 中执行,但不是在 Emacs M-x shell-command 或其他使用 cmdproxycmd 的地方,包括 git gui。找到这个答案后,使用git config core.hookspath hooks 解决了这个问题,它独立于 git 是从 cmd 还是 Cygwin 的 bash 中调用的。 非常感谢..我有error: cannot spawn .git/hooks/pre-commit: no such file or directory 这个解决方案对我有用.. 它对我有用。【参考方案5】:

对我来说,我尝试运行 .bat 文件。

我发现反斜杠需要转义

例如:

#!/bin/bash
C:\\somefolder\\somefile.bat

【讨论】:

【参考方案6】:

在我的情况下,我做了npm install 并意外删除了 .git 文件夹,npm install pre-commit --save 起作用了。

【讨论】:

【参考方案7】:

对我来说,以前的解决方案都不起作用。我将预提交文件从挂钩移动到其他位置,有效地从挂钩中删除了文件。

这对我有用:D

【讨论】:

是的,删除 hooks 目录中的 pre-commit 文件是可行的 这只是意味着你把 git 钩子拿出来了,并没有修复钩子。【参考方案8】:

如果对任何人有帮助:

我收到以下错误:

错误:无法生成 .git/hooks/pre-commit:没有错误

事实证明,在我的预提交文件中,我在最后一个退出命令之后没有“换行符”:

#!/bin/sh
# From gist at https://gist.github.com/chadmaughan/5889802

# Stash any unstaged changes
git stash -q --keep-index

# Run the tests with the Gradle wrapper
./gradlew test --daemon

# Store the last exit code in a variable
RESULT=$?

# Unstash the unstashed changes
git stash pop -q

# Return the './gradlew test' exit code
exit $RESULT
# << must have a newline after the above command >>

我在 Windows 上运行 Gradle 项目,并在 Cmder shell 和 cmd 中运行 Gradle 命令。

【讨论】:

非常不幸的是,许多系统会默默地(自动地)删除文件末尾的“换行符”,即使它不是空行(例如:Arduino IDE)。同时,许多编译器无法处理文件末尾缺少的换行符。一种解决方法是在文件末尾添加某种注释。【参考方案9】:

我尝试了其他答案中建议的解决方案,但对解决此问题没有帮助:

无法生成 .git/hooks/pre-commit:没有这样的文件或目录

对我有用的解决方案是将文件 .git/pre-commit.sample 重命名为 .git/pre-commit 并插入脚本以使用 Prettier 格式化更改的文件。我手动创建的名为“pre-commit”的文件一定有一些问题(编码或结束行符号仍不清楚)。

【讨论】:

以上是关于Git 预提交挂钩未在 Windows 上运行的主要内容,如果未能解决你的问题,请参考以下文章

Git 预提交挂钩:更改/添加的文件

Git 预提交挂钩以在文件中查找文本

如何在预提交挂钩中使用 git diff 的退出代码

哈士奇预提交挂钩未触发

text Git预提交挂钩(.git / hooks / pre-commit)以防止意外提交调试代码(在源注释中添加NOCOMMIT)

预提交/挂钩:没有这样的文件或目录