我正在使用libgit2sharp(libgit2的C#包装器),并且遇到了问题,因为它没有很多我想要的功能(希望我能很快为它做出贡献;这似乎是一个非常有用的项目)

我现在想做的事情是获取从特定提交及其父级更改的文件的列表。我不会试图弄清楚 merge 及其两个父级之间发生了什么变化。我对常规提交更感兴趣。

这些家伙(https://github.com/libgit2/libgit2sharp/issues/89)正在从事类似的工作。我认为他们的程序是一个不错的主意,但是我对GIT内部的理解有些虚弱(最终用户的GIT指南中有很多指南,但内部结构却不多)

我很好奇GIT本身是如何执行“git diff”命令的。假设GIT实际上没有存储增量,而是存储了文件的完整版本(如果未更改,它将仅指向现有的SHA。可以从各种来源(如http://xentac.net/2012/01/19/the-real-difference-between-git-and-mercurial.html)中找到此信息)。这似乎使在两次提交(在我的情况下是一个特定的提交及其单亲)之间的更改变得更加困难,因为数据没有作为提交的一部分存储(如果您在libgit2sharp的Commit.cs中检查Commit类,这很清楚)。文件)。

我可以从提交访问的是树。进行以下操作来查找此信息是否有意义:

1)从所需的提交开始,然后沿着树走,并将所有SHA值存储在一组中。

2)从父级开始进行所需的提交,然后向下移动其树以将其所有blob SHA值存储在另一组中。

3)更改的文件的SHA将是不在两个集合的交集中的文件。

我看到的这种方法的问题在于,它看起来好像没有一种方法可以从Blob的SHA值中获取文件名(我在libgit2sharp的Blob.cs文件中看不到任何可以做到这一点的东西)。

我知道这个问题有很多方面,但它们是从git中获取特定数据这一宏伟目标的一部分。

谢谢。

最佳答案

根据 libgit2 tree.h header 中的定义,在 Interop definitions 中已经存在一个差异树功能。
git_tree_diff()函数比较两个Trees并针对每个差异(添加,更新和删除)调用回调。正在向回调函数传递git_tree_diff_data结构,其中包含所考虑的Blob的文件路径,其状态,以前和当前的文件模式以及以前和当前的SHA。

从LibGit2Sharp的角度来看,利用现有的libgit2功能比在C#中重新实现它们更有意义。但是,即使您可以从现有的 src/tree.c 中获得一些启发,但在尝试驯服.Net/ native 互操作层时,事情往往会很快变得棘手。

从您的角度来看(作为对LibGit2Sharp的贡献可能不是您的主要目标;)),的另一种选择是依靠LibGit2Sharp的现有功能将C代码移植到C#git_tree_diff()(及其附属函数)是一段非常干净的代码,尽管它完成了相当复杂的工作,但注释却非常清晰和有用。

引用:

  • git_tree_diff()函数在 here
  • 中实现
  • 可以使用此功能进行测试 libgit2 tracker

  • 注:为了绑定(bind)git_tree_diff(),应在中打开一个问题unit tests in DiffTreeToTreeFixture.cs ,要求更新方法定义以使其成为GIT_EXTERN。否则它将无法从.Net访问。

    更新

    LibGit2Sharp的 v0.9.0 版本最终带来了Tree to Tree diffing功能。
    TreeChanges changes = repo.Diff.Compare(fromTree, newTree);
    公开的属性是:
  • 添加/修改的行
  • 每种更改(例如,已添加,已修改等)的TreeEntry集合的更改
  • 差异补丁

  • 通过查看 ojit_a ,您可以找到有关此功能以及如何利用TreeChanges的更多信息。

    关于git - 使用libgit2sharp获取提交及其父项之间的更改,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9133684/

    10-13 08:43
    查看更多