【问题标题】:How can I know if `git gc --auto` has done something?我怎么知道`git gc --auto`是否做了什么?
【发布时间】:2017-07-31 22:31:58
【问题描述】:

我正在运行 git gc --auto 作为自动保存脚本的一部分。如果git gc --auto 做了一些事情,我想进行进一步的清理,但如果git gc --auto 觉得不需要做某事,我想省去麻烦。有没有办法检查git gc --auto的返回值,或者提前检查是否需要运行?

【问题讨论】:

  • 简短的回答是“不”。更长的答案是:你到底会做什么?无论您会做什么(检查 reflog 计数?),您都可以这样做并查看它们是否已更改。不过,一开始就很难等待自动 GC。你会想要一个显式的、非自动的 GC,这样你就可以知道它什么时候完成了。
  • 我想真正的问题是我正在使用带有非常非常大的存储库的 git,有时 git gc --auto 会失败(磁盘空间或 oomkiller)并留下可以用 @987654326 处理的东西@,这很好地填满了磁盘。我想我可以系统地运行git pack-redundant 吗?
  • 啊。理想情况下,您希望监控故障(我不确定 Linux 是否有合适的进程跟踪来执行此操作),否则您确实可以偶尔进行一次包冗余检查。

标签: git


【解决方案1】:

2020 年 9 月更新:您不必只运行 git gc --auto 作为自动保存脚本的一部分。

旧的“gc”现在可以被新的git maintenance run --auto取代。
它可以显示它在做什么。

随着 Git 2.29(2020 年第四季度),A “git gc(man) 的大哥被引入负责更多的存储库维护任务,不限于对象数据库清理。

commit 25914c4commit 4ddc79bcommit 916d062commit 65d655bcommit d7514f6commit 090511bcommit 663b2b1commit 3103e98commit 3103e98commit 3103e98commit a95ce12commit 3ddaad0、@397654332@(178643332@, 2020 年)Derrick Stolee (derrickstolee)
(由 Junio C Hamano -- gitster --commit 48794ac 中合并,2020 年 9 月 25 日)

maintenance: 创建基本维护运行器

帮助者:Jonathan Nieder
签名者:Derrick Stolee

'gc' 内置是我们当前用于自动维护存储库的入口点。这个工具做了很多操作,例如:

  • 重新打包存储库,
  • 包装参考,以及
  • 重写提交图文件。

顾名思义它执行“垃圾收集”,这意味着几个不同的东西,有些用户可能不想使用这个重写整个对象数据库的操作。

创建一个新的 'maintenance' 内置命令,它将成为更通用的命令。

一开始它只支持'run'子命令,但稍后会扩展以添加用于在后台安排维护的子命令。

目前,“maintenance”内置函数是“gc”内置函数的薄垫片。
事实上,唯一的选择是“--auto”切换,它直接交给了“gc”内置。
当前的更改与这个简单的操作隔离,以防止在添加新内置函数的所有样板中丢失更多有趣的逻辑。

使用现有的builtin/gc.c 文件,因为我们想在两个内置函数之间共享代码。
我们可能会在某个时候让 'maintenance' 完全替换 'gc' 内置函数,留下 'git gc(man)' 作为某些特定参数的别名到'git maintenance run'。

创建一个新的test_subcommand 帮助器,它允许我们测试某个子命令是否已运行。它需要将GIT_TRACE2_EVENT 日志存储在一个文件中。
可以使用否定模式,将在以后的测试中使用。

(最后一部分是确定新的git maintainance run --auto 做某事的一种方法)

git maintenance 现在包含在其man page 中:

git-维护(1)

姓名

git-maintenance - 运行任务以优化 Git 存储库数据

概要

[verse]
'git maintenance' run [<options>]

说明

运行任务以优化 Git 存储库数据,加速其他 Git 命令 并减少存储库的存储需求。

添加存储库数据的 Git 命令,例如 git addgit fetch, 针对响应式用户体验进行了优化。这些命令不采取 是时候优化 Git 数据了,因为这样的优化会随着整个 存储库的大小,而这些用户命令每个执行一个相对 小动作。

git maintenance 命令为如何优化 Git 存储库。

子命令

run

运行一项或多项维护任务。

任务

gc

清理不必要的文件并优化本地存储库。 “GC” 代表“垃圾收集”,但这个任务执行很多 较小的任务。对于大型存储库,此任务可能很昂贵, 因为它将所有 Git 对象重新打包到一个单独的包文件中。它还可以 在某些情况下具有破坏性,因为它会删除陈旧的数据。看 git gc 了解更多关于 Git 垃圾收集的详细信息。

选项

--auto

run 子命令结合使用时,运行维护任务 仅当满足某些阈值时。例如,gc 任务 当松散对象的数量超过存储的数量时运行 在gc.auto 配置设置中,或者当包文件的数量 超过了gc.autoPackLimit 配置设置。


maintenance:替换run_auto_gc()

签字人:Derrick Stolee

run_auto_gc() 方法用于在一些 Git 命令后触发对 repo 维护的检查,例如 'git commit'(man) 或 'git fetch' (man).

要允许对此维护活动进行额外自定义,请将“git gc --auto [--quiet](man)”调用替换为“git maintenance run --auto [--quiet](man)”支持>'。
随着我们通过其他步骤扩展内置维护,用户将能够选择不同的维护活动。

run_auto_gc() 重命名为 run_auto_maintenance() 以更清楚地了解此调用中发生的情况,并在当前差异中公开所有调用者。重写方法以使用结构体child_process 稍微简化调用。

由于 'git fetch'(man) 已经允许禁用 'git gc --auto'(man) 子进程,添加一个等效选项不同的名称更能描述新行为:'--[no-]maintenance'。

fetch-options 现在包含在其man page 中:

在最后运行git maintenance run --auto执行自动 如果需要,存储库维护。 (--[no-]auto-gc 是同义词。)
这是默认启用的。

git clone 现在包含在其man page 中:

自动调用git maintenance run --auto。 (看 git maintenance.)


另外,感谢tasks,您的保存脚本将使git maintenancegit gc 做的更多。

maintenance:添加 --task 选项

签字人:Derrick Stolee

用户可能只想按特定顺序运行某些维护任务。

添加--task=&lt;task&gt; 选项,允许用户指定要运行的任务的有序列表。但是,这些不能多次运行。

这就是我们的maintenance_task 指针数组变得至关重要的地方。我们可以根据任务顺序对指针数组进行排序,但我们不想移动结构数据本身以保留 hashmap 引用。我们使用 hashmap 将 --task= 参数匹配到任务结构数据中。

请记住,maintenance_task 结构的“enabled”成员是未来“maintenance.&lt;task&gt;.enabled”配置选项的占位符。因此,我们使用“enabled”成员来指定当用户未指定任何--task=&lt;task&gt; 参数时运行哪些任务。
如果出现--task=&lt;task&gt;,则应忽略“enabled”成员。

git maintenance 现在包含在其man page 中:

运行一项或多项维护任务。如果一个或多个--task=&lt;task&gt; 指定选项,然后这些任务在提供的 命令。否则,只运行gc 任务。

git maintenance 现在包含在其man page 中:

--task=&lt;task&gt;

如果此选项被指定一次或多次,则只运行 按指定顺序指定任务。请参阅“任务”部分 获取接受的&lt;task&gt; 值列表。

还有:

maintenance: 创建维护..启用配置

签字人:Derrick Stolee

目前,正常运行“git maintenance run(man) 只会运行“gc”任务,因为它是唯一启用的任务。
这主要是出于向后兼容的原因,因为在一些 Git 进程之后,“git maintenance run --auto(man) 命令替换了之前的“git gc --auto”命令。

用户可以通过直接调用“git maintenance run --task=&lt;task&gt;”手动运行特定的维护任务。

允许用户自定义使用 config 自动运行哪些步骤。然后,“maintenance.&lt;task&gt;.enabled”选项可以打开这些其他任务(或关闭“gc”任务)。

git config 现在包含在其man page 中:

maintenance.&lt;task&gt;.enabled

这个布尔配置选项控制是否维护任务 当没有指定 --task 选项时运行名称为 &lt;task&gt;git maintenance run。如果 a --task 选项存在。
默认情况下,只有maintenance.gc.enabled 为真。

git maintenance 现在包含在其man page 中:

运行一项或多项维护任务。如果有一个或多个--task 选项 指定,然后这些任务按该顺序运行。除此以外, 任务由哪个maintenance.&lt;task&gt;.enabled 决定 配置选项为真。
默认情况下,只有maintenance.gc.enabled 为真。

git maintenance 现在还包含在其man page 中:

如果没有--task=&lt;task&gt; 参数被指定,那么只有任务 maintenance.&lt;task&gt;.enabled 配置为true 被考虑。


了解新的git maintenance run 当前是否正在执行任何操作的另一种方法是检查锁(.git/maintenance.lock 文件):

maintenance: 锁定对象目录

签字人:Derrick Stolee

对 Git 存储库执行维护涉及将数据写入 .git 目录,这对于尝试相同操作的多个写入者来说是不安全的。
通过持有基于文件的锁,确保一次只有一个 'git maintenance'(man) 进程在运行。

.git/maintenance.lock 文件的存在将阻止未来的维护。这个锁永远不会被提交,因为它不代表有意义的数据。相反,它只是一个占位符。

如果锁定文件已经存在,则不会尝试维护任务。稍后当我们实现 'prefetch' 任务时,这将变得非常重要,因为这是我们在 'git fetch'(man) 和'git maintenance run --auto(man).


您还可以检查git gc/git maintenance 是否需要做任何事情。

随着 Git 2.29 (Q4 2020),A "git gc"(man) 的大哥被引入,负责更多的仓库维护任务,不限于对象数据库清理。

commit 25914c4commit 4ddc79bcommit 916d062commit 65d655bcommit d7514f6commit 090511bcommit 663b2b1commit 3103e98commit 3103e98commit a95ce12commit 3ddaad0987654388@997654388@9 2020 年)Derrick Stolee (derrickstolee)
(由 Junio C Hamano -- gitster -- 合并于 commit 48794ac,2020 年 9 月 25 日)

maintenance:使用指针检查--auto

签字人:Derrick Stolee

git maintenance run(man)”命令有一个“--auto”选项。这由其他 Git 命令使用,例如 'git commit(man) ' 或 'git fetch(man) ' 来检查是否应该进行维护在将数据添加到存储库后运行。

以前,此--auto 选项仅用于将参数添加到“git gc(man) 命令作为“gc”任务的一部分。
我们将扩展其他任务以检查它们是否应该作为--auto 标志的一部分在配置启用时工作。

  • 首先,更新“gc”任务以在维护过程中执行自动检查。
    这样可以防止在不需要时运行额外的 'git gc --auto'(man) 命令。
    它还显示了其他任务的模型。

  • 其次,使用'auto_condition'函数指针作为是否启用'--auto'下的维护任务的信号。
    例如,我们不想在 '--auto' 模式下启用 'fetch' 任务,因此函数指针将保持为NULL

我们会在必要时继续将“--auto”选项传递给“git gc(man) 命令,因为gc.autoDetach 配置选项会改变行为。
很可能,我们希望将gc.autoDetach 隐含的守护进程行为吸收为maintenance.autoDetach 配置选项。


为了说明git maintenance 会做什么git gc 不会:

maintenance: 添加提交图任务

签字人:Derrick Stolee

'git maintenance(man)'内置的第一个新任务是'commit-graph'任务。
这将使用命令增量更新提交图文件

git commit-graph write --reachable --split  

通过使用“--split”选项编写增量提交图文件,我们可以最大限度地减少此操作的中断。

默认行为是合并图层,直到新的“顶部”图层小于下方图层大小的一半。这在大多数情况下提供了快速写入,而较长的写入遵循幂律分布。

最重要的是,并发 Git 进程只会在很短的时间内查看 commit-graph-chain 文件,因此当我们尝试替换文件时,它们很可能不会持有该文件的句柄。 (这只在 Windows 上很重要。)

如果一个并发进程读取了旧的 commit-graph-chain 文件,但我们的作业在读取之前使某些 .graph 文件过期,那么这些进程将看到一条警告消息(但不会失败)。这可以通过未来的更新来避免,以便在编写提交图时使用 --expire-time 参数。

git maintenance 现在包含在其man page 中:

commit-graph

commit-graph 作业以增量方式更新commit-graph 文件, 然后验证写入的数据是否正确。

增量 write 可以安全地与并发 Git 进程一起运行,因为它 不会过期 .graph 之前的文件 commit-graph-chain 文件。它们将在以后的运行中删除 关于过期延迟。

还有:

maintenance:为commit-graph 任务添加自动条件

签字人:Derrick Stolee

不要在每个'git maintenance run --auto'(man)进程中写入一个新的commit-graph(当maintenance.commit-graph.enabled配置为true时),只在有“足够”提交不在 commit-graph 文件中。

此计数由 maintenance.commit-graph.auto 配置选项控制。

要计算计数,请使用从每个 ref 开始的深度优先搜索,并使用 SEEN 标志留下标记。
如果此计数达到限制,则提前终止并启动任务。
否则,此操作将剥离每个 ref 并解析它指向的提交。如果这些都在commit-graph 中,那么这通常是一个非常快的操作。

拥有许多 ref 的用户可能会感到速度变慢,因此可以考虑将他们的限制更新得非常小。负值将强制该步骤每次都运行。

git config 现在包含在其man page 中:

maintenance.commit-graph.auto

这个整数配置选项控制commit-graph 任务的频率 应该作为git maintenance run --auto 的一部分运行。

  • 如果为零,则commit-graph 任务将不会与--auto 选项一起运行。
  • 负值将强制任务每次都运行。
  • 否则,正值表示命令应在 不在提交图文件中的可达提交至少是 maintenance.commit-graph.auto 的值。

默认值为 100。


使用 Git 2.30(2021 年第一季度),根据需要运行 commit-graph 任务 "git maintenance"(man) 的测试覆盖率增强导致发现和修复错误。

参见commit d334107(2020 年 10 月 12 日)和 commit 8f80180(2020 年 10 月 8 日)Derrick Stolee (derrickstolee)
(由 Junio C Hamano -- gitster -- 合并于 commit 0be2d65,2020 年 11 月 2 日)支持>

maintenance: 测试提交图自动条件

签字人:Derrick Stolee

commit-graph 维护任务的自动条件遍历 refs 以查找不在 commit-graph 文件中的提交。
这是在4ddc79b2(“maintenance:为提交图任务添加自动条件”,2020-09-17,Git v2.29.0-rc0 -- mergebatch #17 中列出)中添加的,但未经测试.

此更改的最初目标是通过添加测试来证明该功能正常工作。但是,有一个错误导致围绕 maintenance.commit-graph.auto=1 的基本测试在应该工作时失败。

微妙之处在于,如果参考提示不在commit-graph 中,那么我们不会将其添加到总数中。在测试中,我们看到自上次提交图写入以来我们只添加了一个提交,因此自动条件会说无事可做。

修复很简单:在开始我们的步行之前添加对commit-graph 位置的检查,以查看提示不在commit-graph 文件中。由于这是在添加到 DFS 堆栈之前发生的,因此我们不需要清除我们的(当前为空的)提交列表。

这确实为测试增加了一些额外的复杂性,因为我们还想验证沿着父母的步行确实做了一些工作。这意味着我们需要在不写commit-graph 的情况下连续添加至少两个提交。但是,我们还需要确保没有其他 ref 指向此列表的中间,否则 should_write_commit_graph() 中的 for_each_ref() 可能会访问这些提交作为提示,而不是进行 DFS 遍历。因此,最后两个提交添加了“git commit(man) 而不是"test_commit"


使用 Git 2.30(2021 年第一季度),“git maintenance(man) run/start/stop”需要在存储库中运行以保存他们使用的锁定文件,但没有t 确保它们实际上位于已更正的存储库中。

Josh Steadmon (steadmon)commit 0a1f2d0(2020 年 12 月 8 日)。
请参阅 Rafael Silva (raffs)commit e72f7de(2020 年 11 月 26 日)。
(由 Junio C Hamano -- gitster -- 合并于 commit f2a75cb,2020 年 12 月 8 日)

maintenance:在没有存储库时修复 SEGFAULT

签字人:Rafael Silva
审核人:Derrick Stolee

git maintenance run git(man) 和“git maintenance start/stop”命令分别在.git/maintenance.lock.git/schedule.lock 处持有基于文件的锁。 这些锁用于确保一次只执行一个维护过程,因为这两个操作都涉及将数据写入存储库。

锁文件的路径是使用"the_repository->objects->odb->path" that results in SEGFAULT when we have no repository available as `"`the_repository-&gt;objects-&gt;odb"设置为NULL构建的。

让我们教维护命令使用RUN_SETUP 选项,该选项将提供验证并在存储库之外运行时失败。因此,修复了所有三个操作的 SEGFAULT,并使所有子命令的行为保持一致。

设置RUN_SETUP 也为所有子命令提供相同的保护,因为“注册”和“取消注册”也需要在存储库中执行。

此外,让我们删除由“注册”和“取消注册”实现的本地验证,因为新选项不再需要这样做。

【讨论】:

    【解决方案2】:

    随着 Git 2.30(2021 年第一季度),“git maintenance(man),“git gc”的扩展大哥(man)the previous answer 中介绍,不断发展。

    它比git gc 更精确,并且在 2.30 中引入的选项允许知道它何时做了某事,正如 OP 中所要求的那样。

    参见commit e841a79commit a13e3d0commit 52fe41fcommit efdd2f0commit 18e449fcommit 3e220e6commit 252cfb7commit 28cb5e6(2020 年 9 月 25 日)Derrick Stolee (derrickstolee)
    (由Junio C Hamano -- gitster -- 合并于commit 52b8c8c,2020 年 10 月 27 日)

    maintenance: 添加增量重新打包任务

    签字人:Derrick Stolee

    之前的更改使用可以在后台安全运行的“松散对象”清理松散对象。添加一个对包文件执行类似清理的类似作业。

    运行“git repack(man)”的一个问题是它旨在将所有包文件重新打包到一个包文件中。虽然这是存储对象数据的最节省空间的方式,但它的时间或内存效率不高。如果 repo 太大以至于用户难以在磁盘上存储包的两个副本,这将变得非常重要。

    相反,通过将一些小包文件收集到一个新的包文件中来执行“增量”重新打包。自从在 19575c7 ("multi-pack-index: implement 'expire' subcommand", 2019-06 -10,Git v2.23.0-rc0 -- merge 列在batch #6) 和'git multi-pack-index repack(man) '被添加到ce1e4a1 ("midx:实现midx_repack()", 2019-06-10, Git v2.23.0-rc0 -- merge 列在batch #6)。

    “增量重新打包”任务运行以下步骤:

    1. 'git multi-pack-index write(man)' 如果一个多包索引文件不存在,则创建一个,否则将更新多包索引 自上次写入以来出现的任何新包文件。这 与后台抓取作业特别相关。

      当多包索引看到同一对象的两个副本时,它 将偏移数据存储到较新的包文件中。这意味着 一些旧的包文件可能会变成“未引用”,我将使用它 意思是“一个在包文件列表中的包文件 多包索引,但多包索引中没有任何对象 引用该包文件中的位置。”

    2. 'git multi-pack-index expire(man)' 删除所有未引用的包文件并更新多包索引以从 列表。这是安全的,因为并发的 Git 进程会看到 multi-pack-index 并且在查找对象时不打开这些包 内容。 (类似于 'loose-objects' 工作,有一些 Git 无论多包索引如何打开包文件的命令, 但它们很少使用。此外,用户自行选择 使用后台操作可能会避免使用那些 命令。)

    3. 'git multi-pack-index repack --bacth-size=&lt;size&gt;(man)' 收集多包索引中列出的一组包文件并创建 包含列出其偏移量的对象的新包文件 通过 multi-pack-index 在这些对象中。套装- 通过对包文件进行排序来贪婪地选择文件修改 如果它的“预期大小”是时间并添加一个包文件到集合中 小于批量大小,直到达到预期的总大小 selected pack-files 至少是批量大小。 “预期 size”是通过将包文件的大小除以计算得出的 由包文件中的对象数乘以 多包索引中具有偏移量的对象数 包文件。预期大小近似于其中的数据量 包文件将有助于生成的包文件大小。这 目的是生成的包文件的大小将接近 到提供的批量大小。

      增量重新打包任务的下一次运行将删除这些 在“过期”步骤中重新打包的包文件。

      在这个版本中,批量大小设置为“0”,忽略 选择包文件时的大小限制。它反而 选择所有打包文件并将所有打包对象重新打包到一个 单个包文件。这将在下一次更改中更新,但是 它需要进行一些更好地隔离的计算 单独更改。

    这些步骤基于Scalar (and VFS for Git) 中的类似后台维护步骤。这对于 Windows 操作系统存储库的用户来说非常有效。 在为 Git 存储库使用相同的 VFS 一年多之后,一些用户拥有 数千个 的包文件,这些文件组合起来高达 250 GB 的数据。我们注意到一些用户遇到了打开文件描述符的限制(部分原因是由af96fe3 修复的多包索引中的一个错误(“midx:将包添加到packed_git 链接列表”,2019- 04-29,Git v2.22.0-rc1 -- merge)。

    这些包文件大多很小,因为它们包含在给定小时内推送到源的提交和树。 GVFS 协议包括一个“预取”步骤,该步骤要求预先计算的包文件包含按时间戳的提交和树。这些包文件被分组为“每日”包文件,每天一次,最多 30 天。如果用户超过 30 天没有请求预取包,那么他们将在一个新的大包文件中获得提交和树的整个历史记录。这导致大量压缩差的压缩文件。

    通过每天运行一次此包文件维护步骤,这些包含数千个 200+ GB 包的存储库减少到数十个 30-50 GB 包文件。这一切都是在没有从系统中删除对象的情况下完成的,并且使用了 2 GB 的恒定批量大小。一旦完成将包文件减小到较小大小的工作,2 GB 的批处理大小意味着并非每次运行都会触发重新打包操作,因此接下来的运行不会使包文件过期。这使这些存储库保持“干净”状态。

    git maintenance 现在包含在其man page 中:

    incremental-repack

    incremental-repack 作业重新打包对象目录 使用multi-pack-index 功能。为了防止种族 并发 Git 命令的条件,它遵循两步 过程。首先调用git multi-pack-index expire删除 multi-pack-index 文件未引用的包文件。其次,它 来电git multi-pack-index repack选几个小 打包文件并将它们重新打包成一个更大的文件,然后更新 multi-pack-index 引用小包文件的条目 请参阅新的包文件。这准备了那些小包文件 以便在下次运行 git multi-pack-index expire 时删除。 小包文件的选择使得预期的 大包文件的大小至少是批量大小;见 --batch-size 选项中的 repack 子命令 git multi-pack-index。默认批量大小为零, 这是一个尝试重新打包所有包文件的特殊情况 到一个单独的包文件中。

    还有:

    maintenance: 添加增量重新打包自动条件

    签字人:Derrick Stolee

    incremental-repack 任务通过删除已被新包替换的包文件来更新多包索引,然后将一批小包文件重新打包成一个更大的包文件。这种增量重新打包比重写所有对象数据要快,但比其他一些维护活动要慢。

    maintenance.incremental-repack.auto”配置选项指定在运行该步骤之前,在多包索引之外应该存在多少个包文件。
    这些包文件可以通过 'git fetch(man)' 命令或松散对象任务创建。
    默认值为 10。

    将选项设置为零会禁用带有“--auto”选项的任务,而负值会使任务每次都运行。

    git config 现在包含在其man page 中:

    maintenance.incremental-repack.auto

    这个整数配置选项控制incremental-repack 的频率 任务应作为git maintenance run --auto 的一部分运行。如果为零, 那么incremental-repack 任务将不会与--auto 一起运行 选项。负值将强制任务每次运行。 否则,正值意味着命令应该在 不在多包索引中的包文件数至少是该值 的maintenance.incremental-repack.auto。默认值为 10。


    在 Git 2.30(2021 年第一季度)中,添加了“git maintenance”的部分内容(man) 以简化为其编写 crontab 条目(和其他调度系统配置)。

    commit 0016b61commit 61f7a38commit a4cb1a2(2020 年 10 月 15 日)、commit 2fec604commit 0c18b70commit 4950b2acommit b08ff1f(2020 年 9 月 11 日)和commit 1942d48(2020 年 8 月 28 日) ) by Derrick Stolee (derrickstolee)
    (由 Junio C Hamano -- gitster -- 合并于 commit 7660da1,2020 年 11 月 18 日)

    maintenance:在文档中添加故障排除指南

    帮助:Junio C Hamano
    签字人:Derrick Stolee

    git maintenance run(man)”子命令会锁定对象数据库以防止并发进程竞争资源。这是防止可能的存储库损坏和数据丢失的重要安全措施。

    如果用户不知道,此功能可能会导致令人困惑的行为。在 'git maintenance(man) ' 内置文档中添加一个 TROUBLESHOOTING 部分来讨论这些权衡。

    本节的简短版本是 Git 不会损坏您的存储库,但如果计划任务列表花费的时间超过一个小时,那么由于对象数据库冲突,一些计划任务可能会被丢弃。
    例如,在午夜长时间运行的“每日”任务可能会阻止“每小时”任务在凌晨 1 点运行。

    相反的情况也是可能的,但只要“每小时”任务比“每日”和“每周”任务快得多,这种可能性就较小。

    git maintenance 现在包含在其man page 中:

    疑难解答


    git maintenance 命令旨在简化存储库 维护模式,同时最大限度地减少 Git 命令期间的用户等待时间。 有多种配置选项可用于自定义 过程。默认维护选项侧重于完成的操作 快速,即使在大型存储库上也是如此。

    用户可能会发现某些情况下计划的维护任务不会像 经常按预期。每个git maintenance run 命令都会锁定 存储库的对象数据库,这可以防止其他并发 git maintenance run 在同一存储库上运行的命令。没有 这种保护措施,竞争进程可能会将存储库留在 不可预知的状态。

    后台维护计划运行git maintenance run 进程 按小时计算。每次运行都会执行“每小时”任务。在午夜, 该过程还执行“日常”任务。第一天的午夜 每周,该进程还执行“每周”任务。一个 进程遍历每个注册的存储库,执行预定的 该频率的任务。视注册人数而定 存储库及其大小,此过程可能需要一个多小时。 在这种情况下,多个git maintenance run 命令可能会在同一个服务器上运行 存储库同时,碰撞对象数据库锁。这 导致两个任务之一没有运行。

    如果您发现某些维护时段的时间超过一小时 完成,然后考虑降低维护的复杂性 任务。例如,gc 任务比 incremental-repack 任务。然而,这需要付出一些代价 更大的对象数据库。考虑移动更昂贵的任务来运行 不太频繁。

    专家用户可以考虑使用 与通过git maintenance start 和 Git 配置选项。这些用户应该知道对象 数据库锁以及并发git maintenance run 命令的行为方式。 此外,git gc 命令不应与 git maintenance run 命令。 git gc修改对象数据库 但不会像git maintenance run 那样获取锁。如果 可能的话,使用git maintenance run --task=gc 而不是git gc

    【讨论】:

    【解决方案3】:

    如果您正在监视git gc --auto 退出状态(例如用于检测故障),则该返回值已随 Git 2.20 更改:

    commit 3029970(2018 年 7 月 17 日)Jonathan Nieder (artagnon)
    帮助者:Jeff King (peff)
    (由 Junio C Hamano -- gitster -- 合并于 commit 993fa56,2018 年 10 月 16 日)

    gc:失败时退出状态为 128

    cmd_gc gets 返回的-1 值传播到exit(),导致退出状态为 255。
    使用 die 代替更清晰的错误消息和受控退出。

    您现在拥有的是“error: The last gc run reported the following.”而不是:

    fatal: The last gc run reported the following
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-12
      相关资源
      最近更新 更多