在命令行,如果I型包含一个提交
git tag --contains {commit}
以获得包含给定提交版本的列表的版本的高效检索,它需要大约11至20秒为每个提交。由于目标代码库存在超过300,000次提交,因此对于所有提交检索此信息将花费很多。
但是,gitk
显然设法检索这些数据做得很好。从我搜索的内容来看,它使用缓存来达到这个目的。
我有两个问题:
- 我怎么能解释该高速缓存格式?
- 有没有办法从
git
命令行工具获取转储以生成相同的信息?
在命令行,如果I型包含一个提交
git tag --contains {commit}
以获得包含给定提交版本的列表的版本的高效检索,它需要大约11至20秒为每个提交。由于目标代码库存在超过300,000次提交,因此对于所有提交检索此信息将花费很多。
但是,gitk
显然设法检索这些数据做得很好。从我搜索的内容来看,它使用缓存来达到这个目的。
我有两个问题:
git
命令行工具获取转储以生成相同的信息?你几乎可以直接从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显示了这一点,只有最近的邻居?
因此,为了澄清我们的非awk用户:这些脚本与'git tag --contains {commit}'完全相同吗? –
rev-list的%d显示所有ref不只是标签,所以all.awk获取所有标签和分支不仅仅是标签,但除此之外是的,all.awk是一批 - 包含... btw它不会采取两个学习awk的时间。 – jthill
要实现您自己的cli缓存功能吗?如果是这样,我想我可以为此提出一些想法。 –
是的,那对我很有用。 – leco