[英]git post commit hook - server side
我需要運行一個提交后的git服務器端鈎子,該鈎子應該檢查是否有合並,如果有合並則進行一些自動化。
我嘗試使用git reflog -1
,它很好用,但僅在客戶端。
我還嘗試實現了合並后掛鈎,但是沒有用。
當我在服務器端運行git reflog -1
時,沒有任何輸出。
有什么想法我可以做到這一點嗎?
ElpieKay的評論是答案的關鍵,但是值得更多細節。 由於服務器實際上並未運行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
給定C..H
(以及它們的哈希ID)的git rev-list
將以某種順序列出H
, D
, G
和F
H
的哈希將首先出現,但是之后的一切取決於您提供給git rev-list
任何排序選項。 如果對您的代碼的工作方式很重要,請使用--topo-order
來確保您獲得拓撲排序(例如,您可能希望--reverse --topo-sort
以便始終向前工作,獲取D, F, G, H
或F, G, D, H
作為輸入)。
請注意,如果您確實使用兼容POSIX的sh
來實現您的鈎子,則git rev-list ... | while read ...
會讓您感到煩惱git rev-list ... | while read ...
git rev-list ... | while read ...
: while
循環在子shell中運行,這意味着當循環退出時,此處設置的所有變量都會丟失。 您可以通過以下幾種方法來解決: 請參閱Bash中的While循環子外殼難題 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.