2010-08-18 78 views
26

我有'更新'鉤子的問題。在新分支的情況下,它將得到一個0000000000000000000000000000000000000000作爲'oldrev'。我不知道如何處理這種情況。Git接收/更新掛鉤和新分支

我們有這樣的要求,即每個提交消息引用一個有效的Jira問題。所以我在中央倉庫上安裝了一個「更新」鉤子。該鉤子獲得「oldrev」和「newrev」。然後我通過那些「混帳轉列表」是這樣的:

git rev-list $oldrev..$newrev

這給了我所有轉速下,我可以然後遍歷列表,並做我需要做的。

問題是,當用戶按下一個新的分支時,鉤子獲取0000000000000000000000000000000000000000作爲oldrev。和「混帳轉列表」簡單地抱怨:

fatal: Invalid revision range 0000000000000000000000000000000000000000..21bac83b2

那麼,如何讓所有的都在新的分支轉速的名單?我已經在網上查了很長一段時間了,什麼都沒發現。這個例子鉤,我發現無論是

  • 不處理這個問題,失敗,上面的錯誤消息
  • 錯誤地試圖通過設置OLDREV爲「」,它返回自啓錯誤的結果來解決問題-list
  • 乾脆放棄,當他們遇到的這些OLDREV

無聲音特別興奮。

那麼有人有任何想法如何得到正確的答案在這種情況下?我在考慮查詢git是否「給我所有可從newrev獲得的轉發,但不能從任何其他分支(=除新分支以外的所有分支)」。但即使如此,如果從新分支合併到任何舊分支,這也會給出錯誤的答案。

回答

14

在這種情況下,術語「正確答案」有點含糊不清。我實際上認爲,「所有可以從newrev到其他地方都可以轉到的地方」是完全正確的。即使存在合併,情況也是如此 - 在這種情況下,您應該看到對新引用和合並提交唯一的提交,而不是合併的提交。

所以,我要說,檢查「OLDREV」全爲零,如果是,採取相應的行動:

if [ "$oldrev" -eq 0 ]; then 
    # list everything reachable from newrev but not any heads 
    git rev-list $(git for-each-ref --format='%(refname)' refs/heads/* | sed 's/^/\^/') "$newrev" 
else 
    git rev-list "$oldrev..$newrev" 
fi 
+2

我不確定它是否與我的環境或git更新有些奇怪,但否定是刪除當前分支上的引用。我必須做這樣的事情:'git rev-list $(git for-each-ref --format ='%(refname)'「refs/heads/*」| grep -v'$ ref'| sed '/'/'^ /')「$ newrev」' – mmalone 2012-11-08 01:47:44

+1

爲了在'update'(和'pre-receive')鉤子中使用,如問題中所述,這些答案都更加複雜和昂貴。約瑟在下面的答案是最簡單和最有效的;這應該是IMO的選擇答案。 – MadScientist 2014-06-01 19:41:26

+0

@mmalone你是對的。我不得不添加「| grep -v'$ rev'」。否則,我總是得到empy結果 – dritan 2015-03-31 09:18:14

7

我只是理解了它自己。

git的日誌newref --not otherheads

是讓那些沒有任何其他分支的分支的所有日誌的關鍵。下面是我的python腳本來檢查提交消息的正確的最大行長度。

import sys 
import commands 

ref = sys.argv[1] 
old = sys.argv[2] 
new = sys.argv[3] 

x = 0 

# only a tag is pushed to server, nothing to check 
if ref.find('refs/tags/') >= 0: 
    if len(ref.strip('refs/tags/')) > 25: 
    print 'tag name is longer than 25 characters' 
    exit(1) 
    else: 
    exit(0) 
# either a new branch is pushed or an empty repo is being pushed 
if old == '0000000000000000000000000000000000000000': 
    heads = commands.getoutput("git for-each-ref --format='%(refname)' 'refs/heads/*'") 
    heads = heads.replace(ref+'\n','').replace('\n',' ') 
    hashes = commands.getoutput('git log '+new+' --pretty=%H --not '+heads).split('\n') 
else: 
    hashes = commands.getoutput('git log '+old+'..'+new+' --pretty=%H').split('\n') 

for hash in hashes: 
    subject = commands.getoutput('git show '+hash+' --format=%s --summary').split('\n') 
    body = commands.getoutput('git show '+hash+' --format=%b --summary').split('\n') 

    if len(subject[0]) > 75: 
    print 
    print 'commit: '+hash 
    print 'bad commit message(s): header line is too long or second line is not blank (max 75 chars)' 
    print 'bad line: "%s"' % subject[0] 
    print 'length of header line: %d' % len(subject[0]) 
    print 'try again with correct message format' 
    print 
    x = 1 

    for line in body: 
    if len(line) > 75: 
     print 
     print 'commit: '+hash 
     print 'bad commit message(s): description lines are too long (max 75 chars)' 
     print 'bad line: "%s"' % line 
     print 'length of line: %d' % len(line) 
     print 'try again with correct message format' 
     print 
     x = 1 

if x == 0: 
    exit(0) 
else: 
    exit(1) 
+0

在'for-each-ref'中使用'refs/heads/*'不是一個好主意。它不會匹配名稱中帶有斜槓的任何分支(例如'foo/bar')。你應該使用'refs/heads /'(否'''')。但是,請參閱下面Joseph的答案以獲得更簡單的選擇。 – MadScientist 2014-06-01 19:47:05

3

我使用解決了這個對我的更新掛鉤以下:

if [ "$oldrev" -eq 0 ]; then 
git log "$(git show-branch --merge-base)".."$newrev"; else 
foo; 
fi 
+0

如果你在鉤子裏面,這根本不起作用,特別是如果你的倉庫中有超過25個分支。 – MadScientist 2014-06-01 19:39:29

9

$oldrev都是零,不同的git rev-list命令做了所有你需要:

git rev-list $newrev --not --branches=* 

會給你從$newrev可到達但不是來自任何分支的修訂列表。

注意,這絕對不做同樣的事情,git rev-list $oldrev..$newrev時OLDREV是全部爲零,所以你要檢查你是這種情況,並選擇適當的命令來運行。

+1

儘管實際上它在預接收和更新hooks_時起作用,因爲當這些掛鉤運行時,新分支還沒有在那裏!太好了! – MadScientist 2014-06-01 19:35:48

+0

但是,如果它不是全零,這是不是也會讓你在oldrev之前被引用? – Cascabel 2014-06-01 21:40:08

+1

@Jefromi你是什麼意思?上面的命令會給你一個根本不從任何分支引用的所有提交列表。在更新和預先接收觸發器中,這是作爲推送的一部分添加的新提交:分支refname不存在(如果是新的)或尚未移動(如果存在)。這不適用於接收後的鉤子,但這不是問題所在。我不明白爲什麼這是低調的:這是對問題提出的最簡單,最乾淨的回答。 – MadScientist 2014-06-19 16:01:21