English ▾ 主题 ▾ 最新版本 ▾ git-pack-objects 上次更新于 2.49.0

NAME

git-pack-objects - 创建对象的打包存档

SYNOPSIS

git pack-objects [-q | --progress | --all-progress] [--all-progress-implied]
	[--no-reuse-delta] [--delta-base-offset] [--non-empty]
	[--local] [--incremental] [--window=<n>] [--depth=<n>]
	[--revs [--unpacked | --all]] [--keep-pack=<pack-name>]
	[--cruft] [--cruft-expiration=<time>]
	[--stdout [--filter=<filter-spec>] | <base-name>]
	[--shallow] [--keep-true-parents] [--[no-]sparse]
	[--name-hash-version=<n>] < <object-list>

DESCRIPTION

从标准输入读取对象列表,并将一个或多个具有指定基本名称的打包存档写入磁盘,或将打包存档写入标准输出。

打包存档是在两个存储库之间传输一组对象的有效方式,也是一种访问高效的存档格式。在打包存档中,对象要么存储为压缩的整体,要么存储为与某些其他对象的差异。后者通常被称为 delta。

打包存档格式 (.pack) 被设计为自包含的,因此可以无需任何其他信息即可解包。因此,delta 依赖的每个对象都必须存在于包中。

会生成一个包索引文件 (.idx),以便快速随机访问包中的对象。将索引文件 (.idx) 和打包存档 (.pack) 都放置在 $GIT_OBJECT_DIRECTORY 的 pack/ 子目录(或 $GIT_ALTERNATE_OBJECT_DIRECTORIES 上的任何目录)中,使 Git 能够从包存档中读取。

git unpack-objects 命令可以读取打包存档并将包中包含的对象展开为 "one-file one-object" 格式;当通过智能拉取命令为高效网络传输而即时创建包时,通常会这样做。

OPTIONS

base-name

使用 <base-name> 写入文件对 (.pack 和 .idx),以确定创建的文件的名称。使用此选项时,文件对中的两个文件将写入 <base-name>-<SHA-1>.{pack,idx} 文件。 <SHA-1> 是基于包内容的哈希值,并写入命令的标准输出。

--stdout

将包内容(原本将写入 .pack 文件的内容)输出到标准输出。

--revs

从标准输入读取修订参数,而不是单个对象名称。修订参数的处理方式与 git rev-list 使用带有 --objects 标志的 commit 参数来构建其输出的对象列表的方式相同。结果列表上的对象将被打包。除了修订之外,还接受 --not--shallow <SHA-1> 行。

--unpacked

这意味着 --revs。处理从标准输入读取的修订参数列表时,将打包的对象限制为尚未打包的对象。

--all

这意味着 --revs。除了从标准输入读取的修订参数列表之外,假装指定包含 refs/ 下的所有引用。

--include-tag

如果其引用的对象包含在生成的包文件中,则包含未经请求的带注释的标签。这对于将新标签发送到原生 Git 客户端很有用。

--stdin-packs

从标准输入读取包文件的基本名称(例如,pack-1234abcd.pack),而不是对象名称或修订参数。生成的包包含包含的包(那些不以 ^ 开头的包)中列出的所有对象,但不包括排除的包(以 ^ 开头)中列出的任何对象。

--revs 或暗示 --revs 的选项(例如 --all)不兼容,但 --unpacked 除外,它兼容。

--cruft

将无法访问的对象打包到单独的 "cruft" 包中,用 .mtimes 文件的存在表示。通常由 git repack --cruft 使用。调用者提供包名称列表,并指示哪些包将保留在存储库中,以及哪些包将被删除(以 - 前缀表示)。cruft 包的内容是不包含在幸存包中且未超过宽限期的所有对象(请参阅下面的 --cruft-expiration),或者已超过宽限期但可以从另一个尚未超过宽限期的对象访问的对象。

当输入列出一个包含所有可访问对象的包(并将所有其他包列为待删除)时,相应的 cruft 包将包含所有无法访问的对象(mtime 比 --cruft-expiration 新)以及 mtime 比 --cruft-expiration 旧但可以从 mtime 比 --cruft-expiration 新的无法访问对象访问的任何无法访问的对象。

--unpack-unreachable--keep-unreachable--pack-loose-unreachable--stdin-packs 以及任何其他暗示 --revs 的选项不兼容。

--cruft-expiration=<approxidate>

如果指定,则如果对象的 mtime 比 <approxidate> 旧,则会从 cruft 包中删除这些对象。如果未指定(并且给定 --cruft),则不会删除任何对象。

--window=<n>
--depth=<n>

这两个选项影响如何使用 delta 压缩来存储包中包含的对象。对象首先按类型、大小和可选名称进行内部排序,并与 --window 中的其他对象进行比较,以查看使用 delta 压缩是否可以节省空间。 --depth 限制了最大 delta 深度;使其太深会影响解包器端的性能,因为需要多次应用 delta 数据才能获得必要的对象。

--window 的默认值为 10,--depth 的默认值为 50。最大深度为 4095。

--window-memory=<n>

此选项在 --window 之上提供了额外的限制;窗口大小将动态缩小,以便在内存中不超过 <n> 字节。这在具有大小对象混合的存储库中很有用,可以避免在使用大窗口时耗尽内存,但仍然能够为较小的对象利用大窗口。大小可以用 "k"、"m" 或 "g" 作为后缀。 --window-memory=0 使内存使用不受限制。默认值取自 pack.windowMemory 配置变量。

--max-pack-size=<n>

在不寻常的情况下,你可能无法在文件系统上创建大于某个大小的文件,并且可以使用此选项来告诉命令将输出包文件拆分为多个独立的包文件,每个文件都不大于给定的大小。大小可以用 "k"、"m" 或 "g" 作为后缀。允许的最小大小限制为 1 MiB。默认值为无限制,除非设置了配置变量 pack.packSizeLimit。请注意,此选项可能会导致存储库更大更慢;请参阅 pack.packSizeLimit 中的讨论。

--honor-pack-keep

此标志使已经存在于具有 .keep 文件的本地包中的对象被忽略,即使它原本会被打包。

--keep-pack=<pack-name>

此标志使已经存在于给定包中的对象被忽略,即使它原本会被打包。 <pack-name> 是不带前导目录的包文件名(例如 pack-123.pack)。可以多次指定该选项以保留多个包。

--incremental

此标志使已经存在于包中的对象被忽略,即使它原本会被打包。

--local

此标志使从备用对象存储借用的对象被忽略,即使它原本会被打包。

--non-empty

仅当打包存档包含至少一个对象时才创建它。

--progress

默认情况下,如果标准错误流连接到终端,则会报告进度状态,除非指定了 -q。即使标准错误流未定向到终端,此标志也会强制显示进度状态。

--all-progress

当指定了 --stdout 时,会在对象计数和压缩阶段显示进度报告,但在写入阶段会抑制显示。原因是,在某些情况下,输出流直接链接到另一个命令,该命令可能希望在处理传入的 pack 数据时显示其自身的进度状态。此标志类似于 --progress,但即使使用了 --stdout,它也会强制显示写入阶段的进度报告。

--all-progress-implied

此选项用于在激活进度显示时暗示 --all-progress。与 --all-progress 不同,此标志本身实际上并不强制进行任何进度显示。

-q

此标志使命令不在标准错误流上报告其进度。

--no-reuse-delta

在具有现有包的存储库中创建打包归档文件时,该命令会重用现有的 delta。这有时会导致稍微次优的包。此标志告诉命令不要重用现有的 delta,而是从头开始计算它们。

--no-reuse-object

此标志告诉命令根本不要重用现有的对象数据,包括非 delta 化的对象,强制重新压缩所有内容。这暗示着 --no-reuse-delta。仅在希望对打包数据强制执行不同压缩级别的模糊情况下才有用。

--compression=<n>

指定生成的 pack 中新压缩数据的压缩级别。如果未指定,则首先由 pack.compression 确定 pack 压缩级别,然后由 core.compression 确定,如果两者都未设置,则默认为 -1,即 zlib 默认值。如果要强制对所有数据使用统一的压缩级别,无论其来源如何,请添加 --no-reuse-object。

--[no-]sparse

切换“sparse”算法,以确定在与“--revs”选项结合使用时,要在包中包含哪些对象。此算法仅遍历出现在引入新对象的路径中的树。在计算包以发送少量更改时,这可以带来显着的性能优势。但是,如果包含的提交包含某些类型的直接重命名,则可能会将额外的对象添加到包文件中。如果未包含此选项,则默认值为 pack.useSparse,除非另有说明,否则该值为 true。

--thin

通过省略发送者和接收者之间的公共对象来减少网络传输,从而创建一个“thin”包。此选项仅在与 --stdout 结合使用时才有意义。

注意:thin 包通过省略必需的对象来违反打包的归档文件格式,因此在不使其自包含的情况下,Git 无法使用它。使用 git index-pack --fix-thin(请参阅 git-index-pack[1])来恢复自包含属性。

--shallow

优化将提供给具有浅层存储库的客户端的包。此选项与 --thin 结合使用,可以以速度为代价,从而产生更小的包。

--delta-base-offset

打包的归档文件可以将 delta 的基本对象表示为 20 字节的对象名称,也可以表示为流中的偏移量,但旧版本的 Git 不理解后者。默认情况下,git pack-objects 仅使用前者格式以获得更好的兼容性。此选项允许命令使用后者格式以提高紧凑性。根据平均 delta 链长度,此选项通常会将生成的 packfile 缩小 3-5%。

注意:诸如 git gc(请参阅 git-gc[1]),git repack(请参阅 git-repack[1])之类的 Porcelain 命令在现代 Git 中默认情况下会传递此选项,当它们将对象放入存储库中的 pack 文件时。git bundle(请参阅 git-bundle[1])在创建 bundle 时也会这样做。

--threads=<n>

指定在搜索最佳 delta 匹配时要产生的线程数。这需要使用 pthreads 编译 pack-objects,否则此选项将被忽略并显示警告。这是为了减少多处理器计算机上的打包时间。但是,delta 搜索窗口所需的内存量乘以线程数。指定 0 将导致 Git 自动检测 CPU 的数量并相应地设置线程数。

--index-version=<version>[,<offset>]

这旨在仅由测试套件使用。它允许强制生成的 pack 索引的版本,并强制位于给定偏移量之上的对象的 64 位索引条目。

--keep-true-parents

使用此选项,即使 grafts 隐藏了父对象,仍然对其进行打包。

--filter=<filter-spec>

从生成的 packfile 中省略某些对象(通常是 blob)。有关有效的 <filter-spec> 形式,请参见 git-rev-list[1]

--no-filter

关闭任何先前的 --filter= 参数。

--missing=<missing-action>

一个调试选项,用于帮助将来的“部分克隆”开发。此选项指定如何处理丢失的对象。

--missing=error 形式要求如果遇到丢失的对象,pack-objects 会停止并显示错误。如果存储库是部分克隆,则会在声明它们丢失之前尝试获取丢失的对象。这是默认操作。

--missing=allow-any 形式允许在遇到丢失的对象时继续对象遍历。不会获取丢失的对象。丢失的对象将被默默地从结果中省略。

--missing=allow-promisor 形式类似于 allow-any,但仅允许继续遍历预期(EXPECTED) promisor 丢失的对象。不会获取丢失的对象。意外的丢失对象将引发错误。

--exclude-promisor-objects

省略已知位于 promisor 远程中的对象。(此选项的目的是仅对本地创建的对象进行操作,以便在重新打包时,我们仍然保持本地创建的对象[没有 .promisor]和来自 promisor 远程的对象[具有 .promisor]之间的区别。)这与部分克隆一起使用。

--keep-unreachable

除了未标记为 *.keep 文件的包中的可访问对象之外,还将在结果包中添加从 --unpacked= 选项命名的包中的引用无法访问的对象。这暗示着 --revs

--pack-loose-unreachable

打包无法访问的松散对象(并删除其松散副本)。这暗示着 --revs

--unpack-unreachable

以松散形式保留无法访问的对象。这暗示着 --revs

--delta-islands

根据“岛屿”限制 delta 匹配。请参见下面的 DELTA ISLANDS。

--name-hash-version=<n>

执行 delta 压缩时,Git 根据使用对象路径的启发式方法对可能相似的对象进行分组。虽然按精确路径匹配对对象进行分组对于具有多个版本的路径有利,但在不同的完整路径中查找 delta 对也很有好处。Git 按类型收集对象,然后按路径的“名称哈希”进行收集,然后再按大小进行收集,希望将可以很好地压缩在一起的对象分组在一起。

默认名称哈希版本为 1,它通过将路径的最后几个字节视为为哈希函数提供最大幅度来优先考虑哈希局部性。此版本擅长区分短路径并查找跨目录的重命名。但是,哈希函数主要取决于路径的最后 16 个字节。如果存储库中有许多路径具有相同的最后 16 个字节,并且仅因父目录而异,则此名称哈希可能会导致过多的冲突并导致不良结果。目前,使用 --write-bitmap-index 写入可达性位图文件时,必须使用此版本。

名称哈希版本 2 具有与版本 1 相似的局部性特征,除了它单独考虑每个路径组件并使用移位覆盖哈希。这仍然优先考虑路径的最后几个字节,但也使用父目录名称“salt”哈希的较低位。此方法允许版本 1 的某些局部性优势,同时打破了出现在许多不同目录中的类似名称文件的绝大多数冲突。目前,使用 --write-bitmap-index 写入可达性位图文件时,不允许使用此版本,并且会自动将其更改为版本 1

DELTA ISLANDS

在可能的情况下,pack-objects 会尝试重用现有的磁盘上的 delta,以避免必须即时搜索新的 delta。这对于服务 fetch 而言是一项重要的优化,因为它意味着服务器可以避免膨胀大多数对象,而只需直接从磁盘发送字节。当对象存储为针对接收者没有(并且我们尚未发送)的基对象的 delta 时,此优化不起作用。在这种情况下,服务器会“破坏” delta,并且必须找到一个新的 delta,这会产生很高的 CPU 成本。因此,重要的是磁盘上的 delta 关系中的对象集应与客户端将 fetch 的内容相匹配,这对于性能至关重要。

在正常的存储库中,这往往会自动起作用。这些对象主要是从分支和标签可访问的,而这就是客户端 fetch 的内容。我们在服务器上找到的任何 delta 都可能位于客户端具有或将具有的对象之间。

但是在某些存储库设置中,您可能具有几个相关但独立的 ref tips 组,客户端倾向于独立地 fetch 这些组。例如,假设您在单个共享对象存储中托管存储库的多个“fork”,并允许客户端通过 GIT_NAMESPACE 或使用替代机制的单独存储库将它们视为单独的存储库。一个简单的重新打包可能会发现对象的最佳 delta 是针对仅在另一个 fork 中找到的基对象。但是,当客户端 fetch 时,它们将没有基对象,并且我们必须即时找到一个新的 delta。

如果您在 refs/heads/refs/tags/ 之外有很多指向相关对象的引用(例如,某些托管提供商使用的 refs/pullrefs/changes),则可能存在类似的情况。默认情况下,客户端仅获取 heads 和 tags,并且不能直接发送针对仅在这些其他组中找到的对象的增量。

增量岛通过允许您将引用分组到不同的“岛”中来解决此问题。 Pack-objects 计算哪些对象可以从哪些岛访问,并拒绝从对象 A 创建增量,而该增量的基不在 A 的所有岛中。 这会导致包稍微变大(因为我们会错过一些增量机会),但保证了对一个岛的获取不必由于跨越岛边界而即时重新计算增量。

使用增量岛重新打包时,增量窗口往往会被配置禁止的候选对象阻塞。 使用较大的 --window 重新打包会有所帮助(并且不会像其他情况下那样花费很长时间,因为我们可以在对内容进行任何计算之前,根据岛来拒绝某些对象对)。

岛屿通过 pack.island 选项配置,该选项可以多次指定。 每个值都是一个左锚定的正则表达式,匹配 refnames。 例如

[pack]
island = refs/heads/
island = refs/tags/

将 heads 和 tags 放入一个岛中(其名称为空字符串;有关命名的更多信息,请参见下文)。 任何不匹配这些正则表达式的引用(例如,refs/pull/123)都不在任何岛中。 因此,任何只能从 refs/pull/ 访问的对象(而不是 heads 或 tags)都不能用作 refs/heads/ 的基。

引用根据其“名称”分组到岛中,并且产生相同名称的两个正则表达式被认为在同一个岛中。 这些名称通过连接正则表达式中的任何捕获组来计算,中间用一个 - 短划线分隔。(如果没有捕获组,则名称为空字符串,如上例所示。) 这允许您创建任意数量的岛。 但最多支持 14 个此类捕获组。

例如,假设您将每个 fork 的引用存储在 refs/virtual/ID 中,其中 ID 是一个数字标识符。 然后您可以配置

[pack]
island = refs/virtual/([0-9]+)/heads/
island = refs/virtual/([0-9]+)/tags/
island = refs/virtual/([0-9]+)/(pull)/

这会将每个 fork 的 heads 和 tags 放入它们自己的岛中(命名为 "1234" 或类似名称),并将每个 fork 的 pull 引用放入它们自己的 "1234-pull" 中。

请注意,我们为每个正则表达式选择一个岛屿,使用“最后一个获胜”的排序(这允许存储库特定的配置优先于用户范围内的配置,依此类推)。

配置

各种配置变量会影响打包,请参阅 git-config[1](搜索“pack”和“delta”)。

值得注意的是,增量压缩不用于大于 core.bigFileThreshold 配置变量的对象,也不用于属性 delta 设置为 false 的文件。

GIT

git[1] 套件的一部分

scroll-to-top