2010-08-18 79 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