2012-02-26 107 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