How to retrieve the history of a file?

假如想象 提交于 2019-11-30 10:59:47

But it looks none-optimal for me...

Your approach is the correct one. Beware that you'll have to fight against:

  • Plain renaming (same object Hash, different tree entry name)
  • Renaming and content updation occuring in the same commit (Different hash, different tree entry name. Would require file content analysis and comparison feature which is not available in libgit2)
  • Multiple parents history (two branches which have been merged and into which the same file has been modified in a different way)

May be is there any other approach, for example, look directly into .git folder and get needed information there?

Even though understanding the .git folder layout is always a well-spent time, I'm afraid this won't help you with this specific file history issue.

Note: this question is very close from this libgit2sharp issue: How to get the last commit that affected a given file?

Update

Pull request #963 adds this very feature.

It's available since LibGit2Sharp.0.22.0-pre20150415174523 pre-release NuGet package.

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.

If using C#, this functionality has been added to the LibGit2Sharp 0.22.0 NuGet Package (Pull Request 963). You can do the following:

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

In my Diff All Files VS Extension (which is open source so you can view the code), I needed to get a file's previous commit so I can see what changes were made to a file in a given commit. This is how I retrieved the file's previous commit:

/// <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;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!