git-pack-objects
创建对象的打包归档。
概要
'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>] [--path-walk] < <object-list>描述
从标准输入读取对象列表,并将一个或多个具有指定基本名称的打包归档写入磁盘,或将打包归档写入标准输出。
打包归档是在两个仓库之间传输一组对象集合的有效方式,也是一种访问高效的归档格式。在打包归档中,对象要么存储为压缩的整体,要么存储为与某个其他对象的差异。后者通常称为增量。
打包归档格式(.pack)设计为自包含的,因此可以在没有任何额外信息的情况下解包。因此,增量所依赖的每个对象必须存在于包中。
为包中的对象生成包索引文件(.idx)以实现快速随机访问。将索引文件(.idx)和打包归档(.pack)都放在 $GIT_OBJECT_DIRECTORY(或 $GIT_ALTERNATE_OBJECT_DIRECTORIES 上的任何目录)的 pack/ 子目录中,使 Git 能够从包归档中读取。
'git unpack-objects' 命令可以读取打包归档并将包中包含的对象展开为"一个文件一个对象"格式;这通常由智能拉取命令在对等方动态创建包以实现高效网络传输时完成。
选项
base-name
:写入文件对(.pack 和 .idx),使用 <base-name> 确定创建文件的名称。使用此选项时,一对中的两个文件写入 <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[=<mode>]
:从标准输入读取包文件的基本名称(例如 pack-1234abcd.pack),而不是对象名称或修订参数。结果包包含列出的包中所有对象(不以 ^ 开头的),排除排除包中列出的任何对象(以 ^ 开头的)。 当 mode 为 "follow" 时,包可以额外以 ! 为前缀,表示它们被排除但在可达性下不一定封闭。除了包含包中的对象外,结果包可能包含基于以下内容的额外对象:
- 如果任何包标记为
!,则从此类包或包含的包通过排除封闭包外部的对象可达的对象将被包含。在这种情况下,所有^包在可达性下被视为封闭。 - 否则(如果没有
!包),如果未列出包中的对象 (1) 从包含的包可达,且 (2) 未在任何排除包中找到,则这些对象将被包含。 此模式很有用,例如,用于恢复在 cruft 包中发现的曾经不可达的对象,以生成在排除包设置的边界下可达性封闭的包。 与--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>:这两个选项影响包中包含的对象如何使用增量压缩存储。对象首先按类型、大小和可选名称在内部排序,并与 --window 内的其他对象进行比较,看使用增量压缩是否节省空间。--depth 限制最大增量深度;使其过深会影响解包器端的性能,因为增量数据需要应用那么多次才能到达必要的对象。 --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 时,进度报告在对象计数和压缩阶段显示,但在写出阶段被抑制。原因是某些情况下输出流直接链接到另一个命令,该命令可能希望在处理传入包数据时显示自己的进度状态。此标志类似于 --progress,只是即使使用了 --stdout,它也强制在写出阶段进行进度报告。
--all-progress-implied
:用于在激活进度显示时隐含 --all-progress。与 --all-progress 不同,此标志本身实际上不强制任何进度显示。
-q
:此标志使命令不向标准错误流报告其进度。
--no-reuse-delta
:在具有现有包的仓库中创建打包归档时,命令会重用现有增量。这有时会导致稍微次优的包。此标志告诉命令不重用现有增量,而是从头开始计算它们。
--no-reuse-object
:此标志告诉命令完全不重用现有对象数据,包括非增量对象,强制重新压缩所有内容。这隐含 --no-reuse-delta。仅在需要对打包数据强制执行不同压缩级别的晦涩情况下有用。
--compression=<n>
:指定生成包中新压缩数据的压缩级别。如果未指定,包压缩级别首先由 pack.compression 确定,然后由 core.compression 确定,如果都未设置则默认为 -1(zlib 默认值)。如果您想强制对所有数据统一压缩级别而不考虑来源,请添加 --no-reuse-object。
--sparse
、--no-sparse:与 "--revs" 选项组合时,切换 "sparse" 算法以确定要包含在包中的对象。此算法仅遍历引入新对象的路径中出现的树。在计算要发送小更改的包时,这可以带来显著的性能优势。但是,如果包含的提交包含某些类型的直接重命名,则可能向包文件添加额外的对象。如果未包含此选项,则默认为 pack.useSparse 的值,除非另有指定,否则为 true。
--thin
:通过省略发送方和接收方之间的公共对象来创建"薄"包,以减少网络传输。此选项仅在与 --stdout 结合使用时有意义。 注意:薄包通过省略必需对象违反了打包归档格式,因此 Git 无法使用它而不使其自包含。使用 git index-pack --fix-thin(参见 git-index-pack(1))恢复自包含属性。
--shallow
:优化将提供给具有浅层仓库的客户端的包。此选项与 --thin 结合使用,可以以速度为代价产生更小的包。
--delta-base-offset
:打包归档可以将增量的基础对象表示为 20 字节的对象名称或流中的偏移量,但旧版本的 Git 不理解后者。默认情况下,'git pack-objects' 仅使用前者格式以获得更好的兼容性。此选项允许命令使用后者格式以获得紧凑性。根据平均增量链长度,此选项通常将结果包文件缩小 3-5%。 注意:Porcelain 命令如 git gc(参见 git-gc(1))、git repack(参见 git-repack(1))在现代 Git 中将对象放入包文件时默认传递此选项。git bundle(参见 git-bundle(1))在创建 bundle 时也是如此。
--threads=<n>
:指定搜索最佳增量匹配时要生成的线程数。这要求 pack-objects 使用 pthreads 编译,否则此选项将被忽略并发出警告。这旨在减少多处理器机器上的打包时间。但是,增量搜索窗口所需的内存量乘以线程数。指定 0 将导致 Git 自动检测 CPU 数量并相应设置线程数。
--index-version=<version>[,<offset>]
:这仅供测试套件使用。它允许强制生成的包索引的版本,并强制对位于给定偏移量之上的对象使用 64 位索引条目。
--keep-true-parents
:使用此选项时,被 grafts 隐藏的父提交仍然会被打包。
--filter=<filter-spec>
:从结果包文件中省略某些对象(通常是 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',但仅允许对预期的 promisor 缺失对象继续对象遍历。不会获取缺失对象。意外的缺失对象将引发错误。
--exclude-promisor-objects
:省略已知在 promisor 远程中的对象。(此选项的目的是仅对本地创建的对象进行操作,以便在重新打包时,我们仍然保持本地创建的对象 [没有 .promisor] 和来自 promisor 远程的对象 [有 .promisor] 之间的区别。)这与部分克隆一起使用。
--keep-unreachable
:从 --unpacked= 选项命名的包中的引用不可达的对象被添加到结果包中,除了未被 *.keep 文件标记的包中的可达对象。这隐含 --revs。
--pack-loose-unreachable
:打包不可达的松散对象(并移除其松散副本)。这隐含 --revs。
--unpack-unreachable
:保持不可达对象为松散形式。这隐含 --revs。
--delta-islands
:基于"岛"限制增量匹配。请参阅下面的增量岛。
--name-hash-version=<n>
:在执行增量压缩时,Git 根据使用该对象路径的启发式方法将可能相似的对象分组。虽然按精确路径匹配分组对具有多个版本的路径有益,但在不同完整路径之间查找增量对也有好处。Git 按类型收集对象,然后按路径的"名称哈希",然后按大小,期望将压缩效果良好的对象分组在一起。 默认名称哈希版本为 1,通过考虑路径的最后字节为哈希函数提供最大幅度来优先考虑哈希局部性。此版本擅长区分短路径和跨目录查找重命名。但是,哈希函数主要依赖于路径的最后 16 字节。如果仓库中有许多路径具有相同的最后 16 字节且仅在父目录上不同,则此名称哈希可能导致过多冲突并导致结果不佳。目前,在使用 --write-bitmap-index 写入可达性位图文件时需要此版本。 名称哈希版本 2 具有与版本 1 类似的局部性特征,只是它分别考虑每个路径组件并用移位覆盖哈希。这仍然优先考虑路径的最后字节,但也使用父目录名称"加盐"哈希的低位。此方法允许版本 1 的一些局部性优势,同时打破了在许多不同目录中出现类似命名文件的大部分冲突。目前,在使用 --write-bitmap-index 写入可达性位图文件时不允许此版本,它将自动更改为版本 1。
--path-walk
:首先按路径组织对象进行压缩,然后进行第二遍跨路径的正常压缩。这有可能改善增量压缩,特别是在存在导致 Git 默认名称哈希算法冲突的文件名时。 与 --delta-islands、--shallow 或 --filter 不兼容。在存在 --path-walk 时,--use-bitmap-index 选项将被忽略。
增量岛
在可能的情况下,pack-objects 尝试重用现有的磁盘增量以避免必须动态搜索新的增量。这对于服务获取是一个重要的优化,因为这意味着服务器可以完全避免膨胀大多数对象,只直接从磁盘发送字节。当对象存储为接收方没有(且我们尚未发送)的基础的增量时,此优化无法工作。在这种情况下,服务器"打破"增量并必须找到新的增量,这具有很高的 CPU 成本。因此,对于性能而言,磁盘增量关系中的对象集与客户端将获取的内容匹配非常重要。
在普通仓库中,这往往会自动工作。对象大多从分支和标签可达,这就是客户端获取的内容。我们在服务器上找到的任何增量很可能在客户端已有或将有的对象之间。
但在某些仓库设置中,您可能有几个相关但独立的引用提示组,客户端倾向于独立获取这些组。例如,想象一下,您在单个共享对象存储中托管仓库的多个"分支",并通过 GIT_NAMESPACE 或使用 alternates 机制的单独仓库让客户端将它们视为单独的仓库。朴素的重新打包可能会发现对象的最佳增量是针对仅在另一个分支中找到的基础。但当客户端获取时,它们将没有基础对象,我们将不得不动态找到新的增量。
如果您有许多在 refs/heads/ 和 refs/tags/ 之外指向相关对象的引用(例如 refs/pull 或某些托管提供商使用的 refs/changes),也可能存在类似情况。默认情况下,客户端仅获取头和标签,针对仅在这些其他组中找到的对象的增量无法按原样发送。
增量岛通过允许您将引用分组为不同的"岛"来解决此问题。Pack-objects 计算哪些对象从哪些岛可达,并拒绝从对象 A 到不存在于 A 所有岛中的基础创建增量。这导致稍大的包(因为我们错过了一些增量机会),但保证获取一个岛不会由于跨越岛边界而动态重新计算增量。
使用增量岛重新打包时,增量窗口往往会被配置禁止的候选项阻塞。使用大的 --window 重新打包有帮助(并且不会花费通常那么长的时间,因为我们可以在对内容进行任何计算之前基于岛拒绝一些对象对)。
岛通过 pack.island 选项配置,可以多次指定。每个值是匹配引用名的左锚定正则表达式。例如:
[pack]
island = refs/heads/
island = refs/tags/将头和标签放入一个岛(其名称为空字符串;有关命名的更多信息见下文)。任何不匹配这些正则表达式的引用(例如 refs/pull/123)不在任何岛中。因此,任何仅从 refs/pull/ 可达(但不是头或标签)的对象不能用作 refs/heads/ 的基础候选项。
引用根据它们的"名称"分组到岛中,产生相同名称的两个正则表达式被视为在同一个岛中。名称通过连接正则表达式中的任何捕获组(以 '-' 破折号分隔)从正则表达式计算。(如果没有捕获组,则名称为空字符串,如上例所示。)这允许您创建任意数量的岛。但仅支持最多 14 个这样的捕获组。
例如,想象您将每个分支的引用存储在 refs/virtual/ID 中,其中 ID 是数字标识符。然后您可以配置:
[pack]
island = refs/virtual/([0-9]+)/heads/
island = refs/virtual/([0-9]+)/tags/
island = refs/virtual/([0-9]+)/(pull)/这将每个分支的头和标签放入它们自己的岛(命名为 "1234" 或类似),每个的拉取引用放入它们自己的 "1234-pull"。
请注意,我们使用"最后获胜"的排序为每个正则表达式选择一个岛(这允许仓库特定配置优先于用户范围配置,等等)。
配置
各种配置变量影响打包,请参阅 git-config(1)(搜索 "pack" 和 "delta")。
值得注意的是,增量压缩不用于大于 core.bigFileThreshold 配置变量的对象以及 delta 属性设置为 false 的文件。
另请参阅
git-rev-list(1)、git-repack(1)、git-prune-packed(1)
Git
git(1) 套件的一部分
