在LibGit2Sharp中找出提交所属的分支?

时间:2012-02-26 09:48:27

标签: c# git libgit2 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显示最相关分支名称的行为:

enter image description here

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

3 个答案:

答案 0 :(得分:5)

目前没有内置方式可以模仿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进行了测试。

<强>更新

在评论中讨论之后,这里有一个小小的更新,我希望能满足您的要求。

下面的代码将返回包含搜索到的提交的所有分支。如果提交恰好是至少一个分支的提示,那么将返回那些分支。

[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;
    }
}

答案 1 :(得分:1)

Git不会通过提交存储分支信息。您必须遍历历史DAG并查看是否可以从refs中获取提交。

在具有普通git的命令行上,您将运行git branch --contains $SHA1

答案 2 :(得分:1)

正如knittl所说,git不存储这些信息。提交是具有一些元数据的存储库的固定状态。由于提交是不可变的,并且它所属的分支可以更改,因此分支信息不能直接存储在提交中。

因此,要找出某个提交是否实际属于某个分支,您需要遍历该分支的提交并将它们与一个提交进行比较。

为了加快速度,您可以将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));

    …
}