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

Posted

技术标签:

【中文标题】如何在预提交挂钩中使用 git diff 的退出代码【英文标题】:How to use exit code of git diff in pre-commit hook 【发布时间】:2021-12-05 11:15:38 【问题描述】:

我有一个带有后端和前端的项目,但是由于每次更改都会执行 git pre-commit 挂钩,因此我需要检查更改是否在前端进行。

我尝试了这个预提交挂钩:

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

git diff --cached --name-only --quiet frontend
if [ $? -eq 1 ]; then
  cd frontend && npm run lint
fi

但由于某种原因,它在运行 git 命令时失败了——这在我的终端中运行良好。我得到的错误是:

husky - pre-commit 钩子以代码 1 退出(错误)

这并没有真正的帮助。我的猜测是 git 命令返回一个错误代码,脚本就这样结束了。

知道如何解决这个问题吗?

【问题讨论】:

git diff 将在有更改时返回 1。 [ 也将有一个退出代码(它需要,否则 if 无法检查退出代码)。你总是想用代码 0 退出你的脚本吗?如果是这样,true 作为最后一个命令可能会有所帮助。 @knittl 感谢您的回答,但您能提示一下您的意思吗?我对shell脚本一无所知。我要做的就是运行 git diff 并检查其返回值是否为 1。如果是,请运行 lint 命令。但是如何防止 git 将其返回到 shell 并保存以进行比较? 如果您需要脚本始终成功退出,true 作为最后一个命令可能会这样做。 (我已经在我的第一条评论中写过这个;))。说明:true 总是成功退出。 shell 脚本退出时使用与最后执行的命令相同的代码(或使用exit 指定的代码)。所以实际上,exit 0 可能比true 更明确:) 我的问题是我不知道语法。我不知道在哪里把“真实”放在哪里。 【参考方案1】:

shell 脚本总是以最后执行的命令的退出代码或使用 exit 内置命令指定的代码退出。

如果您需要脚本始终以特定的退出代码退出(例如,始终成功,0),请确保您明确指定退出代码:

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

git diff --cached --name-only --quiet frontend
if [ $? -eq 1 ]; then
  cd frontend && npm run lint
fi

exit 0

【讨论】:

但是我又想知道:这种预提交挂钩的目的是什么?如果 linting 失败,它仍然会成功退出,因此没有任何价值。还是npm run lint 实际格式化/更改文件? 谢谢。我真的很困惑,因为它看起来永远不会到达终点。我们在同一个存储库中有一个后端和前端,但提交挂钩属于存储库。如果后端开发没有在前端文件夹中安装 npm 依赖项,则它们的构建将失败。我想阻止这种情况。仅当前端文件夹发生更改时,linter 才必须运行。 @ctwx: 那么你想要脚本以npm run lint的退出状态退出如果你正在运行npm run lint。否则,您希望脚本以状态 0 退出。因此,明确的、始终到达的 exit 0 是错误的。我可能会把它写成if ! git diff-index --cached --quiet HEAD -- frontend; then cd frontend && npm run lint; fi,这应该可以实现。

以上是关于如何在预提交挂钩中使用 git diff 的退出代码的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Windows 上的 Git Bash 中退出“git diff”的结果? [复制]

如何提交两个分支的“git diff”?

gitlog和diff区别

SVN - 在开始提交挂钩中获取提交大小?

如何在 2 次提交之间创建一个 git diff/diff-tree/archive 与此时的文件版本(不是头)

Git挂钩