ebo*_*osi 14 git git-push githooks
我想确保我推送的每个提交都通过测试。
我想在我的(客户端)端检查这一点,即在提交之前进行检查(所以我不想依赖 CI 工具)。
目前,我已经实现了一个pre-commit运行测试的钩子,因此我什至无法提交损坏的状态。
然而,我的测试套件运行需要花费几秒钟的时间。在编写提交消息之前我需要等待很多时间。这使得日常使用变得不切实际;两者都是因为我经常提交,而且我有时故意想要提交一个损坏的状态以供稍后粉碎(我知道git commit --no-verify,但这不是重点)。
因此,我不想一次(在创建时)检查每个提交,而是想在推送之前对它们进行批量测试。
如何实现一个钩子来为每个要推送的新提交pre-push运行我的测试套件?
(为了简单起见,假设通过测试意味着test/run_tests.sh返回0。)
感谢 的phd提示(在评论中)和对 git 自己示例的无耻掠夺,我起草了以下./.git/hooks/pre-push钩子(我事先注意到了chmod +x)。
它似乎在普通情况下完成了工作,我们将看看随着时间的推移它会如何进行。无论如何,欢迎改进!
#!/usr/bin/sh
# An example hook script to verify that each commit that is about to be pushed
# pass the `./run_tests` suite. Called by "git push" after it has checked the
# remote status, but before anything has been pushed.
# If the test suite (and so the script) exits with a non-zero status, nothing
# will be pushed.
#
# In any case, we revert to the pre `$ git push` state.
# Retrieve arguments
remote="$1"
url="$2"
z40=0000000000000000000000000000000000000000 # SHA of a non existing commit
# Save current "git state"
current_branch=$(git rev-parse --abbrev-ref HEAD)
STASH_NAME="pre-push-$(date +%s)"
git stash save -q --keep-index $STASH_NAME
# Do wonders
while read local_ref local_sha remote_ref remote_sha
do
if [ "$local_sha" = $z40 ]
then
# Handle delete
continue # to the next branch
elif [ "$remote_sha" = $z40 ]
then
# New branch, examine all commits
range="$local_sha"
else
# Update to existing branch, examine new commits
range="$remote_sha..$local_sha"
fi
# Retrieve list of commit in "chronological" order
commits=$(git rev-list --reverse $range)
# Loop over each commit
for commit in $commits
do
git checkout $commit
# Run the tests
./test/run_tests.sh
# Retrieve exit code
is_test_passed=$?
# Stop iterating if error
if [ $is_test_passed -ne 0 ]
then
echo -e "Aborting push: Test failed for commit $commit,"\
"with following error trace:\n"
# something like: tail test/run_tests.log
break 2
fi
done
done
# Revert to pre-push state
git checkout $current_branch
STASH_NUM=$(git stash list | grep $STASH_NAME | sed -re 's/stash@\{(.*)\}.*/\1/')
if [ -n "$STASH_NUM" ]
then
git stash pop -q stash@{$STASH_NUM}
fi
#removed fi
# Return exit code
exit $is_test_passed
Run Code Online (Sandbox Code Playgroud)