如何使用 jgit 查找所有提交,而不仅仅是可引用的提交

Posted

技术标签:

【中文标题】如何使用 jgit 查找所有提交,而不仅仅是可引用的提交【英文标题】:How to find all commits using jgit, not just referenceable ones 【发布时间】:2013-06-15 05:33:31 【问题描述】:

我正在尝试使用 jGit 获取存储库中的所有提交,不仅是我可以通过头或标签访问的提交,还包括所有尚未被垃圾收集的提交。有没有办法用 jGit 以有效的方式做到这一点?

更新以更好地描述实际用例

我正在开发一个基于 FUSE 的文件系统,它提供了 Git 历史的文件系统视图,请参阅https://github.com/centic9/JGitFS/ 了解第一个版本(仅限 Linux/Mac)。

有了这个,我为提交提供了“虚拟”子目录,即我正在创建一个如下所示的目录结构

/commit
   00
     abcd..
     bcde..
   ae
     bdas..

在提交 ID 下,虚拟文件​​系统提供了提交时的源文件。

Refs/Tags 以符号链接的形式提供,指向该 ref/tag 的实际提交 HEAD:

/branch
   master -> ../commit/00/abcd...
   bugfix -> ../commit/ae/bdas...
/tag
   version_1 -> ../commit/00/bcde...

为了使这个文件系统更快,我需要一种方法来快速迭代存储库中的所有提交。像我现在这样分别查看每个标签和 ref 是次优的,因为如果 ref 共享一个共同的历史(他们几乎总是这样做!),我会多次查看相同的提交。

最好我想获得所有仍然可用的提交的简单列表,而不仅仅是属于分支的提交,这样您甚至可以查看 refs/tags 无法再访问的版本。

【问题讨论】:

Git - get all commits and blobs they created的可能重复 感谢您的链接,不过我正在寻找使用 jgit 的解决方案,而不是命令行工具。 【参考方案1】:

如果找到通过 reflog 引用的提交就足够了,请使用 ReflogCommand(我建议在 JGit 3.0 发布后使用它,它应该在 2013 年 6 月 26 日发布)。

如果您还想查找 reflog 不再引用的提交,您需要类似 git fsck 的内容。 JGit 还没有实现。它确实有一个git gc 的实现,它还必须找到未引用的对象。

查看 JGit 存储库中GC.java 的源代码。你可以做的是调用GC#repack(),之后所有引用的对象都应该在包文件中。然后您可以执行类似于GC#prune 的操作,它会找到未引用的松散对象。请注意,GC 目前是内部的(不是 API),所以不要指望它保持这种状态。

【讨论】:

hmm,对于 ReflogCommand,我仍然需要指定一些“startRef()”来解析除 HEAD 之外的任何内容,所以这并不比从每个分支的头部执行 RevWalk 好多少/标签。我会看看 GC.java,但是听起来很复杂:( 遍历 reflog 和遍历分支的提交是不一样的,因为 reflog 还包括被丢弃且不再是历史一部分的提交。顺便说一句,如果您在问题中描述了您尝试解决的用例,这会有所帮助,也许有更好的解决方案。 是的,你是对的,我已经描述了我在这里真正想要做的事情 我现在尝试通过直接查看对象目录并从包文件中读取 id 来使用类似于 GC.java 所做的事情,但是因为我只对实际提交感兴趣而不是其他对象-types,我必须实际读取每个对象的类型,这使得它比读取每个 ref 的提交日志慢大约 10 倍,因此在性能方面这不是一个可行的解决方案...... 这个限制是 Git 存储数据的方式固有的,这里没有快速的方法。另请参阅Git Internals - Git Objects。

以上是关于如何使用 jgit 查找所有提交,而不仅仅是可引用的提交的主要内容,如果未能解决你的问题,请参考以下文章

如何列出存储库中的所有提交及其父信息以及使用命令行或 JGit 添加和删除的行?

如何使用 JGit 找到提交的分支?

如何查找由特定 plsql 方法更新的所有表

jGit - 如何将所有文件添加到暂存区

如何在与 JGit 合并之前获得冲突?

使用 JGit 从 Git 存储库中查看特定修订