git推送后本地执行钩子? (推后)

问题描述 投票:0回答:8

我已经查看了 githooks 手册页,但除非我遗漏了一些东西,否则我看不到本地、后推 git hooks 的选项。我希望有一个可以在我将 master 分支推送到 GitHub 存储库后更新我的 Web 服务器上的 api 文档(我已经有一个脚本)。当然,我可以编写自己的脚本,结合 git Push 和 api 文档运行,但这感觉有点不优雅。

git githooks
8个回答
56
投票

此问题的另一个解决方案是为

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


39
投票

我最近遇到了同样的问题。我想要一个钩子,以便来自 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 将被执行。


36
投票

Git 不支持这种类型的钩子。它不属于 Git hook 的有效理由 正如 Git 维护者所给出的。

上面链接消息中的介绍性评论几乎直接针对您的案例:

我不太喜欢那些钩子 操作启动后执行 本地并仅根据本地数据进行操作。 这可能是因为我仍然考虑 git 工具构建块适用于 比其他脚本编写更多的高级脚本 人们这样做。

附注“单击”提示

  • 有太多的警告无法完整解释,但如果你能弄清楚全部,你应该能够处理细节。

具有“备用”对象存储的本地存储库的额外

pushurl
可以为您提供一种低开销的方式来本地执行推钩。但实际上,付出的努力远不止
git push upstream && update-web-server
(可能在 shell 别名、git 别名或脚本中)。


6
投票

从 Git 1.8.2 开始,在推送操作之前调用了一个新的钩子:pre-push如果脚本返回非 0,推送操作将被取消。

在发行说明中提及:https://github.com/git/git/blob/master/Documentation/RelNotes/1.8.2.txt#L167

示例:https://github.com/git/git/blob/87c86dd14abe8db7d00b0df5661ef8cf147a72a3/templates/hooks--pre-push.sample


6
投票

实际上可以通过使用

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


3
投票

我正在为此使用一个函数:

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。


1
投票

只需创建一个顶部有 sleep 的

pre-push
钩子即可。确保睡眠时间足够长,以便根据您的网络连接速度将提交上传到上游服务器。理想情况下添加一个
&
以在后台运行脚本:

(sleep 30 && .git/hooks/post-push) &

0
投票

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
© www.soinside.com 2019 - 2024. All rights reserved.