English ▾ 主题 ▾ 最新版本 ▾ git-maintenance 上次更新于 2.47.1

名称

git-maintenance - 运行任务来优化 Git 仓库数据

概要

git maintenance run [<options>]
git maintenance start [--scheduler=<scheduler>]
git maintenance (stop|register|unregister) [<options>]

描述

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

诸如 git addgit fetch 之类的添加仓库数据的 Git 命令针对响应迅速的用户体验进行了优化。 这些命令不会花费时间来优化 Git 数据,因为此类优化会随着仓库的完整大小而扩展,而这些用户命令各自执行相对较小的操作。

git maintenance 命令为如何优化 Git 仓库提供了灵活性。

子命令

run

运行一个或多个维护任务。 如果指定了一个或多个 --task 选项,则按该顺序运行这些任务。 否则,任务由哪些 maintenance.<task>.enabled 配置选项为 true 确定。 默认情况下,只有 maintenance.gc.enabled 为 true。

start

开始在当前仓库上运行维护。 这执行与 register 子命令相同的配置更新,然后更新后台调度程序以每小时运行一次 git maintenance run --scheduled

stop

停止后台维护计划。 当前仓库不会从维护的仓库列表中删除,以防以后重新启动后台维护。

register

初始化 Git 配置值,以便任何计划的维护都将在此仓库上开始运行。 这会将仓库添加到当前用户的全局配置或由 --config-file 选项指定的配置中的 maintenance.repo 配置变量中,并为 maintenance.<task>.schedule 启用一些建议的配置值。 启用的任务可以安全地在后台运行,而不会中断前台进程。

如果先前未设置 maintenance.strategy 配置值,则 register 子命令还会将该值设置为 incrementalincremental 策略对每个维护任务使用以下计划

  • gc: 禁用。

  • commit-graph: 每小时。

  • prefetch: 每小时。

  • loose-objects: 每天。

  • incremental-repack: 每天。

git maintenance register 还会通过在当前仓库中设置 maintenance.auto = false 来禁用前台维护。 此配置设置将在 git maintenance unregister 命令后保留。

unregister

从后台维护中删除当前仓库。 这只会从配置的列表中删除仓库。 它不会停止后台维护进程的运行。

如果当前仓库尚未注册,则 unregister 子命令将报告错误。 即使当前仓库未注册,也可以使用 --force 选项返回成功。

任务

commit-graph

commit-graph 作业以增量方式更新 commit-graph 文件,然后验证写入的数据是否正确。 增量写入可以与并发 Git 进程一起安全运行,因为它不会使以前的 commit-graph-chain 文件中的 .graph 文件过期。 它们将在稍后基于过期延迟的运行中删除。

prefetch

prefetch 任务使用来自所有已注册远程仓库的最新对象更新对象目录。 对于每个远程仓库,都会运行 git fetch 命令。 配置的 refspec 已被修改,以将所有请求的引用放置在 refs/prefetch/ 中。 此外,不会更新标签。

这样做是为了避免中断远程跟踪分支。 最终用户希望这些引用保持不动,除非他们启动提取。 但是,通过预取任务,已经获得了完成以后真正的提取所需的对象,从而使真正的提取更快。 在理想情况下,它将只变成一堆远程跟踪分支的更新,而没有任何对象传输。

可以使用 remote.<name>.skipFetchAll 配置来排除特定的远程仓库不进行预取。

gc

清理不必要的文件并优化本地仓库。“GC”代表“垃圾回收”,但是此任务执行许多较小的任务。 对于大型仓库而言,此任务可能会很昂贵,因为它会将所有 Git 对象重新打包到单个 pack-file 中。 在某些情况下,它也可能会造成中断,因为它会删除过时的数据。 有关 Git 中垃圾回收的更多详细信息,请参见 git-gc[1]

loose-objects

loose-objects 作业清理松散对象并将它们放入 pack-file 中。 为了防止与并发 Git 命令发生竞争情况,它遵循一个两步过程。 首先,它删除 pack-file 中已存在的任何松散对象; 并发 Git 进程将检查 pack-file 以获取对象数据,而不是松散对象。 其次,它创建一个新的 pack-file(以“loose-”开头),其中包含一批松散对象。 批处理大小限制为 5 万个对象,以防止该作业在具有许多松散对象的仓库上花费太长时间。 gc 任务将无法访问的对象写为松散对象,以便仅当它们没有重新添加到 pack-file 时才由后面的步骤清除; 因此,不建议同时启用 loose-objectsgc 任务。

incremental-repack

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

pack-refs

pack-refs 任务收集松散的引用文件并将它们收集到单个文件中。 这加快了需要迭代许多引用的操作。 有关更多信息,请参见 git-pack-refs[1]

选项

--auto

run 子命令结合使用时,仅当满足某些阈值时才运行维护任务。 例如,当松散对象的数量超过存储在 gc.auto 配置设置中的数量时,或者当 pack-file 的数量超过 gc.autoPackLimit 配置设置时,将运行 gc 任务。 与 --schedule 选项不兼容。

--schedule

run 子命令结合使用时,仅当满足某些时间条件时才运行维护任务,如每个 <task>maintenance.<task>.schedule 配置值所指定。 此配置值根据 maintenance.<task>.lastRun 配置值指定自上次运行该任务以来的秒数。 测试的任务是那些由 --task=<task> 选项提供的任务,或者是那些将 maintenance.<task>.enabled 设置为 true 的任务。

--quiet

不要通过 stderr 报告进度或其他信息。

--task=<task>

如果多次指定此选项,则仅按指定的顺序运行指定的任务。 如果未指定任何 --task=<task> 参数,则仅考虑将 maintenance.<task>.enabled 配置为 true 的任务。 有关接受的 <task> 值列表,请参见任务部分。

--scheduler=auto|crontab|systemd-timer|launchctl|schtasks

start 子命令结合使用时,指定用于运行 git maintenance run 的 hourly、daily 和 weekly 执行的计划程序。<scheduler> 的可能值为 autocrontab (POSIX)、systemd-timer (Linux)、launchctl (macOS) 和 schtasks (Windows)。当指定 auto 时,将使用适当的平台特定计划程序;在 Linux 上,如果可用,则使用 systemd-timer,否则使用 crontab。默认为 auto

故障排除

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

以下部分描述了通过 git maintenance start 运行后台维护的机制以及如何自定义它们。

POSIX 系统上的后台维护

在 POSIX 系统上安排后台任务的标准机制是 cron(8)。此工具根据给定的计划执行命令。可以通过运行 crontab -l 找到当前用户计划的任务列表。git maintenance start 写入的计划类似于以下内容

# BEGIN GIT MAINTENANCE SCHEDULE
# The following schedule was created by Git
# Any edits made in this region might be
# replaced in the future by a Git command.

0 1-23 * * * "/<path>/git" --exec-path="/<path>" for-each-repo --config=maintenance.repo maintenance run --schedule=hourly
0 0 * * 1-6 "/<path>/git" --exec-path="/<path>" for-each-repo --config=maintenance.repo maintenance run --schedule=daily
0 0 * * 0 "/<path>/git" --exec-path="/<path>" for-each-repo --config=maintenance.repo maintenance run --schedule=weekly

# END GIT MAINTENANCE SCHEDULE

注释用作区域,用于将计划标记为由 Git 编写。此区域内的任何修改都将被 git maintenance stop 完全删除或被 git maintenance start 覆盖。

crontab 条目指定 git 可执行文件的完整路径,以确保执行的 git 命令与发出 git maintenance start 的命令相同,而与 PATH 无关。如果同一用户使用多个 Git 可执行文件运行 git maintenance start,则仅使用最新的可执行文件。

这些命令使用 git for-each-repo --config=maintenance.repo 在多值 maintenance.repo 配置选项中列出的每个存储库上运行 git maintenance run --schedule=<frequency>。这些通常从用户特定的全局配置加载。然后,git maintenance 进程使用 maintenance.<task>.schedule 配置选项确定配置为在每个存储库上以每个 <frequency> 运行的维护任务。这些值从全局或存储库配置值加载。

如果配置值不足以实现您所需的后台维护计划,则可以创建自己的计划。如果您运行 crontab -e,则编辑器将加载您用户特定的 cron 计划。在该编辑器中,您可以添加自己的计划行。您可以首先调整前面列出的默认计划,也可以阅读 crontab(5) 文档以获取高级计划技术。请使用默认计划中的完整路径和 --exec-path 技术,以确保您在计划中执行正确的二进制文件。

LINUX SYSTEMD 系统上的后台维护

虽然 Linux 支持 cron,但根据发行版,cron 可能是未必须安装的可选包。在现代 Linux 发行版上,systemd 定时器正在取代它。

如果用户 systemd 定时器可用,它们将被用作 cron 的替代品。

在这种情况下,git maintenance start 将创建用户 systemd 定时器单元并启动定时器。可以通过运行 systemctl --user list-timers 找到当前用户计划的任务列表。git maintenance start 写入的定时器类似于以下内容

$ systemctl --user list-timers
NEXT                         LEFT          LAST                         PASSED     UNIT                         ACTIVATES
Thu 2021-04-29 19:00:00 CEST 42min left    Thu 2021-04-29 18:00:11 CEST 17min ago  git-maintenance@hourly.timer git-maintenance@hourly.service
Fri 2021-04-30 00:00:00 CEST 5h 42min left Thu 2021-04-29 00:00:11 CEST 18h ago    git-maintenance@daily.timer  git-maintenance@daily.service
Mon 2021-05-03 00:00:00 CEST 3 days left   Mon 2021-04-26 00:00:11 CEST 3 days ago git-maintenance@weekly.timer git-maintenance@weekly.service

为每个 --schedule=<frequency> 选项注册一个定时器。

可以在以下文件中检查 systemd 单元的定义

~/.config/systemd/user/git-maintenance@.timer
~/.config/systemd/user/git-maintenance@.service
~/.config/systemd/user/timers.target.wants/git-maintenance@hourly.timer
~/.config/systemd/user/timers.target.wants/git-maintenance@daily.timer
~/.config/systemd/user/timers.target.wants/git-maintenance@weekly.timer

git maintenance start 将覆盖这些文件并再次使用 systemctl --user 启动定时器,因此任何自定义都应通过创建 drop-in 文件来完成,即 ~/.config/systemd/user/git-maintenance@.service.d 目录中带有 .conf 后缀的文件。

git maintenance stop 将停止用户 systemd 定时器并删除上述文件。

有关更多详细信息,请参见 systemd.timer(5)

MACOS 系统上的后台维护

虽然 macOS 在技术上支持 cron,但使用 crontab -e 需要提升的权限,并且执行的进程没有完整的用户上下文。如果没有完整的用户上下文,Git 及其凭证助手无法访问存储的凭证,因此某些维护任务无法正常工作。

相反,git maintenance startlaunchctl 工具交互,这是在 macOS 中安排定时作业的推荐方法。通过 git maintenance (start|stop) 安排维护需要一些仅在 macOS 10.11 或更高版本中可用的 launchctl 功能。

您用户特定的计划任务存储为 XML 格式的 .plist 文件,位于 ~/Library/LaunchAgents/ 中。您可以使用以下命令查看当前注册的任务

$ ls ~/Library/LaunchAgents/org.git-scm.git*
org.git-scm.git.daily.plist
org.git-scm.git.hourly.plist
org.git-scm.git.weekly.plist

为每个 --schedule=<frequency> 选项注册一个任务。要检查 XML 格式如何描述每个计划,请在编辑器中打开这些 .plist 文件之一,并检查 <key>StartCalendarInterval</key> 元素后面的 <array> 元素。

git maintenance start 将覆盖这些文件并再次使用 launchctl 注册任务,因此任何自定义都应通过创建具有不同名称的自己的 .plist 文件来完成。同样,git maintenance stop 命令将取消注册 launchctl 中的任务并删除 .plist 文件。

要对您的后台任务进行更高级的自定义,请参阅 launchctl.plist(5) 以获取更多信息。

WINDOWS 系统上的后台维护

Windows 不支持 cron,而是拥有自己的用于安排后台任务的系统。git maintenance start 命令使用 schtasks 命令将任务提交到此系统。您可以使用任务计划程序应用程序检查所有后台任务。Git 添加的任务具有 Git Maintenance (<frequency>) 形式的名称。任务计划程序 GUI 提供了检查这些任务的方法,但您也可以将任务导出到 XML 文件并在其中查看详细信息。

请注意,由于 Git 是一个控制台应用程序,因此这些后台任务会创建一个对当前用户可见的控制台窗口。可以通过在任务计划程序中选择“无论用户是否登录都要运行”选项来手动更改此设置。此更改需要密码输入,这就是 git maintenance start 默认不选择它的原因。

如果您想自定义后台任务,请重命名这些任务,以便将来调用 git maintenance (start|stop) 不会覆盖您的自定义任务。

配置

本节中此行以下的所有内容都从 git-config[1] 文档中有选择地包含。内容与其中找到的内容相同

maintenance.auto

此布尔配置选项控制某些命令在完成其正常工作后是否运行 git maintenance run --auto。默认为 true。

maintenance.autoDetach

许多 Git 命令在将数据写入存储库后会触发自动维护。此布尔配置选项控制此自动维护是在前台发生,还是维护过程应分离并在后台继续运行。

如果未设置,则将使用 gc.autoDetach 的值作为回退。如果两者都未设置,则默认为 true,这意味着维护过程将分离。

maintenance.strategy

此字符串配置选项提供了一种指定几个推荐的后台维护计划之一的方法。这仅影响在 git maintenance run --schedule=X 命令期间运行哪些任务,前提是没有提供 --task=<task> 参数。此外,如果设置了 maintenance.<task>.schedule 配置值,则使用该值,而不是 maintenance.strategy 提供的值。可能的策略字符串为

  • none: 此默认设置意味着在任何计划中都不运行任何任务。

  • incremental: 此设置优化用于执行不删除任何数据的小型维护活动。这不会安排 gc 任务,但会每小时运行 prefetchcommit-graph 任务,每天运行 loose-objectsincremental-repack 任务,每周运行 pack-refs 任务。

maintenance.<task>.enabled

此布尔配置选项控制在没有为 git maintenance run 指定 --task 选项时,是否运行名称为 <task> 的维护任务。如果存在 --task 选项,则忽略这些配置值。默认情况下,只有 maintenance.gc.enabled 为 true。

maintenance.<task>.schedule

此配置选项控制给定的 <task> 是否在 git maintenance run --schedule=<frequency> 命令期间运行。该值必须是“hourly”、“daily”或“weekly”之一。

maintenance.commit-graph.auto

这个整数配置选项控制着作为 git maintenance run --auto 的一部分,commit-graph 任务应该运行的频率。如果为零,则 commit-graph 任务将不会使用 --auto 选项运行。负值将强制任务每次都运行。否则,正值表示当不在 commit-graph 文件中的可达提交的数量至少为 maintenance.commit-graph.auto 的值时,该命令应该运行。默认值为 100。

maintenance.loose-objects.auto

这个整数配置选项控制着作为 git maintenance run --auto 的一部分,loose-objects 任务应该运行的频率。如果为零,则 loose-objects 任务将不会使用 --auto 选项运行。负值将强制任务每次都运行。否则,正值表示当 loose 对象(零散对象)的数量至少为 maintenance.loose-objects.auto 的值时,该命令应该运行。默认值为 100。

maintenance.incremental-repack.auto

这个整数配置选项控制着作为 git maintenance run --auto 的一部分,incremental-repack 任务应该运行的频率。如果为零,则 incremental-repack 任务将不会使用 --auto 选项运行。负值将强制任务每次都运行。否则,正值表示当不在 multi-pack-index 中的 pack-files 的数量至少为 maintenance.incremental-repack.auto 的值时,该命令应该运行。默认值为 10。

GIT

属于 git[1] 套件的一部分

scroll-to-top