2012-06-05 43 views
6

在命令行,如果I型包含一个提交

git tag --contains {commit} 

以获得包含给定提交版本的列表的版本的高效检索,它需要大约11至20秒为每个提交。由于目标代码库存在超过300,000次提交,因此对于所有提交检索此信息将花费很多。

但是,gitk显然设法检索这些数据做得很好。从我搜索的内容来看,它使用缓存来达到这个目的。

我有两个问题:

  1. 我怎么能解释该高速缓存格式?
  2. 有没有办法从git命令行工具获取转储以生成相同的信息?
+0

要实现您自己的cli缓存功能吗?如果是这样,我想我可以为此提出一些想法。 –

+0

是的,那对我很有用。 – leco

回答

5

你几乎可以直接从git rev-list得到这个。

latest.awk

BEGIN { thiscommit=""; } 
$1 == "commit" { 
    if (thiscommit != "") 
     print thiscommit, tags[thiscommit] 
    thiscommit=$2 
    line[$2]=NR 
    latest = 0; 
    for (i = 3 ; i <= NF ; ++i) if (line[$i] > latest) { 
     latest = line[$i]; 
     tags[$2] = tags[$i]; 
    } 
    next; 
} 
$1 != "commit" { tags[thiscommit] = $0; } 
END { if (thiscommit != "") print thiscommit, tags[thiscommit]; } 

样本命令:

git rev-list --date-order --children --format=%d --all | awk -f latest.awk 

你也可以使用--topo-order,你可能不得不在$1!="commit"逻辑淘汰不需要的裁判。

根据您想要的传递性以及清单的明确程度,积累标签可能需要一个字典。下面是一个得到所有裁判对所有提交明确的上市:

all.awk

BEGIN { 
    thiscommit=""; 
} 
$1 == "commit" { 
    if (thiscommit != "") 
     print thiscommit, tags[thiscommit] 
    thiscommit=$2 
    line[$2]=NR 
    split("",seen); 
    for (i = 3 ; i <= NF ; ++i) { 
     nnew=split(tags[$i],new); 
     for (n = 1 ; n <= nnew ; ++n) { 
      if (!seen[new[n]]) { 
       tags[$2]= tags[$2]" "new[n] 
       seen[new[n]] = 1 
      } 
     } 
    } 
    next; 
} 
$1 != "commit" { 
    nnew=split($0,new,", "); 
    new[1]=substr(new[1],3); 
    new[nnew]=substr(new[nnew],1,length(new[nnew])-1); 
    for (n = 1; n <= nnew ; ++n) 
     tags[thiscommit] = tags[thiscommit]" "new[n] 

} 
END { if (thiscommit != "") print thiscommit, tags[thiscommit]; } 

all.awk花了几分钟做322K Linux内核的回购承诺,约一千第二或类似的东西(大量重复的字符串和冗余处理),所以如果你真的在完整的交叉产品之后,你可能想用C++重写它......但我不认为gitk显示了这一点,只有最近的邻居?

+0

因此,为了澄清我们的非awk用户:这些脚本与'git tag --contains {commit}'完全相同吗? –

+0

rev-list的%d显示所有ref不只是标签,所以all.awk获取所有标签和分支不仅仅是标签,但除此之外是的,all.awk是一批 - 包含... btw它不会采取两个学习awk的时间。 – jthill

相关问题