简体中文 ▾ 主题 ▾ 最新版本 ▾ git-gc 最后更新于 2.52.0

名称

git-gc - 清理不必要的文件并优化本地仓库

概要

git gc [--aggressive] [--auto] [--[no-]detach] [--quiet] [--prune=<date> | --no-prune] [--force] [--keep-largest-pack]

描述

在当前仓库中执行一系列的维护任务,例如压缩文件修订(以减少磁盘空间并提高性能)、删除可能由先前调用git add创建的无法访问的对象、打包引用、修剪引用日志、rerere 元数据或过时的暂存区。还可能更新辅助索引,如提交图 (commit-graph)。

当运行创建对象的常用外部命令时,它们会检查自上次维护以来仓库是否已大幅增长,如果增长则会自动运行 git gc。有关如何禁用此行为,请参阅下面的 gc.auto

只有在不定期运行此类外部命令的情况下向仓库添加对象、进行一次性仓库优化、或例如清理不理想的大规模导入时,才需要手动运行 git gc。有关导入情况的更多详细信息,请参阅 git-fast-import[1] 的“PACKFILE OPTIMIZATION”部分。

选项

--aggressive

通常 git gc 运行速度很快,同时提供良好的磁盘空间利用率和性能。此选项将导致 git gc 更积极地优化仓库,但代价是花费更多的时间。此优化的效果大部分是持久的。有关详细信息,请参阅下面的“AGGRESSIVE”部分。

--auto

使用此选项,git gc 会检查是否需要任何维护;如果不需要,它将退出而不执行任何工作。

有关此启发式方法如何工作,请参阅下面的“CONFIGURATION”部分的 gc.auto 选项。

一旦通过超过 gc.autogc.autoPackLimit 等配置选项的限制触发了维护,所有其他维护任务(例如 rerere、暂存区、引用日志……)也将被执行。

--detach
--no-detach

如果系统支持,则在后台运行。此选项将覆盖 gc.autoDetach 配置。

--cruft
--no-cruft

在过期无法访问对象时,将它们单独打包到 cruft pack 中,而不是作为松散对象存储。 --cruft 默认启用。

--max-cruft-size=<n>

在将无法访问的对象打包到 cruft pack 时,将新的 cruft pack 的大小限制在最多 <n> 字节。将覆盖通过 gc.maxCruftSize 配置指定的任何值。有关更多信息,请参阅 git-repack[1]--max-cruft-size 选项。

--expire-to=<dir>

在将无法访问的对象打包到 cruft pack 时,将包含已修剪对象(如果有)的 cruft pack 写入目录 <dir>。此选项仅与 --cruft 一起使用时才有效。有关更多信息,请参阅 git-repack[1]--expire-to 选项。

--prune=<date>

修剪早于指定日期的松散对象(默认为 2 周前,可通过配置变量 gc.pruneExpire 覆盖)。 --prune=now 无论年龄如何都修剪松散对象,并且在另一个进程正在并发写入仓库时会增加损坏的风险;请参阅下面的“NOTES”。 --prune 默认启用。

--no-prune

不修剪任何松散对象。

--quiet

抑制所有进度报告。

--force

强制 git gc 运行,即使可能存在另一个 git gc 实例正在此仓库上运行。

--keep-largest-pack

除了最大的非 cruft pack、任何带有 .keep 文件的 pack 以及任何 cruft pack(s) 之外,所有 pack 都会被合并到一个 pack 中。使用此选项时,将忽略 gc.bigPackThreshold

AGGRESSIVE

当提供了 --aggressive 选项时,git-repack[1] 将以 -f 标志调用,该标志又会将 --no-reuse-delta 传递给 git-pack-objects[1]。这将丢弃任何现有的 delta 并重新计算它们,代价是花费更多时间重新打包。

这些优化的效果大部分是持久的,例如,当 pack 和松散对象合并到另一个 pack 时,该 pack 中现有的 delta 可能会被重用,但在某些情况下,我们可能会从较新的 pack 中选择一个次优的 delta。

此外,提供 --aggressive 将调整传递给 git-repack[1]--depth--window 选项。请参阅下面的 gc.aggressiveDepthgc.aggressiveWindow 设置。通过使用更大的窗口大小,我们更有可能找到更优的 delta。

在对给定仓库运行定制的性能基准测试之前,使用此选项可能不值得。它花费的时间更长,并且产生的空间/delta 优化可能值得,也可能不值得。大多数用户及其仓库选择不使用此选项是正确的权衡。

配置

本节中以下所有内容均从 git-config[1] 文档中选择性地包含。内容与彼处相同:

gc.aggressiveDepth

git gc --aggressive 使用的 delta 压缩算法的深度参数。默认值为 50,当未使用 --aggressive 时,这是 --depth 选项的默认值。

有关更多详细信息,请参阅 git-repack[1]--depth 选项的文档。

gc.aggressiveWindow

git gc --aggressive 使用的 delta 压缩算法的窗口大小参数。默认值为 250,这是一个比默认的 --window 10 更具侵略性的窗口大小。

有关更多详细信息,请参阅 git-repack[1]--window 选项的文档。

gc.auto

当仓库中存在大约多于此数量的松散对象时,git gc --auto 会将它们打包。一些外部命令会使用此命令来不时执行轻量级的垃圾回收。默认值为 6700。

将其设置为 0 不仅禁用了基于松散对象数量的自动打包,还禁用了 git gc --auto 将用于确定是否有工作要做的任何其他启发式方法,例如 gc.autoPackLimit

gc.autoPackLimit

当仓库中存在多于此数量的未被 *.keep 文件标记的 pack 时,git gc --auto 会将它们合并为一个更大的 pack。默认值为 50。将其设置为 0 将禁用它。将 gc.auto 设置为 0 也会禁用此项。

参阅下面的 gc.bigPackThreshold 配置变量。当使用时,它将影响自动 pack 限制的工作方式。

gc.autoDetach

使 git gc --auto 立即返回并在系统支持的情况下在后台运行。默认值为 true。此配置变量充当回退,以防 maintenance.autoDetach 未设置。

gc.bigPackThreshold

如果非零,则在运行 git gc 时,所有大于此限制的非 cruft pack 都将被保留。这与 --keep-largest-pack 非常相似,只是所有符合阈值的非 cruft pack 都被保留,而不仅仅是最大的 pack。默认为零。支持 kmg 的常用单位后缀。

请注意,如果保留的 pack 数量超过 gc.autoPackLimit,则将忽略此配置变量,除了基本 pack 之外的所有 pack 都将重新打包。之后,pack 的数量应低于 gc.autoPackLimit,并且将再次尊重 gc.bigPackThreshold。

如果估计的 git repack 顺利运行所需的内存量不可用且未设置 gc.bigPackThreshold,那么最大的 pack 也将被排除(这相当于使用 --keep-largest-pack 运行 git gc)。

gc.writeCommitGraph

如果为 true,则 gc 在 git-gc[1] 运行时将重写 commit-graph 文件。在使用 git gc --auto 时,如果需要维护,commit-graph 将被更新。默认值为 true。有关详细信息,请参阅 git-commit-graph[1]

gc.logExpiry

如果 gc.log 文件存在,则 git gc --auto 将打印其内容并以状态零退出,除非该文件比 gc.logExpiry 更旧。默认值为“1.day”。有关指定其值的更多方法,请参阅 gc.pruneExpire

gc.packRefs

在仓库中运行 git pack-refs 会使其被 Git 版本早于 1.5.1.2 的通过哑传输(如 HTTP)克隆。此变量决定 git gc 是否运行 git pack-refs。可以将其设置为 notbare 以在所有非裸仓库中启用它,或者可以将其设置为布尔值。默认值为 true

gc.cruftPacks

将无法访问的对象存储在 cruft pack 中(请参阅 git-repack[1]),而不是作为松散对象。默认值为 true

gc.maxCruftSize

重新打包时限制新的 cruft pack 的大小。当与 --max-cruft-size 一起指定时,命令行选项优先。请参阅 git-repack[1]--max-cruft-size 选项。

gc.pruneExpire

当运行 git gc 时,它将调用 prune --expire 2.weeks.ago(如果使用 cruft pack(通过 gc.cruftPacks--cruft)),则还会调用 repack --cruft --cruft-expiration 2.weeks.ago)。使用此配置变量覆盖宽限期。值“now”可用于禁用此宽限期并立即修剪无法访问的对象,或使用“never”来抑制修剪。此功能有助于防止 git gc 与另一个正在写入仓库的进程并发运行时发生损坏;请参阅 git-gc[1] 的“NOTES”部分。

gc.worktreePruneExpire

当运行 git gc 时,它会调用 git worktree prune --expire 3.months.ago。此配置变量可用于设置不同的宽限期。值“now”可用于禁用宽限期并立即修剪 $GIT_DIR/worktrees,或使用“never”来抑制修剪。

gc.reflogExpire
gc.<pattern>.reflogExpire

git reflog expire 会删除早于此时间(默认为 90 天)的引用日志条目。值“now”会立即过期所有条目,“never”会完全抑制过期。在中间使用“<pattern>”(例如“refs/stash”)时,设置仅适用于匹配 <pattern> 的引用。

gc.reflogExpireUnreachable
gc.<pattern>.reflogExpireUnreachable

git reflog expire 会删除早于此时间且无法从当前尖端到达的引用日志条目(默认为 30 天)。值“now”会立即过期所有条目,“never”会完全抑制过期。在中间使用“<pattern>”(例如“refs/stash”)时,设置仅适用于匹配 <pattern> 的引用。

这些类型的条目通常是使用 git commit --amendgit rebase 的结果,并且是发生在修改或 rebase 之前的提交。由于这些更改不是当前项目的一部分,大多数用户希望更早地过期它们,因此默认设置比 gc.reflogExpire 更具侵略性。

gc.recentObjectsHook

在考虑是否删除某个对象时(无论是生成 cruft pack 还是将无法访问的对象存储为松散对象),使用 shell 执行指定的命令。将其输出解释为 Git 将视为“最近”的对象 ID,无论其年龄如何。通过将它们的 mtime 视为“现在”,任何在输出中提及的对象(及其后代)都将被保留,而不管其真实年龄。

输出必须每行包含一个十六进制对象 ID,并且别无其他。仓库中找不到的对象将被忽略。支持多个 hook,但所有 hook 都必须成功退出,否则操作(生成 cruft pack 或解包无法访问的对象)将中止。

gc.repackFilter

在重新打包时,使用指定的过滤器将某些对象移动到单独的 packfile 中。请参阅 git-repack[1]--filter=<filter-spec> 选项。

gc.repackFilterTo

在重新打包并使用过滤器(请参阅 gc.repackFilter)时,指定的目录将用于创建包含过滤掉的对象(即被过滤出去的对象)的 packfile。警告: 指定的目录应可访问,例如使用 Git 的 alternate 机制,否则 Git 可能会将仓库视为已损坏,因为它可能无法访问该 packfile 中的对象。请参阅 git-repack[1]--filter-to=<dir> 选项以及 gitrepository-layout[5]objects/info/alternates 部分。

gc.rerereResolved

在运行 git rerere gc 时,您之前解决的冲突合并记录将保留此天数。您也可以使用更易读的“1.month.ago”等格式。默认为 60 天。请参阅 git-rerere[1]

gc.rerereUnresolved

在运行 git rerere gc 时,您尚未解决的冲突合并记录将保留此天数。您也可以使用更易读的“1.month.ago”等格式。默认为 15 天。请参阅 git-rerere[1]

注意事项

git gc 会尽最大努力不删除在您的仓库中任何地方被引用的对象。特别地,它不仅会保留由您当前分支和标签集引用的对象,还会保留由索引、远程跟踪分支、引用日志(可能引用后来被修改或回滚的分支中的提交)以及 refs/* 命名空间中的任何其他内容引用的对象。请注意,附加到对象的注释(由 git notes 创建的类型)不会影响对象的生命周期。如果您期望某些对象被删除但未删除,请检查所有这些位置,并决定在您的场景下删除这些引用是否有意义。

另一方面,当 git gc 与另一个进程并发运行时,存在删除另一个进程正在使用但尚未创建引用的对象的风险。这可能会导致另一个进程失败,或者如果另一个进程稍后向已删除对象添加引用,则可能导致仓库损坏。Git 有两个功能可以显著缓解此问题:

  1. 任何修改时间比 --prune 日期新的对象,以及从它可达的所有对象,都将被保留。

  2. 大多数将对象添加到数据库的操作会更新对象(如果它已存在)的修改时间,以便应用 #1。

然而,这些功能并未提供完整的解决方案,因此并发运行命令的用户必须承担一定的损坏风险(尽管在实践中风险似乎很低)。

钩子

git gc --auto 命令将运行 pre-auto-gc hook。有关更多信息,请参阅 githooks[5]

GIT

Git[1] 套件的一部分