2

在我的示例代码中,我这样做(在 Windows 上):

var repo = new Repository(command.RepoFolder);
for (int i = 0; i < 100; i++)
{
  string file = command.RepoFolder + "\\text.txt";
  File.WriteAllText(file, string.Format("File number {0}, written at {1}", i, DateTime.Now));

  repo.Index.Stage("text.txt");
  repo.Commit(string.Format("Written version {0}", i), new Signature("me through code", "email@email.com", DateTimeOffset.Now));
}

如果我使用调试器逐步执行此序列,则通过循环运行的每个循环都会创建一个新的提交,其中包含 text.txt 文件中的预期检查和适当的提交消息。但是,如果我在不阻止它的情况下运行它,我会得到 100 次提交,并带有预期的提交消息,但只有一些提交中有真正的文件更改。它们通常是这种形式:

- File number 54, written at 8/30/2013 10:27:38 AM
+ File number 88, written at 8/30/2013 10:27:39 AM

因此,似乎 repo.Index.Stage() 是异步发生的,并且提交是在注意到文件系统更改之前完成的。这是预期的吗?这是“活泼的 git”行为吗?Libgit2Sharp 中有没有办法明确地等待索引接收到更改?

添加:

  1. 如果我对文件进行附加而不是用不同的行重写,一切正常
  2. 如果我在命令行上使用 git.exe 做同样的事情,我看不到这样的行为
4

2 回答 2

4

LibGit2Sharprepo.Index.Stage()依靠 libgit2 差异功能来确定工作目录中哪些文件已被修改,哪些文件尚未修改。

在进行比较时,在比较实际文件内容之前,libgit2 依靠一些“技巧”来检查文件是否已更改。例如:

  • 如果文件在索引和工作目录中的大小相同
  • 并且文件修改日期/时间是否相同(在 Windows 上以秒为精度的时间)
  • 如果其他属性(文件所有者、模式、...)相同

那么文件就被认为是未修改的,根本不会打开它来查看内容是否相同。这允许对包含数千个文件的大型存储库进行大优化。

在您的情况下,您的许多文件具有相同的大小和相同的修改日期/时间,这就是为什么这些文件没有被repo.Index.Stage().


Thread.Sleep(TimeSpan.FromSeconds(1));一个可能的(肮脏的)解决方法是在您的修改之间添加一个。


最近在 LibGit2Sharp bugtracker 上打开了处理相同问题的错误报告。如果你有真实世界的例子,或者关于这个主题的意见,请随时权衡!

于 2013-09-02T11:59:25.827 回答
1

我遇到了同样的问题,但是这个Thread.Sleep技巧对我不起作用,不管我让它等了多久,但这确实

File.SetLastWriteTime(filePath, DateTime.UtcNow.AddHours(-1));

于 2013-09-11T03:13:53.000 回答