Skip to content

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

仅在不经常运行此类 porcelain 命令的情况下向仓库添加对象、进行一次性仓库优化或清理次优的批量导入时,才需要手动运行 git gc。有关导入情况的更多详细信息,请参阅 git-fast-import(1) 中的"包文件优化"部分。

选项

  • --aggressive - 通常 'git gc' 运行非常快,同时提供良好的磁盘空间利用率和性能。此选项将使 'git gc' 以花费更多时间为代价更积极地优化仓库。此优化的效果大多是持久的。有关详细信息,请参阅下面的"激进"部分。

  • --auto - 使用此选项,'git gc' 检查是否需要任何维护;如果不执行任何工作则退出。有关此启发式如何工作的信息,请参阅下面"配置"部分中的 gc.auto 选项。 一旦维护因超过 gc.autogc.autoPackLimit 等配置选项的限制而触发,所有其他维护任务(例如 rerere、工作树、reflog...)也将被执行。

  • --detach, --no-detach - 如果系统支持,在后台运行。此选项覆盖 gc.autoDetach 配置。

  • --cruft, --no-cruft - 过期不可达对象时,将它们单独打包到 cruft 包中而不是作为松散对象存储。--cruft 默认开启。

  • --max-cruft-size=<n> - 将不可达对象打包到 cruft 包时,将新 cruft 包的大小限制为最多 <n> 字节。覆盖通过 gc.maxCruftSize 配置指定的任何值。

  • --expire-to=<dir> - 将不可达对象打包到 cruft 包时,将包含已修剪对象(如果有)的 cruft 包写入目录 <dir>。此选项仅在与 --cruft 一起使用时有效。

  • --prune=<date> - 修剪比日期更旧的松散对象(默认为 2 周前,可由配置变量 gc.pruneExpire 覆盖)。--prune=now 修剪所有松散对象而不考虑其存在时间,如果另一个进程正在同时写入仓库,则增加损坏的风险;请参阅下面的"备注"。--prune 默认开启。

  • --no-prune - 不修剪任何松散对象。

  • --quiet - 禁止所有进度报告。

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

  • --keep-largest-pack - 除了最大的非 cruft 包、任何标记有 .keep 文件的包和任何 cruft 包外,所有包都合并为单个包。使用此选项时,gc.bigPackThreshold 被忽略。

激进

当提供 --aggressive 选项时,将调用 git-repack(1) 并带有 -f 标志,这反过来会将 --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 选项的默认值。

  • gc.aggressiveWindow - 'git gc --aggressive' 使用的增量压缩算法中使用的窗口大小参数。默认为 250,这比默认的 --window 10 更激进。

  • gc.auto - 当仓库中大约有超过此数量的松散对象时,git gc --auto 将打包它们。一些 Porcelain 命令使用此命令不时执行轻量级垃圾回收。默认值为 6700。 将此设置为 0 不仅禁用基于松散对象数量的自动打包,还禁用 git gc --auto 用于确定是否有工作要做的任何其他启发式方法(如 gc.autoPackLimit)。

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

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

  • gc.bigPackThreshold - 如果非零,当运行 git gc 时,所有大于此限制的非 cruft 包将被保留。这与 --keep-largest-pack 非常相似,只是所有满足阈值的非 cruft 包都被保留,而不仅仅是最大的包。默认为零。支持常见的单位后缀 'k'、'm' 或 'g'。

  • gc.writeCommitGraph - 如果为 true,则在运行 git-gc(1) 时 gc 将重写 commit-graph 文件。使用 git gc --auto 时,如果需要维护,commit-graph 将被更新。默认为 true。

  • gc.logExpiry - 如果文件 gc.log 存在,则 git gc --auto 将打印其内容并以状态零退出,除非该文件超过 'gc.logExpiry'。默认为 "1.day"。

  • gc.packRefs - 在仓库中运行 git pack-refs 使其无法通过 HTTP 等哑传输由 1.5.1.2 之前的 Git 版本克隆。此变量决定 'git gc' 是否运行 git pack-refs。这可以设置为 notbare 以在所有非裸仓库中启用,或设置为布尔值。默认为 true

  • gc.cruftPacks - 将不可达对象存储在 cruft 包中(参见 git-repack(1))而不是作为松散对象。默认为 true

  • gc.maxCruftSize - 重新打包时限制新 cruft 包的大小。当与 --max-cruft-size 一起指定时,命令行选项优先。

  • gc.pruneExpire - 运行 'git gc' 时,它将调用 'prune --expire 2.weeks.ago'(以及如果通过 gc.cruftPacks--cruft 使用 cruft 包,则调用 'repack --cruft --cruft-expiration 2.weeks.ago')。使用此配置变量覆盖宽限期。值 "now" 可用于禁用此宽限期并始终立即修剪不可达对象,或 "never" 可用于禁止修剪。

  • gc.worktreePruneExpire - 运行 'git gc' 时,它调用 'git worktree prune --expire 3.months.ago'。此配置变量可用于设置不同的宽限期。

  • gc.reflogExpire, gc.<pattern>.reflogExpire - 'git reflog expire' 删除比此时间更旧的 reflog 条目;默认为 90 天。值 "now" 立即过期所有条目,"never" 完全禁止过期。中间有 "<pattern>"(例如 "refs/stash")时,设置仅适用于匹配 <pattern> 的引用。

  • gc.reflogExpireUnreachable, gc.<pattern>.reflogExpireUnreachable - 'git reflog expire' 删除比此时间更旧且不可从当前提示可达的 reflog 条目;默认为 30 天。

  • gc.recentObjectsHook - 考虑是否删除对象时(无论是生成 cruft 包还是将不可达对象存储为松散对象),使用 shell 执行指定的命令。将其输出解释为对象 ID,Git 将视为"最近的",无论其存在时间如何。

  • gc.repackFilter - 重新打包时,使用指定的过滤器将某些对象移动到单独的包文件中。

  • gc.repackFilterTo - 重新打包并使用过滤器时,指定的位置将用于创建包含过滤出的对象的包文件。警告:指定的位置应该可访问(例如使用 Git 备用机制),否则 Git 可能认为仓库损坏。

  • gc.rerereResolved - 您先前解决的冲突合并的记录在运行 'git rerere gc' 时保留此天数。默认为 60 天。

  • gc.rerereUnresolved - 您未解决的冲突合并的记录在运行 'git rerere gc' 时保留此天数。默认为 15 天。

备注

'git gc' 非常努力地不删除仓库中任何地方引用的对象。特别是,它不仅保留当前分支和标签集引用的对象,还保留索引、远程跟踪分支、reflog(可能引用后来被修改或回绕的分支中的提交)以及 refs/* 命名空间中的任何其他内容引用的对象。请注意,附加到对象的注释(由 'git notes' 创建的那种)不会有助于保持对象存活。如果您期望某些对象被删除但它们没有被删除,请检查所有这些位置并确定在您的情况下删除这些引用是否有意义。

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

  1. 修改时间比 --prune 日期更新的任何对象都会被保留,以及从它可达的所有内容。
  2. 大多数向数据库添加对象的操作都会更新对象的修改时间(如果已存在),以便 #1 适用。

但是,这些功能并不构成完整的解决方案,因此并发运行命令的用户必须承受一些损坏的风险(在实践中似乎很低)。

钩子

'git gc --auto' 命令将运行 'pre-auto-gc' 钩子。有关更多信息,请参阅 githooks(5)

另请参阅

git-prune(1)git-reflog(1)git-repack(1)git-rerere(1)

Git

git(1) 套件的一部分

基于 CC BY-NC-SA 3.0 许可发布