Repository.Commit() 抛出 EmptyCommitException,即使工作目录发生了变化

Repository.Commit() is throwing EmptyCommitException even though there are changes in the working directory

我有相当于此

的代码
public static async Task CopyAndRestAndCommitFile(Stream content,
                                                  string branchName,
                                                  string sha)
{
    CreateOrResetBranch(branchName, sha);

    await Copy(content);

    Commit("changed");
}

private static async Task Copy(Stream content)
{
    var filePath = @"C:\temp\libgit2sharpTestRepo\fileToChange.txt";
    using (var fileStream = new FileStream(filePath,
                                           FileMode.Create, 
                                           FileAccess.Write,
                                           FileShare.None,
                                           32 * 1024,
                                           useAsync: true))
    {
        await content.CopyToAsync(fileStream);
    }
}

private static void CreateOrResetBranch(string branchName, string startPoint)
{
    //This Replaces git -B \{branchName} \{startPoint}
    using (var repo = new LibGit2Sharp.Repository(RepositoryPath))
    {
        var branch = repo.Branches[branchName];
        if (branch == null)
        {
            branch = repo.CreateBranch(branchName, startPoint);
            repo.Checkout(branch);
        }
        else if (string.IsNullOrEmpty(startPoint))
        {
            repo.Checkout(branch);
        }
        else
        {
            var commit = repo.Commits.Single(c => c.Sha == startPoint);
            if (commit != null)
            {
                repo.Checkout(branch);
                repo.Reset(ResetMode.Hard, commit);
            }
        }
    }
}

private static void Commit(string message)
{
    // this replaces git add -A
    //               git -m \{message}
    using (var repo = new Repository(RepositoryPath))
    {
        repo.Stage("*");
        repo.Commit(message);
    }
}

CopyAndRestAndCommitFile()为切入点。由于某些原因 repo.Commit(message) 总是抛出 LibGit2Sharp.EmptyCommitException 即使磁盘上的文件已经更改。如果我在调用提交函数之前从命令行转到 运行 git status,提交成功。

这不是时间问题,因为无论我在 Copy()Commit() 函数之间延迟多长时间,问题都会发生。我重复 Commit() 函数多少次也没关系,它总是抛出异常,直到我从 repo 上的命令行 运行 git status

奇怪的是,上面的代码并没有完全重现这个问题,但它与实际代码之间的唯一区别是实际代码在 ASP.NET 上下文中是 运行ning我们正在复制的流是请求内容流。

如何调试这个问题?

EmptyCommitException 当要提交的树与父提交的树匹配时引发。这意味着没有进行任何修改。

由于您的场景演示了一些暂存工作,我的猜测是您在 libgit2.

中遇到了一个已知问题

repo.Stage() 是将 workdir 目录中发生的更改提升到 Index 的操作。为了做到这一点,LibGit2Sharp 在工作目录和索引之间运行差异。

但是,为了避免过多的 oid 计算,当前的 libgit2 启发式 "skips" 一个文件,如果它在磁盘上的大小与索引知道的相同并且如果修改时间没有改变。问题是,根据最初的 git 设计,时间戳以一秒的精度存储在索引中。

因此,当您在同一秒内暂存两次文件而不更改其大小时,libgit2 diff 算法将无法检测到第二个文件。

有关详细信息,请参阅 http://github.com/libgit2/libgit2sharp/pull/688