How to retrieve the history of a file?
Asked Answered
I

3

23

I got another libgit2 issue and will be very grateful for your help.

I'm trying to retrieve file history, i.e. list of commits where this file was changed. And it seems to be quite unconventional... As far as I can see, there are no function for that.

The only approach I can come up with is to use revision walking API to iterate through revisions, check the tree object attached to commit and search for given file there, if found, add commit to my list, otherwise proceed to next commit.

But it looks none-optimal for me...

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

Many thanks in advance!

Inquisition answered 23/11, 2011 at 9:10 Comment(0)
B
15

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.

Button answered 23/11, 2011 at 10:1 Comment(1)
Actually it's exactly the same issue :)Inquisition
H
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.

Humperdinck answered 17/6, 2015 at 7:20 Comment(6)
thanks but thats not much more than null token said. he also provided the one link. + I used google too .. I hoped for the gist shyitok talked about. - I implemented it but it doesn't follow renaming - it is based on the git log example codeAdriel
I agree, this is more an update, 4years later. The implementation, as mentioned, remains up for grabs.Humperdinck
@Adriel nulltoken mentions the same PR I just mentioned: LibGit2Sharp.0.22.0-pre20150415174523 has this feature.Humperdinck
I would like to retrieve the file history of a specific file as well. I already tried the next code, but there aren't any commits in the history IEnumerable. Could you please provide some information how to solve this problem. Repository repo = new Repository(repoPath); IEnumerable<LogEntry> history = repo.Commits.QueryBy(filePath, new FollowFilter { SortBy = CommitSortStrategies.Topological });Pongee
@Pongee I understand. It seems github.com/libgit2/rugged/pull/531 is still "in progress".Humperdinck
@Pongee not that I know of for now.Humperdinck
P
0

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;
}
Paramo answered 9/7, 2016 at 16:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.