2012-02-26 64 views
3

我通過循環犯LibGit2Sharp在LibGit2Sharp中找出提交所屬的分支?

Repository repo = new Repository("Z:/www/gg"); 

foreach (LibGit2Sharp.Commit commit in repo.Commits) 
{ 
    ... 
} 

我可以檢索像AuthorMessage屬性,但我不認爲它是屬於哪個分支什麼?理想情況下,我想要一個指向分支對象的指針,但在這種情況下,即使名稱也沒問題。

這是調試器顯示出來:

enter image description here

這就是我要找:

enter image description here

顯示最相關的分支名稱的TortoiseGit的行爲:

​​

存儲庫示例:https://docs.google.com/open?id=0B-3-X85VysdNcmZIaGVTSDZSenVGbTJxYlI2SUlsZw

回答

4

目前模仿git branch --contains <commit>沒有內置的方式。

但是,您可以通過明確地遍歷每個分支並將每個彈出的提交與搜索的提交進行比較來解決此限制。

下面的測試演示了這種

[Test] 
public void CanSearchBranchesContainingASpecificCommit() 
{ 
    using (var repo = new Repository(StandardTestRepoPath)) 
    { 
     const string commitSha = "5b5b025afb0b4c913b4c338a42934a3863bf3644"; 
     IEnumerable<Branch> branches = ListBranchesContaininingCommit(repo, commitSha); 

     branches.Count().ShouldEqual(6); 
    } 
} 

private IEnumerable<Branch> ListBranchesContaininingCommit(Repository repo, string commitSha) 
{ 
    foreach (var branch in repo.Branches) 
    { 
     var commits = repo.Commits.QueryBy(new CommitFilter { Since = branch }).Where(c => c.Sha == commitSha); 

     if (!commits.Any()) 
     { 
      continue; 
     } 

     yield return branch; 
    } 
} 

注:該代碼兌LibGit2Sharp的the current tip of the development branch試驗成功。

UPDATE:

繼在評論中討論,這裏有一個小更新,我希望將滿足您的要求。

下面的代碼將返回包含搜索提交的所有分支。如果提交恰好是至少一個分支的提示,那麼這些分支將被返回。

[Test] 
public void CanSearchBranchesContainingASpecificCommit() 
{ 
    using (var repo = new Repository(StandardTestRepoPath)) 
    { 
     const string commitSha = "5b5b025afb0b4c913b4c338a42934a3863bf3644"; 
     IEnumerable<Branch> branches = ListBranchesContaininingCommit(repo, commitSha); 

     branches.Count().ShouldEqual(6); 

     const string otherCommitSha = "4a202b346bb0fb0db7eff3cffeb3c70babbd2045"; 
     branches = ListBranchesContaininingCommit(repo, otherCommitSha); 

     branches.Count().ShouldEqual(1); // origin/packed-test 
    } 
} 

private IEnumerable<Branch> ListBranchesContaininingCommit(Repository repo, string commitSha) 
{ 
    bool directBranchHasBeenFound = false; 
    foreach (var branch in repo.Branches) 
    { 
     if (branch.Tip.Sha != commitSha) 
     { 
      continue; 
     } 

     directBranchHasBeenFound = true; 
     yield return branch; 
    } 

    if (directBranchHasBeenFound) 
    { 
     yield break; 
    } 

    foreach (var branch in repo.Branches) 
    { 
     var commits = repo.Commits.QueryBy(new CommitFilter { Since = branch }).Where(c => c.Sha == commitSha); 

     if (!commits.Any()) 
     { 
      continue; 
     } 

     yield return branch; 
    } 
} 
+0

這工作正常,但還有一件事:我可以不知何故知道這些多個分支中的哪一個是它所屬的「最近的一個」?即在我的情況下,如果它是一年前屬於某個分支的,如果它在一週前剛剛合併爲「master」,那就沒什麼意義了。我懷疑我只能依靠它成爲第一個結果集... – Tower 2012-02-26 11:10:45

+0

你能給我一些例子或等效的git命令嗎?我很樂意回答你,但我不確定要清楚地瞭解「最新」分支是什麼。 – nulltoken 2012-02-26 11:40:27

+0

如果您從'master'分支並創建分支'foo'。如果你現在提交'foo',提交是2個分支的一部分('foo'和'master')。我想要的只是'foo',因爲那是「最近的」。如果'foo'是一個孤兒分支('git checkout -b foo --orphan'),那麼你的解決方案只會返回'foo',我可以使用它,但在很多情況下,提交是一個或多個分支的一部分,只對最近連接的那個感興趣。 – Tower 2012-02-26 12:40:17

1

Git不存儲具有提交的分支信息。你必須走歷史的DAG,看看提交是否可以從ref中得到。

與普通的git命令行作爲knittl說,Git並不保存這些信息,你會跑git branch --contains $SHA1

+0

該命令行調用正是我想要的。現在我該如何使用LibGit2Sharp來做到這一點? – Tower 2012-02-26 10:52:16

1

。提交是具有一些元數據的存儲庫的固定狀態。由於提交是不可變的,它所屬的分支可以改變,分支信息不能直接存儲在提交中。

因此,要確定某個提交是否實際屬於某個分支,您需要遍歷該分支的提交併將它們與一個提交進行比較。

爲了使這個速度,你可以爲每個分支的所有提交存放在HashSet<T>這樣的:

var branchCommits = 
    repo.Branches.Select(
     b => new 
      { 
       b.Name, 
       Commits = new HashSet<Commit>(b.Commits) 
      }) 
     .ToArray(); 

foreach (Commit commit in branch.Commits) 
{ 
    var commitBranches = branchCommits.Where(b => b.Commits.Contains(commit)); 

    … 
} 
+2

請注意,這是急切地加載內存中每個分支的所有提交(基本上分析整個存儲庫)。爲了更加「資源友好」,可以依靠利用walker的'Commits.QueryBy()'方法。 – nulltoken 2012-02-26 11:15:17