我git gc --auto作为自动保存脚本的一部分运行。如果git gc --auto做了什么,我想进一步清理,但如果git gc --auto觉得不需要做些什么,我想省去麻烦。有没有办法检查 的返回值git gc --auto,或者事先检查是否有必要运行它?
2020 年 9 月更新:您不必仅git gc --auto作为自动保存脚本的一部分运行。
旧的“ gc”现在可以被新的git maintenance run --auto.
它可以显示它在做什么。
在 Git 2.29(2020 年第四季度)中,引入了“ git gc” (男人)的大哥来处理更多的存储库维护任务,而不仅限于对象数据库清理。
见提交25914c4,提交4ddc79b,提交916d062,提交65d655b,提交d7514f6,提交090511b,提交663b2b1,提交3103e98,提交a95ce12,提交3ddaad0,提交2057d75(2020年9月17日)由井架Stolee( )derrickstolee。
(由Junio C gitsterHamano合并-- --在提交 48794ac 中,2020 年 9 月 25 日)
maintenance: 创建基本维护运行程序帮助者:Jonathan Nieder
签字人:Derrick Stolee
'gc' 内置是我们当前用于自动维护存储库的入口点。这一工具执行许多操作,例如:
- 重新打包存储库,
- 包装参考,和
- 重写提交图文件。
顾名思义,它执行“垃圾收集”,这意味着几个不同的事情,有些用户可能不想使用这种重写整个对象数据库的操作。
创建一个新的 '
maintenance' 内置命令,它将成为一个更通用的命令。首先,它将仅支持“
run”子命令,但稍后将扩展以添加用于在后台调度维护的子命令。现在,'
maintenance' 内置函数是' ' 内置函数的一个薄垫片gc。
事实上,唯一的选择是 '--auto' 切换,它直接传递给 'gc' 内置函数。
当前更改与此简单操作隔离,以防止在添加新内置函数的所有样板中丢失更有趣的逻辑。使用现有
builtin/gc.c文件,因为我们希望在两个内置函数之间共享代码。
有可能我们会在某个时候让 ' ' 完全maintenance替换gc内置的 ' ',而将 ' ( man ) ' 作为 ' ' 的某些特定参数的别名。git gcgit maintenance run创建一个新的
test_subcommand帮助程序,允许我们测试某个子命令是否已运行。它需要将GIT_TRACE2_EVENT日志存储在文件中。
可以使用否定模式,将在以后的测试中使用。
(最后一部分是确定新git maintainance run --auto功能的一种方法)
git maintenance现在包括在其手册页中:
git-维护(1)
姓名
git-maintenance- 运行任务以优化 Git 存储库数据概要
Run Code Online (Sandbox Code Playgroud)[verse] 'git maintenance' run [<options>]描述
运行任务以优化 Git 存储库数据,加快其他 Git 命令并降低存储库的存储要求。
添加存储库数据的 Git 命令(例如
git add或git fetch)针对响应式用户体验进行了优化。这些命令不需要时间来优化 Git 数据,因为这样的优化会随着存储库的完整大小而扩展,而这些用户命令每个都执行相对较小的操作。该
git maintenance命令为如何优化 Git 存储库提供了灵活性。子命令
run运行一项或多项维护任务。
任务
gc清理不必要的文件并优化本地存储库。“GC”代表“垃圾收集”,但此任务执行许多较小的任务。对于大型存储库,此任务可能会很昂贵,因为它会将所有 Git 对象重新打包到单个打包文件中。在某些情况下,它也可能具有破坏性,因为它会删除陈旧的数据。有关
git gcGit 中垃圾收集的更多详细信息,请参见 。选项
--auto与
run子命令结合使用时,仅当满足特定阈值时才运行维护任务。例如,gc当松散对象的数量超过gc.auto配置设置中存储的数量时,或者当包文件的数量超过gc.autoPackLimit配置设置时,任务就会运行。
maintenance: 代替run_auto_gc()签字人:德里克·斯托利
该
run_auto_gc()方法在多个地方用于在某些 Git 命令之后触发对 repo 维护的检查,例如 'git commit' ( man )或 'git fetch' ( man )。要允许对此维护活动进行额外定制,请将“ ( man ) ”调用替换为“ ( man ) ”。 随着我们通过其他步骤扩展内置的维护,用户将能够选择不同的维护活动。
git gc --auto [--quiet]git maintenance run --auto [--quiet]重命名
run_auto_gc()以run_auto_maintenance()更清楚地了解此调用中发生的情况,并公开当前差异中的所有调用者。重写方法以使用结构child_process来稍微简化调用。由于 '
git fetch' ( man )已经允许禁用 'git gc --auto' ( man )子进程,所以添加一个具有不同名称的等效选项以更好地描述新行为:'--[no-]maintenance'。
fetch-options现在包括在其手册页中:
git maintenance run --auto如果需要,最后运行以执行自动存储库维护。(--[no-]auto-gc是同义词。)
默认情况下启用。
git clone现在包括在其手册页中:
这会自动调用
git maintenance run --auto. (见git maintenance。)
另外,由于tasks,您的保存脚本将能够git maintenance比git gc以往任何时候都做得更多。
maintenance: 添加 --task 选项签字人:德里克·斯托利
用户可能只想按特定顺序运行特定维护任务。
添加
--task=<task>选项,它允许用户指定要运行的任务的有序列表。但是,这些不能多次运行。这就是我们的
maintenance_task指针数组变得至关重要的地方。我们可以根据任务顺序对指针数组进行排序,但我们不想移动结构数据本身以保留哈希映射引用。我们使用哈希图将 --task= 参数匹配到任务结构数据中。请记住,结构的“
enabled”成员maintenance_task是未来“maintenance.<task>.enabled”配置选项的占位符。因此,我们使用“enabled”成员来指定当用户未指定任何--task=<task>参数时运行哪些任务。如果出现
'enabled' 成员应该被忽略--task=<task>。
git maintenance现在包括在其手册页中:
运行一项或多项维护任务。如果
--task=<task>指定了一个或多个选项,则这些任务将按提供的顺序运行。否则,只gc运行任务。
git maintenance现在包括在其手册页中:
--task=<task>如果此选项被指定一次或多次,则仅以指定的顺序运行指定的任务。有关可接受
<task>值的列表,请参阅“任务”部分。
和:
maintenance: 创建维护..启用配置签字人:德里克·斯托利
目前,正常运行 "
git maintenance run" ( man )只会运行 'gc' 任务,因为它是唯一启用的。
这主要是出于向后兼容的原因,因为在某些 Git 进程之后,“git maintenance run --auto” (man)命令替换了之前的“git gc --auto”命令。用户可以通过
git maintenance run --task=<task>直接调用“ ”来手动运行特定的维护任务。允许用户自定义使用 config 自动运行哪些步骤。然后“
maintenance.<task>.enabled”选项可以打开这些其他任务(或关闭“gc”任务)。
git config现在包括在其手册页中:
maintenance.<task>.enabled此布尔配置选项控制
<task>在未--task指定任何选项 时是否运行具有名称的维护任务git maintenance run。如果--task存在选项,这些配置值将被忽略 。
默认情况下, onlymaintenance.gc.enabled为 true。
git maintenance现在包括在其手册页中:
运行一项或多项维护任务。如果
--task指定了一个或多个选项,则这些任务将按该顺序运行。否则,任务由哪些maintenance.<task>.enabled配置选项为真决定。
默认情况下, onlymaintenance.gc.enabled为 true。
git maintenance现在还包括在其手册页中:
如果未
--task=<task>指定参数,则仅考虑maintenance.<task>.enabled配置为 as的任务true。
了解 newgit maintenance run当前是否在做任何事情的另一种方法是检查锁(.git/maintenance.lock文件):
maintenance: 锁定对象目录签字人:德里克·斯托利
对 Git 存储库执行维护涉及将数据写入
.git目录,这对于尝试相同操作的多个编写者来说是不安全的。通过持有基于文件的锁,
确保一次只有一个 'git maintenance' ( man )进程正在运行。该
.git/maintenance.lock文件的存在将阻止未来的维护。这个锁永远不会提交,因为它不代表有意义的数据。相反,它只是一个占位符。如果锁定文件已存在,则不会尝试任何维护任务。这将在稍后我们实现 '
prefetch' 任务时变得非常重要,因为这是我们在 'git fetch' ( man ) ' 和 ' ( man )之间创建递归过程循环的权宜之计。git maintenance run --auto
您还可以检查git gc/git maintenance 是否必须执行任何操作。
在 Git 2.29(2020 年第四季度)中,引入了“ git gc” (男人)的大哥来处理更多的存储库维护任务,而不仅限于对象数据库清理。
见提交25914c4,提交4ddc79b,提交916d062,提交65d655b,提交d7514f6,提交090511b,提交663b2b1,提交3103e98,提交a95ce12,提交3ddaad0,提交2057d75(2020年9月17日)由井架Stolee( )derrickstolee。
(由Junio C gitsterHamano合并-- --在提交 48794ac 中,2020 年 9 月 25 日)
maintenance: 使用指针检查--auto签字人:德里克·斯托利
' ( man ) ' 命令有一个 '--auto' 选项。其他 Git 命令(例如“ ( man ) ”或“ ( man ) ”)使用它来检查在将数据添加到存储库后是否应运行维护。
git maintenance rungit commitgit fetch以前,此
--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 2.30(2021 年第一季度),“ git maintenance” (man),在上一个答案中出现的“ git gc” (man)的扩展大哥,继续进化。
它比git gc2.30 中引入的选项更精确,允许知道它何时完成了某些操作,正如 OP 中所要求的那样。
请参阅( Derrick Sto ) 的commit e841a79、commit a13e3d0、commit 52fe41f、commit efdd2f0、commit 18e449f、commit 3e220e6、commit 252cfb7、commit 28cb5e6(2020 年 9 月 25 日)。(由Junio C Hamano合并-- --在提交 52b8c8c 中,2020 年 10 月 27 日)derrickstolee
gitster
maintenance: 添加增量重新打包任务签字人:德里克·斯托利
之前的更改使用可以在后台安全运行的“松散对象”清理松散对象。添加一个类似的作业,对包文件执行类似的清理。
运行 ' ( man ) ' 的一个问题是它旨在将所有包文件重新打包为单个包文件。虽然这是存储对象数据的最节省空间的方式,但它在时间或内存方面并不高效。如果 repo 太大以至于用户难以在他们的磁盘上存储包的两个副本,这将变得非常重要。
git repack相反,通过将一些小包文件收集到一个新的包文件中来执行“增量”重新打包。自19575c7中添加' ( man ) '以来,多包索引促进了此过程(“ :实施 'expire' 子命令”,2019 年 6 月 10 日,Git v2.23.0-rc0 --合并在第 6 批中列出) 和 ' ( man ) ' 被添加到ce1e4a1 (" : implement ", 2019-06-10, Git v2.23.0-rc0 --合并在第 6 批中列出)。
git multi-pack-index expiremulti-pack-indexgit multi-pack-index repackmidxmidx_repack()'incremental-repack' 任务运行以下步骤:
' ( man ) ' 创建一个 multi-pack-index 文件,如果一个不存在,否则将使用自上次写入以来出现的任何新 pack-file 更新 multi-pack-index。这与后台提取作业特别相关。
git multi-pack-index write当 multi-pack-index 看到同一个对象的两个副本时,它会将偏移数据存储到较新的包文件中。这意味着一些旧的包文件可能会变得“未引用”,我将用它来表示“在多包索引的包文件列表中的包文件,但在多包索引中没有任何对象-索引引用该包文件中的一个位置。”
' ( man ) ' 删除任何未引用的包文件并更新多包索引以从列表中删除这些包文件。这是安全的,因为并发 Git 进程将看到 multi-pack-index 并且在查找对象内容时不会打开这些包。(类似于'loose-objects'工作,有一些Git命令会打开pack-files而不管multi-pack-index,但它们很少使用。此外,一个用户自己选择使用后台操作可能会避免使用这些命令。)
git multi-pack-index expire' (男人
git multi-pack-index repack --bacth-size=<size>)' 收集在 multi-pack-index 中列出的一组包文件,并创建一个新的包文件,其中包含由 multi-pack-index 列出的偏移量在这些对象中的对象。通过按修改时间对包文件进行排序并在其“预期大小”小于批处理大小的情况下将包文件添加到集合中,直到选定包文件的总预期大小,从而贪婪地选择包文件集至少是批量大小。“预期大小”的计算方法是将包文件的大小除以包文件中的对象数,再乘以来自具有该包文件中偏移量的多包索引中的对象数。预期大小近似于来自该包文件的数据将有助于生成的包文件大小。增量重新打包任务的下一次运行将在“过期”步骤中删除这些重新打包的打包文件。
在此版本中,批处理大小设置为“0”,这在选择包文件时忽略了大小限制。相反,它选择所有打包文件并将所有打包对象重新打包到单个打包文件中。这将在下一次更改中更新,但它需要进行一些更好地隔离到单独更改的计算。
这些步骤基于Scalar(和 VFS for Git)中类似的后台维护步骤。这对于 Windows 操作系统存储库的用户来说非常有效。在为 Git 存储库使用相同的 VFS 一年多之后,一些用户拥有数千个打包文件,这些文件合并起来高达 250 GB 的数据。我们注意到一些用户遇到了打开文件描述符限制(部分原因是af96fe3修复的 multi-pack-index 中的错误(“
midx:将包添加到packed_git链表”,2019 年 4 月 29 日,Git v2.22.0 -rc1 --合并)。这些包文件大多很小,因为它们包含在给定小时内推送到源的提交和树。GVFS 协议包括一个“预取”步骤,该步骤要求按时间戳包含提交和树的预计算包文件。这些包文件被分组为“每日”包文件,每天一次,最多 30 天。如果用户超过 30 天没有请求预取包,那么他们将在一个新的大包文件中获得提交和树的完整历史记录。这导致大量包文件的增量压缩很差。
通过每天运行一次这个包文件维护步骤,这些包含数千个包跨越 200+ GB 的存储库减少到几十个跨越 30-50 GB 的包文件。这一切都是在没有从系统中删除对象的情况下完成的,并且使用了 2 GB 的恒定批量大小。一旦完成将打包文件减小到小尺寸的工作,2 GB 的批处理大小意味着并非每次运行都会触发重新打包操作,因此接下来的运行不会使打包文件过期。这使这些存储库保持在“干净”状态。
git maintenance现在包括在其手册页中:
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: 添加增量重新打包自动条件签字人:德里克·斯托利
增量重新打包任务通过删除已被新包替换的包文件来更新多包索引,然后将一批小包文件重新打包成更大的包文件。这种增量重新打包比重写所有对象数据更快,但比其他一些维护活动慢。
'
maintenance.incremental-repack.auto' 配置选项指定在运行该步骤之前应该在多包索引之外存在多少包文件。
这些包文件可以由' ( man ) ' 命令或由松散对象任务创建。 默认值为 10。git fetch将选项设置为零会禁用带有“
--auto”选项的任务,负值会使任务每次都运行。
git config现在包括在其手册页中:
maintenance.incremental-repack.auto此整数配置选项控制
incremental-repack任务应作为git maintenance run --auto. 如果为零,则incremental-repack任务将不会使用该--auto选项运行。负值将强制任务每次都运行。否则,正值意味着命令应该在不在 multi-pack-index 中的包文件数至少为 的值时运行maintenance.incremental-repack.auto。默认值为 10。
在 Git 2.30(2021 年第一季度)中,添加了部分“ git maintenance” (man)以简化为其编写 crontab 条目(和其他调度系统配置)。
见提交0016b61,提交61f7a38,提交a4cb1a2(2020年10月15日),提交2fec604,提交0c18b70,提交4950b2a,提交b08ff1f(2020年9月11日),以及提交1942d48(2020年8月28日)由井架Stolee( )derrickstolee。
(由Junio C gitsterHamano合并-- --在commit 7660da1,2020 年 11 月 18 日)
maintenance:向文档添加故障排除指南帮助者:Junio C Hamano
签字人:Derrick Stolee
' ( man ) ' 子命令锁定对象数据库以防止并发进程争用资源。这是防止可能的存储库损坏和数据丢失的重要安全措施。
git maintenance run如果用户不知道,此功能可能会导致混淆行为。将故障排除部分添加到讨论这些权衡的“ ( man ) ”内置文档中。
git maintenance本节的简短版本是 Git 不会破坏您的存储库,但是如果计划任务列表花费的时间超过一个小时,那么由于此对象数据库冲突,某些计划任务可能会被丢弃。
例如,在午夜长时间运行的“每日”任务可能会阻止“每小时”任务在凌晨 1 点运行。相反的情况也是可能的,但不太可能,只要“每小时”任务比“每日”和“每周”任务快得多。
git maintenance现在包括在其手册页中:
故障排除
该
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。
| 归档时间: |
|
| 查看次数: |
2108 次 |
| 最近记录: |