Git Pre-push 钩子不会在多次检查的情况下中止推送
Posted
技术标签:
【中文标题】Git Pre-push 钩子不会在多次检查的情况下中止推送【英文标题】:Git Pre-push hooks not aborting push in case of more than one checks 【发布时间】:2018-11-02 18:04:04 【问题描述】:在 git 钩子中 - 我想在推送之前检查 jshint 错误和纱线完整性检查,所以我在 pre-push 中添加了下面。 所以它是这样的 -
# Pre-push hooks
# Lint stuff before committing
grunt jshint eslint tslint
# Verifies that versions and hashed value of the package contents
in the project’s package.json matches that of yarn’s lock file.
yarn check --integrity
这里如果 jshint 给出错误但如果纱线完整性检查通过,仍然
它允许推动。如果纱线失败,它将中止。
如果我颠倒顺序然后如果纱线检查失败并且如果 jshint 通过,
然后它也会推动。如果 jshint 失败,它将中止。
因此只有在最后一次检查失败时才会推送失败,而在其他情况下它会声明错误但仍会推送它
【问题讨论】:
无耻插件,但您可以查看我的助手git-riff
,它允许您为钩子中的每个任务编写单独的脚本并为您处理这种情况。
【参考方案1】:
在这里自我宣传:如果你想很花哨,你可以使用我前段时间写的辅助函数(用于提交挂钩)。
你这样运行它:
set -e
run_check 'flake8' . flake8
run_check 'ESLint' . ./node_modules/eslint/bin/eslint.js frontend/js
exit_test
得到这样的输出:
flake8 OK
ESLint OK
或者如果你不太幸运:
./frontend/tests.py:8:83: E999 SyntaxError: invalid syntax
flake8 FAILED
/home/frax/Programowanie/organizer/organizer2/frontend/js/utils.js
11:18 error Parsing error: Unexpected token ;
✖ 1 problem (1 error, 0 warnings)
ESLint FAILED
Some check(s) failed.
exit_test
的退出码是上次检查失败的退出码。当使用set -e
时,它成为整个脚本的退出代码。
代码:
# Use run_check to run groups of independent tests, that should all be run even
# if some of them fail (but you still want to know about failure).
# testing_exit_code variable stores last non-zero exit code of the check, or 0,
# if no check failed so far.
# Important note: using trap prevents set -e from intercepting check failures,
# so it's safe (and recommended) to use -e in testing script.
# Example:
#
# run_check 'Foo check' . echo Foo
# run_check 'Bar check' . echo Bar
# exit_test # fail if any test failed
#
testing_exit_code=0
function run_check ()
# Usage: run_check <check name> <working directory> <command> [args...]
local cmd="$1"
trap 'testing_exit_code=$?; echo "$cmd FAILED"; return 0' ERR
local cmd_wd="$2"
shift 2
( cd "$cmd_wd" && "$@" ) # run the command
echo "$cmd OK"
function exit_test ()
if (( testing_exit_code != 0 )); then
echo "Some check(s) failed."
fi
exit $testing_exit_code
如果添加一些颜色,输出看起来会更好。实际上,我的原始脚本中有它们,但为了简洁和可移植性而省略了它们。如果您有兴趣,我可以单独分享带有颜色的版本。
【讨论】:
【参考方案2】:这真是一个关于编写脚本的问题。
在 sh/bash 脚本中,一系列命令只是运行这一系列命令:
cmd1
cmd2
cmd3
任何一个命令“失败”都没有关系(返回非零退出状态);脚本继续运行下一个。
脚本的最终退出状态是最后运行的命令的退出状态,除非您提供特定状态:
exit 0
(零表示成功)。
如果您希望在任何命令失败后立即退出,您可以设置-e
选项:
set -e
cmd1
cmd2
cmd3
这是相当粗略的,并不总是正确的做法。请注意,如果 cmd2
失败(退出非零),cmd3
甚至不会启动,但 shell 会以 cmd2
的失败退出状态退出。
为了特别花哨,可以保存每个命令的退出状态:
cmd1; cmd1_status=$?
cmd2; cmd2_status=$?
cmd3; cmd3_status=$?
$?
变量扩展为刚刚运行的命令的退出状态。
当然,现在你必须弄清楚如何处理这三个状态,因为你只能退出其中的一个,但你现在可以退出哪个先失败,如果有的话:
test $cmd1_status != 0 && exit $cmd1_status
test $cmd2_status != 0 && exit $cmd2_status
exit $cmd3_status
现在您的脚本无条件运行所有三个命令,但返回第一个非零失败的状态。如果 cmd1 和 cmd2 都返回零状态,则脚本以 cmd3 的状态退出。
【讨论】:
对于 2 cmnds,test cmd1_status != 0 && exit $cmd1_status test cmd2_status != 0 && exit $cmd2_status 即使最后一个命令失败,它仍然会推送 我上面有两个错别字,我会改正的。同时,如果不是这样,请显示确切的代码(可能剪切并粘贴到原始问题中;记得使用“格式即代码”*** 标记)。以上是关于Git Pre-push 钩子不会在多次检查的情况下中止推送的主要内容,如果未能解决你的问题,请参考以下文章
手写 git hooks 脚本(pre-commitcommit-msg)