我已经查看了 githooks 手册页,但除非我遗漏了一些东西,否则我看不到本地、后推 git hooks 的选项。我希望有一个可以在我将 master 分支推送到 GitHub 存储库后更新我的 Web 服务器上的 api 文档(我已经有一个脚本)。当然,我可以编写自己的脚本,结合 git Push 和 api 文档运行,但这感觉有点不优雅。
此问题的另一个解决方案是为
git push
提供一个包装器,在 .git/hooks/pre-push
调用之前和之后执行 .git/hooks/post-push
和 git push
脚本。可能的包装可能如下所示:
#!/bin/sh
GIT_DIR_="$(git rev-parse --git-dir)"
BRANCH="$(git rev-parse --symbolic --abbrev-ref $(git symbolic-ref HEAD))"
PRE_PUSH="$GIT_DIR_/hooks/pre-push"
POST_PUSH="$GIT_DIR_/hooks/post-push"
test -x "$PRE_PUSH" &&
exec "$PRE_PUSH" "$BRANCH" "$@"
git push "$@"
test $? -eq 0 && test -x "$POST_PUSH" &&
exec "$POST_PUSH" "$BRANCH" "$@"
在
git-push-wh
中的某处保存为 PATH
,如果您想用钩子推送,则可以将其称为 git push-wh
。
我最近遇到了同样的问题。我想要一个钩子,以便来自 git 子模块的推送可以在“超级项目”中提交新的子模块引用。
正如 Chris 提到的,最好的方法是使用 git 别名,如下所示:
$ git config alias.xpush '!git push $1 $2 && update-server.sh'
# (remember the backslash before the ! if your shell requires it)
这会将以下内容添加到您的 .git/config 文件中:
[alias]
xpush = !git push $1 $2 && update-server.sh
现在,如果您输入:
$ git xpush
您的更改将被推送,然后 update-server.sh 将被执行。
Git 不支持这种类型的钩子。它不属于 Git hook 的有效理由 正如 Git 维护者所给出的。
上面链接消息中的介绍性评论几乎直接针对您的案例:
我不太喜欢那些钩子 操作启动后执行 本地并仅根据本地数据进行操作。 这可能是因为我仍然考虑 git 工具构建块适用于 比其他脚本编写更多的高级脚本 人们这样做。
具有“备用”对象存储的本地存储库的额外
pushurl
可以为您提供一种低开销的方式来本地执行推钩。但实际上,付出的努力远不止 git push upstream && update-web-server
(可能在 shell 别名、git 别名或脚本中)。
从 Git 1.8.2 开始,在推送操作之前调用了一个新的钩子:pre-push如果脚本返回非 0,推送操作将被取消。
在发行说明中提及:https://github.com/git/git/blob/master/Documentation/RelNotes/1.8.2.txt#L167
实际上可以通过使用
reference-transaction
钩子来实现后推钩子。推送完成后,git 将在本地更新远程跟踪分支,从而在 refs/remotes/REMOTE/BRANCH
上触发参考事务。
这是使用此技术的钩子示例:
#!/bin/bash
set -eu
while read oldvalue newvalue refname
do
if [ $1 = committed -a $refname = refs/remotes/origin/main ]
then
exec .git/hooks/post-push
fi
done
此脚本必须具有可执行位并放置在
.git/hooks/reference-transaction
中。钩子在将主分支推送到原点后运行。将您的实际挂钩脚本放入 .git/hooks/post-push
。
我正在为此使用一个函数:
current_branch() {
local ref=$(git symbolic-ref HEAD 2> /dev/null) || return
echo ${ref#refs/heads/}
}
gp() {
local post_push="$(git rev-parse --git-dir)/hooks/post-push"
git push "$@" && {
[[ -x "$post_push" ]] && "$post_push" "$(current_branch)" "$@"
}
}
compdef _git gp=git-push
compdef 部分适用于 ZSH。
只需创建一个顶部有 sleep 的
pre-push
钩子即可。确保睡眠时间足够长,以便根据您的网络连接速度将提交上传到上游服务器。理想情况下添加一个 &
以在后台运行脚本:
(sleep 30 && .git/hooks/post-push) &
incron
来救援。
我的
incrontab
有这个:
/path/to/.git/logs/refs/remotes/origin IN_CLOSE_WRITE /usr/local/bin/git-post-push $@/$#
该脚本检查远程是否通过推送进行更改,如果是,则使用 GNU grep 提取一些有用的内容:
# The script is called with a filename like /path/to/.git/logs/refs/remotes/origin/main
# Pushes in this file are recorded by a line containing the old hash, the new hash, the commit author,
# the push timestamp followed by the timezone and the text update by push (separated by tabs and spaces).
push=$(tail -1 "$1"| grep -oP '\d{10}(?=\s.{1,5}\supdate by push$)')
if [ -n "$push" ]; then
gitdir=$(echo "$1"|grep -oP '^.*/.git/')
remote=$(echo "$1"|grep -oP '.git/logs/refs/remotes/\K[^/]+')
branch=$(echo "$1"|grep -oP '.git/logs/refs/remotes/[^/]+/\K.*$')
fi