2012-06-05 42 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

相關問題