我需要运行一个提交后的git服务器端钩子,该钩子应该检查是否存在合并,如果存在合并则进行一些自动化。
我尝试使用const object = {
getPastEvents: () => Promise.resolve([1,2,3])
}
function* fetchPastEvents() {
console.log("entry")
const values = yield object.getPastEvents()
console.log(values)
}
const iterator = fetchPastEvents()
const promise = iterator.next().value;
promise.then(val => iterator.next(val))
,它很好用,但只在客户端使用。
我还尝试实现合并后挂钩,但这没用。
当我在服务器端运行git reflog -1
时,没有任何输出。
有什么想法可以实现这一目标吗?
答案 0 :(得分:2)
ElpieKay's comment是答案的关键,但是值得更多细节。由于服务器实际上并未运行git commit
,因此必须使用接收后挂钩监视参考更新。不幸的是,接收后钩子并不简单。这是一个通常有用的简单框架,以POSIX shell表示:
#! /bin/sh
# sample post-receive hook
# return true if the argument ($1) is the null hash (all-0s)
is_nullhash() {
expr "$1" : '0*$' >/dev/null
}
while read oldhash newhash ref; do
# If the old hash is all 0s, the reference was just created.
# If the new hash is all 0s, the reference was just deleted.
# Otherwise, the reference was updated, from $oldhash to $newhash.
if is_nullhash $oldhash; then
op=create
elif is_nullhash $newhash; then
op=delete
else
op=update
fi
# If the reference begins with refs/heads/, the rest of it is
# a branch name. If it starts with refs/tags, the rest is a tag.
# Otherwise it's some other type of reference (not decoded here).
case $ref in
refs/heads/*) reftype=branch; shortref=${ref#refs/heads/};;
refs/tags/*) reftype=tag; shortref=${ref#refs/tags/};;
*) reftype=other; shortref=$ref;; # NB: not shortened!
esac
... insert code here ...
done
“在此处插入代码”部分中的代码必须:
例如,如果您只想观看对master
的推送:
if [ $reftype = branch -a $shortref = master ]; then
if [ $op = update ]; then
handle_master_update $oldhash $newhash
else
... do something different if the op is create or delete ...
fi
fi
其中handle_master_update
是您处理master
更新的函数。如果您不想处理master
分支的创建和删除,则可以将其进一步简化为:
case $ref,$op in
refs/heads/master,update) handle_master_update $oldhash $newhash;;
esac
在这种情况下,您可以删除对引用类型进行解码的样板部分。
现在,我们进入更新处理的核心:
# Do something with update to master branch.
# The old hash is $1 and the new hash is $2,
# so commits in $1..$2 now appear on `master` but
# were not part of `master` before (they may have
# been on some other branch, and may still be).
# Meanwhile, commits in $2..$1 used to be on `master`
# but have just been removed via force-push. If this
# list is empty, the push did not have to be forced,
# and maybe was not.
handle_master_update() {
local rev parents
git rev-list $2..$1 | while read rev; do ...; done # deal with removed commits
git rev-list --parents $1..$2 | while read rev parents; do
...
done
}
第一部分(处理删除的提交)当然是可选的。第二部分是您要检测合并的部分,因此我们使用git rev-list
(而不是git log
,这里的rev-list是更有用的主力)来枚举所有添加的以及他们的父哈希ID 。 read
将所有父哈希放入变量parents
中,因此我们可以轻松地在...
部分中对其进行计数。例如:
set -- $parents
case $# in
0) ...;; # $rev is a root commit
1) ...;; # $rev is an ordinary commit
*) ...;; # $rev is a merge, its parents are $1, $2, ... through $#
esac
零号是非常不寻常的-要使其作为更新发生,我们必须向分支添加一个根提交,例如,从:
A--B--C <-- master
收件人:
A--B--C--D--H <-- master
/
F---------G
在给定git rev-list
的情况下,C..H
(它们的哈希ID)将列出H
,D
,G
和F
以某种顺序。 H
的哈希将首先出现,但之后的所有内容都取决于您提供给git rev-list
的任何排序选项。如果这对代码的工作方式很重要,请使用--topo-order
来确保您得到拓扑排序(例如,您可能希望--reverse --topo-sort
以便始终在 forward 上工作, D, F, G, H
或F, G, D, H
中的一个作为输入)。
请注意,如果您确实使用兼容POSIX的sh
来实现钩子,则git rev-list ... | while read ...
会带来麻烦:while
循环在子shell中运行,这意味着此处设置的任何变量退出循环时丢失。您可以通过以下几种方法来解决:参见While-loop subshell dilemma in Bash。