【问题标题】:Git pre-commit hook is not running on WindowsGit 预提交挂钩未在 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 上。

【问题讨论】:

标签: windows git version-control githooks


【解决方案1】:

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

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

【讨论】:

  • 感谢您的建议。刚刚尝试过,现在当我尝试提交时出现错误:“错误:无法生成 .git/hooks/pre-commit:没有这样的文件或目录”。
  • 已编辑以添加第二条建议(在 stackoverflow.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 存储库的初始化,无需任何修改即可运行。

默认行为示例

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

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

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

    文件名很重要

  4. 将内容替换为以下shell脚本

    #!/bin/sh
    
    echo "Hello, World!"
    
    
  5. 导航回项目的根目录并使用命令echo "something" > text.txt创建一个名为test.txt的文件

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

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

  8. 验证输出如下所示

    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”的文件一定有一些问题(编码或结束行符号仍不清楚)。

        【讨论】:

          猜你喜欢
          • 2021-09-10
          • 1970-01-01
          • 2018-09-29
          • 1970-01-01
          • 2019-12-25
          • 1970-01-01
          • 1970-01-01
          • 2011-07-02
          • 1970-01-01
          相关资源
          最近更新 更多