作为自动保存脚本的一部分,我正在运行git gc --auto
。如果git gc --auto
已经完成了某些操作,我想进一步清理,但是如果git gc --auto
没有做任何事情,我希望避免麻烦。有没有办法检查git gc --auto
的返回值,或者在运行它之前检查是否需要运行它?
作为自动保存脚本的一部分,我正在运行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年第4季度),引入了一个 "git gc
"(man) 的大兄弟来 处理更多的存储库维护任务,不仅限于对象数据库清理。
derrickstolee
)提交。 gitster
--在commit 48794ac中合并,2020年9月25日)
维护
: 创建基本的维护运行程序协助者: Jonathan Nieder
签署者: Derrick Stolee
builtin/gc.c
文件,因为我们希望在两个内置工具之间共享代码。有可能在某些时候,'maintenance'完全取代'gc'内置工具,将'git gc(man)'作为某些特定参数的别名,用于'git maintenance run'。创建一个新的'test_subcommand'助手,允许我们测试是否运行了某个特定的子命令。它需要将'GIT_TRACE2_EVENT'日志存储在文件中。稍后的测试中将使用否定模式。
(最后一部分是确定新的git maintainance run --auto
做了些什么的一种方法)
git maintenance
现在在其手册页中包括:
git-maintenance(1)
NAME
git-maintenance
- Run tasks to optimize Git repository dataSYNOPSIS
[verse] 'git maintenance' run [<options>]
DESCRIPTION
Run tasks to optimize Git repository data, speeding up other Git commands and reducing storage requirements for the repository.
Git commands that add repository data, such as
git add
orgit fetch
, are optimized for a responsive user experience. These commands do not take time to optimize the Git data, since such optimizations scale with the full size of the repository while these user commands each perform a relatively small action.The
git maintenance
command provides flexibility for how to optimize the Git repository.SUBCOMMANDS
run
Run one or more maintenance tasks.
TASKS
gc
Clean up unnecessary files and optimize the local repository. "GC" stands for "garbage collection," but this task performs many smaller tasks. This task can be expensive for large repositories, as it repacks all Git objects into a single pack-file. It can also be disruptive in some situations, as it deletes stale data. See
git gc
for more details on garbage collection in Git.OPTIONS
--auto
When combined with the
run
subcommand, run maintenance tasks only if certain thresholds are met. For example, thegc
task runs when the number of loose objects exceeds the number stored in thegc.auto
config setting, or when the number of pack-files exceeds thegc.autoPackLimit
config setting.
维护
:替换 run_auto_gc()
Signed-off-by: Derrick Stolee
run_auto_gc()
方法在多个地方用于触发检查仓库维护的操作,例如 '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
现在在其手册页中包含:
在结束时运行
git maintenance run --auto
以执行必要的自动存储库维护。(--[no-]auto-gc
是一个同义词。)
默认情况下启用此功能。
git clone
现在在其手册页中包含:
自动调用
git maintenance run --auto
。(请参见git maintenance
。)
git gc
更好地使用git maintenance
功能。
maintenance
:添加--task选项签名作者:Derrick Stolee
用户可能想要以特定顺序运行某些维护任务。
添加
--task=<task>
选项,允许用户指定要运行的任务有序列表。但是这些任务不能多次运行。这就是我们的
maintenance_task
指针数组变得至关重要的地方。我们可以根据任务顺序对指针数组进行排序,但不想移动结构数据本身以保留哈希映射引用。我们使用哈希映射将--task=
参数匹配到任务结构数据中。请注意,
maintenance_task
结构体的“enabled
”成员是未来“maintenance.<task>.enabled
”配置选项的占位符。因此,当用户未指定任何--task=<task>
参数时,我们使用“enabled
”成员指定要运行的任务。
如果出现--task=<task>
,则应忽略“enabled
”成员。
git maintenance
现在在其man page中包括:
运行一个或多个维护任务。如果指定了一个或多个
--task=<task>
选项,则按照提供的顺序运行这些任务。否则,只运行gc
任务。
git maintenance
现在在其man page中包括:
--task=<task>
如果指定了此选项一次或多次,则仅按指定顺序运行指定的任务。请参阅“TASKS”部分以获取接受的
<task>
值列表。
和:
目前,普通运行 "
maintenance
:创建maintenance..enabled配置已签署:Derrick Stolee
git maintenance run
"(man) 仅会运行 'gc
' 任务,因为它是唯一启用的任务。git maintenance run --auto
"(man) 命令在某些 Git 进程之后替代了以前的 "git gc --auto
" 命令。git maintenance run --task=<task>
" 来手动运行特定的维护任务。maintenance.<task>.enabled
' 选项可以打开这些其他任务(或关闭 'gc
' 任务)。
git config
现在在其man页面中包含以下内容:
maintenance.<task>.enabled
这个布尔配置选项控制是否运行名为
<task>
的维护任务,当没有指定--task
选项时,该任务会被运行到git maintenance run
。如果存在--task
选项,则忽略这些配置值。
默认情况下,只有maintenance.gc.enabled
为true。
git maintenance
现在在其man页面中包括以下内容:
运行一个或多个维护任务。如果指定了一个或多个
--task
选项,则按照指定的顺序运行这些任务。否则,任务由哪些maintenance.<task>.enabled
配置选项为true来确定。
默认情况下,只有maintenance.gc.enabled
为true。
git维护
现在也在其手册页面中包括以下内容:
如果没有指定
--task=<task>
参数,则仅考虑已配置为true
的maintenance.<task>.enabled
任务。
另一种判断新的 git maintenance run
是否在执行任务的方法是检查锁定文件 (.git/maintenance.lock
):
在Git仓库上执行维护操作会涉及写入数据到
maintenance
: 在对象目录上获取锁定签名:Derrick Stolee
.git
目录,这个过程不适合多个写入者同时进行。通过持有基于文件的锁,确保只有一个 'git maintenance
'(man) 进程正在运行。.git/maintenance.lock
文件将阻止未来的维护操作。该锁定永远不会被提交,因为它不代表有意义的数据,而只是一个占位符。git fetch
'(man) 和 'git maintenance run --auto
(man)' 之间创建递归进程循环的临时措施。
git gc
/git maintenance
是否需要执行任何操作。git gc
"(man)来处理更多的仓库维护任务,不仅限于对象数据库清理。derrickstolee
) 提交。gitster
-- 在commit 48794ac 中合并,日期为2020年9月25日)
维护
:使用指针检查--auto
签名作者:Derrick Stolee
'git maintenance run
(man)'命令有一个'--auto'选项。其他Git命令,如'git commit
(man)'或'git fetch
(man)'会使用此选项来检查是否应在向存储库添加数据后运行维护操作。git gc
'(man)命令中作为'gc'任务的一部分。我们将扩展其他任务以执行检查,看看它们是否应该作为'--auto'标志的一部分执行工作,当它们通过配置启用时。git gc --auto
'(man)命令。它还为其他任务提供了一个模型。git gc
'(man)命令,因为'gc.autoDetach'配置选项会更改行为。可能,我们希望将由'gc.autoDetach'暗示的守护进程行为吸收为'maintenance.autoDetach'配置选项。
为了说明git maintenance
与git gc
的区别:
maintenance
: 添加提交图任务签名作者:Derrick Stolee
The first new task in the '
git maintenance
(man) ' builtin is the 'commit-graph
' task.
This updates the commit-graph file incrementally with the commandgit commit-graph write --reachable --split
By writing an incremental commit-graph file using the "
--split
" option we minimize the disruption from this operation.The default behavior is to merge layers until the new "top" layer is less than half the size of the layer below. This provides quick writes most of the time, with the longer writes following a power law distribution.
Most importantly, concurrent Git processes only look at the commit-graph-chain file for a very short amount of time, so they will very likely not be holding a handle to the file when we try to replace it. (This only matters on Windows.)
If a concurrent process reads the old commit-graph-chain file, but our job expires some of the
.graph
files before they can be read, then those processes will see a warning message (but not fail). This could be avoided by a future update to use the--expire-time
argument when writing the commit-graph.
git maintenance
现在在其手册页中包括:
commit-graph
commit-graph
作业会增量更新commit-graph
文件,然后验证写入的数据是否正确。增量写入可以安全地与并发Git进程一起运行,因为它不会过期上一个
commit-graph-chain
文件中的.graph
文件。它们将根据到期延迟在稍后的运行中被删除。
还有:
在每个 '
maintenance
:为commit-graph
任务添加自动条件签名作者:Derrick Stolee
git maintenance run --auto
'(man) 进程中(当配置了 maintenance.commit-graph.enabled
为 true
时),不再写入新的 commit-graph
,只有在“足够”数量的提交不在 commit-graph
文件中时才会进行写入。此计数由 maintenance.commit-graph.auto
配置选项控制。要计算此计数,请从每个引用开始进行深度优先搜索,并使用 SEEN
标记留下标记。如果此计数达到限制,则提前终止并开始任务。否则,此操作将剥离每个引用并解析其指向的提交。如果这些都在 commit-graph
中,则通常是非常快速的操作。具有许多引用的用户可能会感到减速,因此可以考虑将其限制更新为非常小的值。负值将强制运行该步骤每次运行。现在,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日)
维护
: 测试提交图自动条件Signed-off-by: Derrick Stolee
commit-graph
维护任务的自动条件会查找不在commit-graph
文件中的提交。
这是在4ddc79b2("maintenance
: add auto condition for commit-graph task",2020年9月17日,Git v2.29.0-rc0 -- batch #17中列出的merge)中添加的,但未经测试。此更改的初始目标是通过添加测试来展示功能正常工作。但是,存在一个偏移错误,导致基本测试
maintenance.commit-graph.auto=1
失败,而实际上应该成功。微妙之处在于,如果引用尖端不在
commit-graph
中,则我们不会将其添加到总计数中。在测试中,我们看到自上次commit-graph写入以来只添加了一个提交,因此自动条件会说没有任何事情要做。修复很简单:在开始遍历之前添加
commit-graph
位置的检查,以查看尖端是否在commit-graph
文件中。由于这是在添加到DFS堆栈之前发生的,因此我们不需要清除我们(当前为空的)提交列表。这确实为测试增加了一些额外的复杂性,因为我们还想验证沿父项的遍历实际上会做一些工作。这意味着我们需要连续添加至少两个提交,而不编写
commit-graph
。但是,我们还需要确保没有其他引用指向此列表的中间部分,否则should_write_commit_graph()
中的for_each_ref()
可能会将这些提交作为尖端访问,而不是进行DFS遍历。因此,最后两个提交是使用"git commit
"(man)而不是"test_commit"
添加的。
git maintenance
(man) run/start/stop" 来持有他们使用的锁定文件,但没有确保他们实际上在存储库中,这已经得到了纠正。
请查看 Josh Steadmon(steadmon
)于2020年12月8日提交的提交0a1f2d0。
请查看Rafael Silva(raffs
)于2020年11月26日提交的提交e72f7de。
(由Junio C Hamano -- gitster
--在提交f2a75cb中合并,2020年12月8日)
"
维护
: 修复没有仓库时的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"
构建,当我们没有可用的存储库时,会导致SEGFAULT,因为"`the_repository->objects->odb`"设置为NULL
。RUN_SETUP
选项,它将提供验证并在在存储库外运行时失败,从而修复所有三个操作的SEGFAULT,并使所有子命令的行为一致。RUN_SETUP
也为所有子命令提供了相同的保护,因为“register”和“unregister”也需要在存储库内执行。在Git 2.30(2021年第一季度),扩展版的 "git maintenance
"(man),即 "git gc
"(man) 的大兄弟,在 上一个答案 中介绍的基础上不断发展。
它比 git gc
更精确,2.30引入的选项允许了解它何时完成操作,正如OP所要求的那样。
请查看 提交 e841a79, 提交 a13e3d0, 提交 52fe41f, 提交 efdd2f0, 提交 18e449f, 提交 3e220e6, 提交 252cfb7, 提交 28cb5e6 (2020年9月25日) 由 Derrick Stolee (derrickstolee
) 提交。
(由Junio C Hamano -- gitster
--合并于提交 52b8c8c,2020年10月27日)
先前的更改使用可以安全在后台运行的 'loose-objects' 清理了松散对象。添加一个类似的任务,执行类似清理打包文件的任务。
维护
:添加增量重打包任务签名作者:Derrick Stolee
git repack
(man)' 的一个问题是它被设计成将所有包文件重新打包为单个包文件。虽然这是存储对象数据最节省空间的方式,但它不够时间或内存有效。如果仓库太大,用户无法在磁盘上存储两份包副本,则这变得非常重要。git multi-pack-index expire
(man) ' 在 19575c7 ("multi-pack-index
: implement 'expire' subcommand", 2019-06-10, Git v2.23.0-rc0 -- merge listed in batch #6) 和 'git multi-pack-index repack
(man) ' 在 ce1e4a1 ("midx
: implement midx_repack()
", 2019-06-10, Git v2.23.0-rc0 -- merge listed in batch #6) 加入以来,多包索引使这个过程更加容易。git multi-pack-index write
(man)'如果不存在,则创建一个多包索引文件,并更新多包索引以包含自上次写入以来出现的任何新包文件。当多包索引看到同一对象的两个副本时,它将偏移数据存储在较新的包文件中。这意味着一些旧的包文件可能变为“未引用”,我将使用它来表示“多包索引的包文件列表中,没有一个对象引用该包文件内的任何位置”的包文件。
2. 'git multi-pack-index expire
(man)'删除任何未引用的包文件,并从列表中删除这些包文件。这是安全的,因为并发 Git 进程会看到多包索引,并且在查找对象内容时不会打开这些包。 (与“loose-objects”作业类似,有一些 Git 命令无论如何都会打开包文件,但它们很少使用。此外,自行选择使用后台操作的用户可能会避免使用这些命令)。
3. 'git multi-pack-index repack --batch-size=<size>
(man)' 收集多包索引中列出的一组包文件,并创建一个包含多包索引中偏移量在这些包中的对象的新包文件。通过按修改时间对包文件进行排序并将包文件添加到集合中,如果其“期望大小”小于批处理大小,则选择一组包文件,直到所选包文件的总期望大小至少为批处理大小。计算“预期大小”的方法是将包文件的大小除以包文件中的对象数,然后乘以具有该包文件中偏移量的多包索引中的对象数。预期大小近似于来自该包文件的数据对生成的包文件大小的贡献。意图是生成的包文件大小接近提供的批处理大小。git maintenance
现在包含在其man页面中:
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
命令时删除那些小的打包文件。选择小的打包文件的方式是使得大的打包文件的预期大小至少为批量大小;请参考 git multi-pack-index
的 repack
子命令的 --batch-size
选项。默认批量大小为零,这是一种特殊情况,尝试将所有打包文件重新打包成一个单独的打包文件。
并且:
增量重打包任务通过删除已被新包替换的包文件,然后将一批小的包文件重新打包成一个较大的包文件来更新多包索引。这种增量重打包比重写所有对象数据要快,但比其他某些维护活动要慢。
维护
: 添加增量重打包自动条件署名: Derrick Stolee
maintenance.incremental-repack.auto
' 配置选项指定运行该步骤之前在多包索引之外应存在多少个包文件。git fetch
(man)' 命令或松散对象任务创建。--auto
' 选项禁用该任务,负值会使任务每次运行。
git config
现在在其手册页面中包括:
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 条目(和其他调度系统配置)。
请查看提交 0016b61, 提交 61f7a38, 提交 a4cb1a2 (2020年10月15日), 提交 2fec604, 提交 0c18b70, 提交 4950b2a, 提交 b08ff1f (2020年9月11日), 以及提交 1942d48 (2020年8月28日)由Derrick Stolee (derrickstolee
)提交。
(由Junio C Hamano -- gitster
--在提交 7660da1中合并,日期为2020年11月18日)
“
维护
:在文档中添加故障排除指南协助者:Junio C Hamano
签署者:Derrick Stolee
git maintenance run
(man)”子命令会在对象数据库上加锁,以防止并发进程竞争资源。这是一个重要的安全措施,以防止可能的存储库损坏和数据丢失。git maintenance
(man)”内置文档中添加一个“故障排除”部分,讨论这些权衡。git maintenance
现在包含在其手册页面中:
git maintenance
命令旨在简化仓库维护模式,同时在Git命令期间最小化用户等待时间。提供了各种配置选项以允许自定义此过程。默认的维护选项专注于快速完成的操作,即使在大型存储库上也是如此。git maintenance run
命令都会锁定存储库的对象数据库,这会阻止其他并发的git maintenance run
命令在同一存储库上运行。如果没有这个保护措施,则竞争进程可能会使存储库处于不可预测的状态。git maintenance run
进程。每次运行都会执行“hourly”任务。在午夜时分,该进程还会执行“daily”任务。在第一天的午夜,该进程还会执行“weekly”任务。单个进程迭代每个注册的存储库,为该频率执行计划任务。根据注册存储库的数量和大小,此过程可能需要比一个小时更长的时间。在这种情况下,多个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
。ele828
)于2021年9月24日提交)。已在commit b39b0e1中由Junio C Hamano -- gitster
--合并(于2021年10月6日)。 - VonC如果你正在监控git gc --auto
的退出状态(例如用于检测失败),那么该返回值已经在Git 2.20中发生了变化:
请参见提交记录3029970(由Jonathan Nieder(artagnon
)于2018年7月17日提交)。
协助者:Jeff King(peff
)。
(由Junio C Hamano -- gitster
--合并于提交记录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
git gc --auto
会失败(磁盘空间或oomkiller),并留下可以通过git pack-redundant --all | xargs rm
处理的东西,这些东西会很好地填满磁盘。我想我可以系统地运行git pack-redundant
吗? - Vincent Fourmond