git日志提取shortstats对象

v1l68za4  于 2022-12-10  发布在  Git
关注(0)|答案(1)|浏览(94)

我克隆了一个特定的仓库,作为自动化系统的一部分来解析提交。我使用的命令是:

git clone https://github.com/google/material-design-icons.git --filter=blob:none --bare --no-tags --single-branch

这对于生成我所能实现的最小磁盘克隆以及确保快速克隆非常有效,这两点对我的过程都很重要。
当使用以下命令运行git log时:

git --no-pager log --max-count=10000 --shortstat -z

git log似乎在提交之间暂停以枚举接收对象:

remote: Enumerating objects: 8, done.
remote: Counting objects: 100% (8/8), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 8 (delta 2), reused 8 (delta 2), pack-reused 0
Receiving objects: 100% (8/8), 13.48 MiB | 5.76 MiB/s, done.
Resolving deltas: 100% (2/2), done.

如果我删除--shortstat标志,就不会发生这种情况。我尝试深入研究文档,但是我要么遗漏了有关--shortstat为什么拉对象的内容,或者我缺乏制度知识。上面提到的回购协议是我们在处理过程中遇到的少数表现出这种行为的回购协议之一。我希望能够输出统计数据,同时拥有一个精简的克隆,而不必在提交之间从远程枚举对象。

lymnna71

lymnna711#

通过--filter=blob:none参数使用新的(仍在开发中)partial clone 特性,这就解释了整个问题。
部分克隆的工作原理是基于一个基本的Git假设。Git假设你总是拥有整个仓库。仓库本身由两个独立的数据库组成:

  • 一种是Git的 objects,这些对象用看起来随机的(但实际上不是随机的)Object ID或OID进行编号。其中一些对象是commit,它们本身非常小,因为它们 * 只包含commit的元数据 *。其他对象类型包含实际的文件(以及其他有用的信息,这些信息在这里几乎不相关)。
  • 另一个数据库保存 names,例如分支和标记名称,将每个名称Map到单个OID。

在一个“普通”的Git仓库中,每个名字Map到一个OID,这个OID实际存在于对象数据库中。该数据库中的提交对象包含额外的OID,这些OID可以定位对象数据库中的额外对象。因此,Git可以提取任何提交的完整快照,而完全不需要借助任何网络访问,因为所有的东西都存在于 * 数据库中 *,本地。
然而,在部分克隆中,有些对象会丢失。它们会被Git称为 promisor pack 的对象所替换。当Git需要一些对象,但却找到了其中一个promisor pack替换对象时,Git必须调用你最初克隆的仓库,并获取丢失的对象。
当使用git log时,Git只需要检查提交元数据。但当你添加--stat--shortstat-p或其他选项时,Git需要检查提交元数据。(部分或全部)文件 *,所以Git会暂停,如果可能的话收集这些对象,将它们插入到对象数据库中,然后才继续下一次提交。
为了获得diff信息,包括--shortstat样式信息,Git需要 two commit的部分或全部文件。由于 tree 对象的数据格式,Git实际上只需要那些不同的文件,所以你可以使用比完整克隆所需的更小的blob集合。但是有一个巨大的缺点:Git一次只提取几个blob,每次提取都有很大的开销。
您可能会发现,总体而言,克隆整个仓库的速度更快,这样git log就不必再提取任何对象了。考虑使用 reference clone 来加速初始克隆过程。(由于引用克隆将是完整克隆,因此这可能对磁盘空间没有太大帮助,但如果您避免使用--dissociate,引用克隆本身可以为每个进一步的克隆提供对象,因此您只有一个克隆使用空间,而不是可能有很多克隆。但是,如果没有--dissociate,您必须非常小心,使引用克隆本身保持有效和可访问。)

相关问题