簡體   English   中英

git post commit鈎子-服務器端

[英]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將以某種順序列出HDGF H的哈希將首先出現,但是之后的一切取決於您提供給git rev-list任何排序選項。 如果對您的代碼的工作方式很重要,請使用--topo-order來確保您獲得拓撲排序(例如,您可能希望--reverse --topo-sort以便始終向前工作,獲取D, F, G, HF, 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM