【问题标题】:Identify renamed and modified file in Git using SHA1使用 SHA1 识别 Git 中重命名和修改的文件
【发布时间】:2011-11-30 10:06:08
【问题描述】:

我在低级别的 git 存储库中进行黑客攻击,试图从中检索文件的历史记录。并且难以识别在同一版本中修改和重命名的文件。

我正在开发 C# 应用程序,我需要实现 git log --follow FILENAME 功能。

修改很简单:在附加到修订版的树中搜索具有给定路径的文件,如果 SHA1 不同 - Voilà

重命名也很简单:如果按给定路径搜索不成功 — 查找具有相同 SHA1 的对象,如前所述,如果找到 — Voilà

但是如果没有找到,可能是文件删除了,我的搜索结束了,或者在同一个版本中重命名和修改……但是如何区分这些情况呢?

我研究了我发现的关于 Git 内部的所有内容,但仍然不知道在这种情况下该怎么做,在不同修订版中对应于相同修改和重命名文件的树对象之间可能有什么共同点?

非常感谢您的帮助!

【问题讨论】:

    标签: c# git repository low-level


    【解决方案1】:

    Git 已经具备该功能。参见-M/--find-renames-C/--find-copies-C -C/--find-copies-harder 选项diff(也适用于logshow)和log 选项@。

    --find-renames 的原则是,如果它在修订中看到新文件,它会查看在该修订中删除的文件,比较它们,如果有足够相似,则将其声明为重命名。

    编辑:更详细:为了检测副本/重命名,git 首先比较两个修订版,它比较文件列表。对于仅出现在新修订版中的每个路径,它会将内容与旧修订版中-M—已删除、-C—已修改或-C—所有文件的内容进行比较,如果它们足够相似(需要差异),将其标记为适当的重命名或复制。这是差异核心的一部分,可用于以任何形式显示差异的所有命令,包括名称状态,它不进行详细的逐行分析。最重要的是,--follow 的工作原理是逐个迭代修订,使用重命名检测进行名称状态差异,并在文件被修改时输出修订,并在重命名时记住新(旧)名称。

    【讨论】:

    • 感谢您的回答。但这并不是我想要的……我需要使用 C# 来实现它。而且我不能使用可执行文件。我可以访问.git 文件夹,并且可以使用libgit2sharp 检索一些信息。我可以找到存储库中某处存储的重命名信息吗?
    • @AlexeyShytikov:信息永远不会存储在任何地方。如果 libgit2 还没有实现逻辑,你需要重新实现(参见上面的第二段)它。如果你这样做了,请考虑直接在 libgit2 中用 C 语言做它并回馈它。请注意,libgit2 不能从 git 中获取代码(因为许可证更宽松),但您仍然可以查看它在 git 中是如何完成的。
    • 不幸的是 libgit2 不需要这个代码:github.com/libgit2/libgit2/issues/495(也许他们是对的),所以我计划为 libgit2sharp 做出贡献github.com/libgit2/libgit2sharp/issues/89 但实际上它并不像第一次那么容易看。
    • @AlexeyShytikov:为什么你认为它不需要代码?没有人站出来讨论它,这可能有很多不同的原因。绑定(libgit2sharp)应该是bindings。它们应该使基础库的功能可访问,但不提供新功能。问题是您需要的功能取决于差异功能,而我在 libgit2 中根本看不到。
    • 实际上这就是为什么:I don't think the library should support it itself. via 我同意,因为跟踪文件历史不是库的基本功能。谈到libgit2sharp,他们确实在libgit2 之上有一些功能,所以他们应该可以将文件历史功能引入他们的对象模型。
    猜你喜欢
    • 1970-01-01
    • 2016-05-23
    • 1970-01-01
    • 2017-06-08
    • 2017-05-17
    • 1970-01-01
    • 2011-08-08
    • 2018-04-23
    相关资源
    最近更新 更多