我想列出git存储库中大量文件的最后提交日期.
为了具体起见,让我们假设我想获取*.txt
特定子目录中所有文件的最后提交日期.存储库中总共有数万个文件,相关*.txt
文件的数量在数百个.存储库中已有数千个提交.
我尝试了三种不同的方法.
解答1. 这个问题给出了一个答案,基于git log
.但是,如果我尝试做这样的事情,那就很慢了:
find . -name '*.txt' |
xargs -n1 git log --format=format:%ai -n1 --all -- '{}'
Run Code Online (Sandbox Code Playgroud)
在我的测试案例中,花了几分钟 - 对我来说太慢了.
解决方案2.这样的事情要快得多,不到一秒钟:
git log --format=format:%ai --name-only .
Run Code Online (Sandbox Code Playgroud)
但是,我必须编写一个后处理输出的脚本.此外,上面的命令打印出许多永远不需要的信息:无关文件和旧提交.
解决方案3.我也试过这样的东西,以摆脱不相关的文件:
git log --format=format:%ai --name-only `find . -name '*.txt'`
Run Code Online (Sandbox Code Playgroud)
然而,事实证明这比解决方案2 慢.(运行时间有3个不同.)此外,它仍然会打印不再需要的旧提交.
题.我错过了什么吗?有快速方便的方法吗?当我们提交更多数量的提交时,最好是现在还是将来工作的东西?
试试这个.
在git中,每个提交引用一个树对象,该对象具有指向每个文件状态的指针(文件是blob对象).
所以,你要做的是编写一个程序,该程序以你感兴趣的所有文件的列表开始,并从HEAD
对象开始(通过SHA1提交git rev-parse HEAD
).它检查是否在该树中修改了任何"感兴趣的文件"(树从"树"属性获得git cat-file commit [SHA1]
) - 注意,您将必须下降到每个目录的子树.如果它们被修改(意味着与"上一个"修订版中的SHA1哈希值不同),它会从兴趣集中删除每个哈希值并打印相应的信息.然后它继续到当前树的每个父节点.这一直持续到感兴趣的组为空.
如果你想要最大速度,你将使用git C API.如果你不想说太多的速度,你可以使用git cat-file tree [SHA1 hash]
(或者,更容易,git ls-tree [SHA1 hash] [files]
),这是要执行工作的绝对量最小读取特定的树对象(管道层的它的一部分).
这个问题将来会继续发挥作用是值得怀疑的,但如果前向比较是一个更大的问题,你可以提升一个级别git cat-file
- 但正如你已经发现的那样,git log
它相对较慢,因为它是瓷器的一部分,而不是管道.
请参阅此处获取有关git对象模型如何工作的非常好的资源.