5

我正在循环提交LibGit2Sharp

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

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

我可以检索和之类的属性AuthorMessage但我看不到它属于哪个分支?理想情况下,我希望有一个指向分支对象的指针,但在这种情况下,即使是名称也可以。

这是调试器显示的内容:

在此处输入图像描述

这就是我要找的:

在此处输入图像描述

TortoiseGit 显示最相关分支名称的行为:

在此处输入图像描述

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

4

3 回答 3

7

目前没有内置的方法来模仿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开发分支的当前提示成功测试。

更新:

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

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

[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;
    }
}
于 2012-02-26T10:48:58.503 回答
2

Git 不会将分支信息与提交一起存储。您必须遍历历史 DAG 并查看是否可以从 refs 访问提交。

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

于 2012-02-26T10:10:52.570 回答
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));

    …
}
于 2012-02-26T10:27:14.100 回答