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

名称

git-gc - 清理无用文件并优化本地仓库

概要

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

描述

在当前仓库中运行一系列内务管理任务,例如压缩文件修订版本(以减少磁盘空间并提高性能)、删除可能由之前的 git add 调用创建的不可达对象、打包引用、清理引用日志 (reflog)、rerere 元数据或过期的工作树。还可能更新辅助索引,例如提交图 (commit-graph)。

当运行创建对象的常见上层 (porcelain) 操作时,它们会检查仓库自上次维护以来是否显著增长,如果是,则自动运行 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、工作树、reflog 等)也将被执行。

--detach
--no-detach

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

--cruft
--no-cruft

在清理不可达对象时,将它们单独打包成一个废弃包 (cruft pack),而不是将其存储为松散对象。--cruft 默认开启。

--max-cruft-size=<n>

在将不可达对象打包到废弃包中时,限制新废弃包的大小最多为 <n> 字节。覆盖通过 gc.maxCruftSize 配置指定的任何值。更多信息请参阅 git-repack[1]--max-cruft-size 选项。

--expire-to=<dir>

在将不可达对象打包到废弃包中时,将包含已修剪对象(如果有)的废弃包写入目录 <dir>。此选项仅在与 --cruft 连用时生效。更多信息请参阅 git-repack[1]--expire-to 选项。

--prune=<date>

修剪早于指定日期的松散对象(默认为 2 周前,可通过配置变量 gc.pruneExpire 覆盖)。--prune=now 会修剪所有松散对象,无论其存续时间长短,并且如果另一个进程同时向仓库写入,则会增加损坏风险;请参阅下文的“注意”。--prune 默认开启。

--no-prune

不修剪任何松散对象。

--quiet

不显示所有进度报告。

--force

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

--keep-largest-pack

除最大的非废弃包、任何标有 .keep 文件的包以及任何废弃包之外,所有包都合并为一个包。使用此选项时,将忽略 gc.bigPackThreshold

AGGRESSIVE (激进优化)

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

这种影响大多是持久的,例如,当包和松散对象合并到另一个包中时,该包中的现有增量可能会被重新利用,但也存在各种情况,我们可能会从较新的包中选择次优的增量。

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

在没有对给定仓库运行量身定制的性能基准测试的情况下,使用此选项可能并不值得。它需要更多的时间,而且产生的空间/增量优化可能值得也可能不值得。对于大多数用户及其仓库来说,完全不使用它是正确的折衷方案。

配置

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

gc.aggressiveDepth

git gc --aggressive 使用的增量压缩算法中的深度参数。默认值为 50,这也是不使用 --aggressive--depth 选项的默认值。

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

gc.aggressiveWindow

git gc --aggressive 使用的增量压缩算法中的窗口大小参数。默认值为 250,这比默认的 --window 值 10 要激进得多。

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

gc.auto

当仓库中大约有超过此数量的松散对象时,git gc --auto 将打包它们。一些上层命令使用此命令不时执行轻量级垃圾回收。默认值为 6700。

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

gc.autoPackLimit

当仓库中没有标有 *.keep 文件的包超过此数量时,git gc --auto 会将它们合并为一个较大的包。默认值为 50。将其设置为 0 可禁用它。将 gc.auto 设置为 0 也会禁用此功能。

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

gc.autoDetach

如果系统支持,使 git gc --auto 立即返回并在后台运行。默认值为 true。此配置变量作为未设置 maintenance.autoDetach 时的备选项。

gc.bigPackThreshold

如果非零,则在运行 git gc 时保留所有大于此限制的非废弃包。这与 --keep-largest-pack 非常相似,不同之处在于保留所有满足阈值的非废弃包,而不仅仅是最大的包。默认为零。支持常用的单位后缀 kmg

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

如果无法获得使 git repack 顺利运行所需的估计内存量,且未设置 gc.bigPackThreshold,则最大的包也将被排除(这相当于运行带有 --keep-largest-packgit gc)。

gc.writeCommitGraph

如果为 true,则在运行 git-gc[1] 时,gc 将重写提交图文件。使用 git gc --auto 时,如果需要进行内务管理,提交图将被更新。默认值为 true。详情请参阅 git-commit-graph[1]

gc.logExpiry

如果文件 gc.log 存在,那么 git gc --auto 将打印其内容并以状态码零退出而不运行,除非该文件的存续时间超过 gc.logExpiry。默认值为 "1.day"。请参阅 gc.pruneExpire 以了解更多指定其值的方法。

gc.packRefs

在仓库中运行 git pack-refs 会导致 1.5.1.2 之前的 Git 版本无法通过 HTTP 等哑传输协议克隆该仓库。此变量决定 git gc 是否运行 git pack-refs。可以将其设置为 notbare 以在所有非纯 (non-bare) 仓库中启用它,也可以将其设置为布尔值。默认值为 true

gc.cruftPacks

将不可达对象存储在废弃包中(参见 git-repack[1]),而不是作为松散对象存储。默认值为 true

gc.maxCruftSize

重新打包时限制新废弃包的大小。如果同时指定了 --max-cruft-size,则命令行选项优先。请参阅 git-repack[1]--max-cruft-size 选项。

gc.pruneExpire

运行 git gc 时,它将调用 prune --expire 2.weeks.ago(如果通过 gc.cruftPacks--cruft 使用废弃包,则调用 repack --cruft --cruft-expiration 2.weeks.ago)。使用此配置变量可以覆盖宽限期。值 "now" 可用于禁用此宽限期并始终立即修剪不可达对象,"never" 可用于抑制修剪。此功能有助于防止 git gc 与另一个写入仓库的进程并发运行时发生损坏;请参阅 git-gc[1] 的“注意”部分。

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 删除早于此时间且从当前末梢 (tip) 不可达的引用日志条目;默认为 30 天。值 "now" 会立即使所有条目过期,"never" 则完全抑制过期。中间带有 "<pattern>"(例如 "refs/stash")时,该设置仅适用于与 <pattern> 匹配的引用。

这些类型的条目通常是由于使用 git commit --amendgit rebase 而创建的,是在进行修正或变基之前的提交。由于这些更改不属于当前项目,大多数用户希望它们更快过期,这就是为什么默认值比 gc.reflogExpire 更激进的原因。

gc.recentObjectsHook

在考虑是否删除对象时(无论是生成废弃包还是将不可达对象存储为松散对象),使用 shell 执行指定的命令。将其输出解释为 Git 将视为“近期”的对象 ID,无论其存续时间长短。通过将其修改时间 (mtime) 视为“现在”,输出中提到的任何对象(及其后代)都将被保留,而不管其实际存续时间。

输出必须每行包含且仅包含一个十六进制对象 ID。在仓库中找不到的对象将被忽略。支持多个钩子,但所有钩子都必须成功退出,否则操作(生成废弃包或解包不可达对象)将被停止。

gc.repackFilter

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

gc.repackFilterTo

在重新打包并使用过滤器时(参见 gc.repackFilter),指定的位置将用于创建包含过滤掉的对象的包文件。警告: 指定的位置应该是可访问的(例如使用 Git 的 alternates 机制),否则 Git 可能会因为无法访问该包文件中的对象而认为仓库已损坏。请参阅 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 钩子。更多信息请参阅 githooks[5]

GIT

Git[1] 套件的一部分