22

我遇到了另一个 libgit2 问题,非常感谢您的帮助。

我正在尝试检索文件历史记录,即更改此文件的提交列表。而且它似乎非常不合常规......据我所知,没有任何功能。

我能想出的唯一方法是使用修订遍历 API 来遍历修订,检查附加到提交的树对象并在那里搜索给定文件,如果找到,将提交添加到我的列表中,否则继续下一次提交。

但它看起来对我来说不是最优的......

可能有没有其他方法,例如,直接查看.git文件夹并在那里获取所需的信息?

提前谢谢了!

4

3 回答 3

15

但它看起来对我来说不是最优的......

你的方法是正确的。请注意,您将不得不对抗:

  • 普通重命名(相同的对象哈希,不同的树条目名称)
  • 在同一提交中发生重命名和内容更新(不同的哈希,不同的树条目名称。需要 libgit2 中不可用的文件内容分析和比较功能)
  • 多个父历史记录(已合并的两个分支,同一文件已以不同方式修改到其中)

可能有没有其他方法,例如,直接查看 .git 文件夹并在那里获取所需的信息?

尽管了解 .git 文件夹布局总是花费大量时间,但恐怕这对您解决这个特定的文件历史问题没有帮助。

注意:这个问题与这个 libgit2sharp 问题非常接近:如何获取影响给定文件的最后一次提交?

更新

拉取请求#963添加了这个特性。

它自LibGit2Sharp.0.22.0-pre20150415174523预发布 NuGet 包以来可用。

于 2011-11-23T10:01:30.327 回答
2

This is mainly followed in issues/495 of libgit2.
Even though it is implemented in libgit2sharp (PR 963, for milestone 22), it is still "up for grabs" in libgit2 itself.

The issue is documented in issues/3041: Provide log functionality wrapping the revwalk.
The approach mentioned in the question was used in this libgit2sharp example and can be adapted to C using libgit2. It remains the current workaround, pending the resolution of 3041.

于 2015-06-17T07:20:44.690 回答
0

如果使用 C#,此功能已添加到LibGit2Sharp0.22.0 NuGet 包( Pull Request 963 )。您可以执行以下操作:

var fileHistory = repository.Commits.QueryBy(filePathRelativeToRepository);
foreach (var version in fileHistory)
{
    // Get further details by inspecting version.Commit
}

在我的Diff All Files VS Extension(它是开源的,因此您可以查看代码)中,我需要获取文件的先前提交,以便查看在给定提交中对文件进行了哪些更改。这就是我检索文件先前提交的方式:

/// <summary>
/// Gets the previous commit of the file.
/// </summary>
/// <param name="repository">The repository.</param>
/// <param name="filePathRelativeToRepository">The file path relative to repository.</param>
/// <param name="commitSha">The commit sha to start the search for the previous version from. If null, the latest commit of the file will be returned.</param>
/// <returns></returns>
private static Commit GetPreviousCommitOfFile(Repository repository, string filePathRelativeToRepository, string commitSha = null)
{
    bool versionMatchesGivenVersion = false;
    var fileHistory = repository.Commits.QueryBy(filePathRelativeToRepository);
    foreach (var version in fileHistory)
    {
        // If they want the latest commit or we have found the "previous" commit that they were after, return it.
        if (string.IsNullOrWhiteSpace(commitSha) || versionMatchesGivenVersion)
            return version.Commit;

        // If this commit version matches the version specified, we want to return the next commit in the list, as it will be the previous commit.
        if (version.Commit.Sha.Equals(commitSha))
            versionMatchesGivenVersion = true;
    }

    return null;
}
于 2016-07-09T16:25:46.160 回答