2020 年 9 月更新:您不必只运行 git gc --auto 作为自动保存脚本的一部分。
旧的“gc”现在可以被新的git maintenance run --auto取代。
它可以显示它在做什么。
随着 Git 2.29(2020 年第四季度),A “git gc”(man) 的大哥被引入负责更多的存储库维护任务,不限于对象数据库清理。
见commit 25914c4、commit 4ddc79b、commit 916d062、commit 65d655b、commit d7514f6、commit 090511b、commit 663b2b1、commit 3103e98、commit 3103e98、commit 3103e98、commit a95ce12、commit 3ddaad0、@397654332@(178643332@, 2020 年)Derrick Stolee (derrickstolee)。
(由 Junio C Hamano -- gitster -- 在 commit 48794ac 中合并,2020 年 9 月 25 日)
帮助者: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 add 或 git fetch,
针对响应式用户体验进行了优化。这些命令不采取
是时候优化 Git 数据了,因为这样的优化会随着整个
存储库的大小,而这些用户命令每个执行一个相对
小动作。
git maintenance 命令为如何优化
Git 存储库。
子命令
run
运行一项或多项维护任务。
任务
gc
清理不必要的文件并优化本地存储库。 “GC”
代表“垃圾收集”,但这个任务执行很多
较小的任务。对于大型存储库,此任务可能很昂贵,
因为它将所有 Git 对象重新打包到一个单独的包文件中。它还可以
在某些情况下具有破坏性,因为它会删除陈旧的数据。看
git gc 了解更多关于 Git 垃圾收集的详细信息。
选项
--auto
与run 子命令结合使用时,运行维护任务
仅当满足某些阈值时。例如,gc 任务
当松散对象的数量超过存储的数量时运行
在gc.auto 配置设置中,或者当包文件的数量
超过了gc.autoPackLimit 配置设置。
签字人: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 maintenance 比git gc 做的更多。
签字人:Derrick Stolee
用户可能只想按特定顺序运行某些维护任务。
添加--task=<task> 选项,允许用户指定要运行的任务的有序列表。但是,这些不能多次运行。
这就是我们的maintenance_task 指针数组变得至关重要的地方。我们可以根据任务顺序对指针数组进行排序,但我们不想移动结构数据本身以保留 hashmap 引用。我们使用 hashmap 将 --task= 参数匹配到任务结构数据中。
请记住,maintenance_task 结构的“enabled”成员是未来“maintenance.<task>.enabled”配置选项的占位符。因此,我们使用“enabled”成员来指定当用户未指定任何--task=<task> 参数时运行哪些任务。
如果出现--task=<task>,则应忽略“enabled”成员。
git maintenance 现在包含在其man page 中:
运行一项或多项维护任务。如果一个或多个--task=<task>
指定选项,然后这些任务在提供的
命令。否则,只运行gc 任务。
git maintenance 现在包含在其man page 中:
--task=<task>
如果此选项被指定一次或多次,则只运行
按指定顺序指定任务。请参阅“任务”部分
获取接受的<task> 值列表。
还有:
签字人:Derrick Stolee
目前,正常运行“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 现在包含在其man page 中:
maintenance.<task>.enabled
这个布尔配置选项控制是否维护任务
当没有指定 --task 选项时运行名称为 <task> 的
git maintenance run。如果 a
--task 选项存在。
默认情况下,只有maintenance.gc.enabled 为真。
git maintenance 现在包含在其man page 中:
运行一项或多项维护任务。如果有一个或多个--task 选项
指定,然后这些任务按该顺序运行。除此以外,
任务由哪个maintenance.<task>.enabled 决定
配置选项为真。
默认情况下,只有maintenance.gc.enabled 为真。
git maintenance 现在还包含在其man page 中:
如果没有--task=<task>
参数被指定,那么只有任务
maintenance.<task>.enabled 配置为true 被考虑。
了解新的git maintenance run 当前是否正在执行任何操作的另一种方法是检查锁(.git/maintenance.lock 文件):
签字人: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 25914c4,commit 4ddc79b,commit 916d062,commit 65d655b,commit d7514f6,commit 090511b,commit 663b2b1,commit 3103e98,commit 3103e98,commit a95ce12,commit 3ddaad0987654388@997654388@9 2020 年)Derrick Stolee (derrickstolee)。
(由 Junio C Hamano -- gitster -- 合并于 commit 48794ac,2020 年 9 月 25 日)
签字人:Derrick Stolee
“git maintenance run(man)”命令有一个“--auto”选项。这由其他 Git 命令使用,例如 'git commit(man) ' 或 'git fetch(man) ' 来检查是否应该进行维护在将数据添加到存储库后运行。
以前,此--auto 选项仅用于将参数添加到“git gc”(man) 命令作为“gc”任务的一部分。
我们将扩展其他任务以检查它们是否应该作为--auto 标志的一部分在配置启用时工作。
我们会在必要时继续将“--auto”选项传递给“git gc”(man) 命令,因为gc.autoDetach 配置选项会改变行为。
很可能,我们希望将gc.autoDetach 隐含的守护进程行为吸收为maintenance.autoDetach 配置选项。
为了说明git maintenance 会做什么git gc 不会:
签字人: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 日)支持>
签字人:Derrick Stolee
commit-graph 维护任务的自动条件遍历 refs 以查找不在 commit-graph 文件中的提交。
这是在4ddc79b2(“maintenance:为提交图任务添加自动条件”,2020-09-17,Git v2.29.0-rc0 -- merge 在batch #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 日)
签字人: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->objects->odb"设置为NULL构建的。
让我们教维护命令使用RUN_SETUP 选项,该选项将提供验证并在存储库之外运行时失败。因此,修复了所有三个操作的 SEGFAULT,并使所有子命令的行为保持一致。
设置RUN_SETUP 也为所有子命令提供相同的保护,因为“注册”和“取消注册”也需要在存储库中执行。
此外,让我们删除由“注册”和“取消注册”实现的本地验证,因为新选项不再需要这样做。