提高git状态表现的方法

Sen*_*mar 71 git performance nfs

我在一台位于NFS上的Linux机器上有一个10 GB的仓库.第一次git status需要36分钟,之后git status需要8分钟.似乎Git依赖于操作系统来缓存文件.只有第一个git命令commit,status包括打包/重新包装整个回购需要很长时间才能获得巨大的回购.我不确定你是否曾经使用git status过这么大的回购,但有没有人遇到过这个问题?

我已经试过git gc,git clean,git repack但所花费的时间仍是/几乎是相同的.

子模块或任何其他概念,比如将repo打成较小的那些有帮助吗?如果是这样,那么最好分割更大的回购.有没有其他方法可以改善大型仓库上git命令的时间?

Jos*_*Lee 42

更确切地说,git取决于lstat(2)系统调用的效率,因此调整客户端的"属性缓存超时"可能会起到作用.

手册git-update-index- 基本上是手动模式git-status- 描述了通过使用--assume-unchanged标志来抑制其正常行为并手动更新已更改的路径,可以采取哪些措施来缓解这种情况.您甚至可以编程编辑器以在每次保存文件时取消设置此标志.

正如你的建议,替代方案是减少结账的大小(包文件的大小在这里并没有真正发挥作用).选项包括稀疏结帐,子模块或Google的repo工具.

(有一个关于在NFS上使用Git的邮件列表线程,但它没有回答很多问题.)

  • 你错过的东西:Linus的补丁实际上已经合并了,可以通过将`core.preloadindex`设置为true来启用它 - 请参阅[`git-config`](http://www.kernel.org/pub /software/scm/git/docs/git-config.html)文档以获取更多描述.(我的工作场所使用NFS,我遇到了这个问题 - 但从未注意到preloadindex设置.感谢您指出我正确的方法!) (28认同)
  • 'git config core.preloadindex true' 应添加到此处接受的答案中。可能带有来自 user1077329 的 -uno 标志 (2认同)
  • 从 Git 2.1.0 开始,`core.preloadindex` 标志默认设置为 true:https://git.kernel.org/pub/scm/git/git.git/tree/Documentation/RelNotes/2.1.0.txt (2认同)

小智 35

我也在通过NFS共享的大型项目上看到了这个问题.

我花了一些时间来发现可以赋予git commit和git status 的标志-uno.

此标志的作用是禁用查找未跟踪的文件.这显着减少了nfs操作的数量.原因是为了让git发现未跟踪的文件,它必须查看所有子目录,所以如果你有许多子目录,这将伤害你.通过禁用git查找未跟踪的文件,可以消除所有这些NFS操作.

将它与core.preloadindex标志相结合,即使在NFS上也可以获得合理的性能.


Jab*_*ari 27

试试git gc.另外,git clean 可能有所帮助.

更新 - 不确定向下投票的来源,但git手册明确指出:

在当前存储库中运行许多内务处理任务,例如压缩文件修订(以减少磁盘空间并提高性能)以及删除可能已从先前调用git add创建的无法访问的对象.

建议用户定期在每个存储库中运行此任务,以保持良好的磁盘空间利用率和良好的运行性能.

当git状态很慢时,我总是注意到运行git gc后的差异!

更新II - 不知道我是如何错过这个,但OP已经尝试了git gc和git clean.我发誓原本不是那里,但我没有看到编辑中的任何变化.对不起!

  • 我也不理解投票; 这真的很有帮助.`git gc`减少了`git log`在我的一个回购中从15秒运行到0的时间. (3认同)
  • 也许是因为OP指出它已被试过? (2认同)

ben*_*eno 17

如果您的git repo大量使用子模块,您可以通过编辑.git目录中的配置文件并设置ignore = dirty任何特别大/重的子模块来大大加快git状态的性能.例如:

[submodule "mysubmodule"]
url = ssh://mysubmoduleURL
ignore = dirty
Run Code Online (Sandbox Code Playgroud)

您将失去提醒的便利性,即您可能忘记的任何子模块中存在未分级的更改,但您仍然可以保留知道子模块何时与主存储库不同步的主要方便性.此外,您仍然可以将工作目录更改为子模块本身,并按常规使用git status以查看更多信息.有关"脏"含义的更多详细信息,请参阅此问题.


Von*_*onC 7

使用Git 2.13(2017年第2季度)可以改善git状态的表现.

请参阅Jeff Hostetler()提交的950a234(2017年4月14日).(由Junio C Hamano合并- -提交8b6bba6,2017年4月24日)jeffhostetler
gitster

> string-list:重新分配时使用ALLOC_GROWstring_list

ALLOC_GROW()在重新分配string_list数组时使用宏而不是简单地将其增加32.
这是性能优化.

在一个非常大的仓库的状态期间,有很多变化,总运行时间的很大一部分用于重新分配wt_status.changes阵列.

此更改会将wt_status_collect_changes_worktree()我非常大的存储库中的时间从125秒减少到45秒.


此外,Git 2.17(2018年第二季度)将引入一条新的轨迹,用于衡量在索引繁重的操作中花费的时间.

提交ca54d9b(2018年1月27日),由阮泰玉维战(pclouds).
(由Junio C gitsterHamano合并- -提交090dbea,2018年2月15日)

trace:衡量在索引繁重的操作中花费的时间

测量所有已知的重代码块(对象数据库访问除外).这应该有助于确定优化是否有效.
未经优化的git-status将提供如下内容:

0.001791141 s: read cache ...
0.004011363 s: preload index
0.000516161 s: refresh index
0.003139257 s: git command: ... 'status' '--porcelain=2'
0.006788129 s: diff-files
0.002090267 s: diff-index
0.001885735 s: initialize name hash
0.032013138 s: read directory
0.051781209 s: git command: './git' 'status'
Run Code Online (Sandbox Code Playgroud)

相同的Git 2.17(2018年第二季度)改进git status了:

revision.c:减少对象数据库查询

mark_parents_uninteresting(),我们检查是否存在目标文件,以查看是否应该将提交视为已解析.结果是在提交时设置"已解析"位.

修改条件以仅检查has_object_file()结果是否会更改已解析的位.

当本地分支与其上游引用不同时," git status"将计算前/后计数.
这使用paint_down_to_common()和命中mark_parents_uninteresting().

在远程分支""后面的本地"master"实例的Linux repo副本上,origin/master通过~60,000次提交,我们发现" git status" 的性能从1.42秒变为1.32秒,相对差异为-7.0%.


kli*_*mat 7

git config --global core.preloadIndex true

为我做了这份工作。请在此处查看官方文档。


小智 6

在我们的代码库中,我们有 20 - 30 个子模块,
git status --ignore-submodules
这大大加快了我的速度。请注意,这不会报告子模块的状态


dCS*_*ven 5

还没有提到的是,在 Windows 机器上激活文件系统缓存(Linux 文件系统完全不同,并且 git 针对它们进行了优化,因此这可能只在 Windows 上有帮助)。

git config core.fscache true
Run Code Online (Sandbox Code Playgroud)


作为最后的手段,如果 git 仍然很慢,可以关闭修改时间检查,即 git 需要找出哪些文件已更改。

git config core.ignoreStat true
Run Code Online (Sandbox Code Playgroud)

但是:更改后的文件必须由开发人员自己使用git add. Git 本身不会发现更改。

来源


Von*_*onC 5

在 Git 2.40(2023 年第 1 季度)中,更新了在枚举未跟踪路径需要很长时间时由“ git status( man )给出的建议消息。

它更好地说明了您可以应用以获得更快/更快的所有配置设置git status

请参阅Rudy Rigot ( )提交的 ecbc23e(2022 年 11 月 30 日)。(由Junio C Hamano 合并 -- --在2022 年 12 月 19 日提交 f3d9bc8中)rudyrigot
gitster

status:现代化 git-status“缓慢的未跟踪文件”建议

签署人:鲁迪·里戈特

git status当有大量未跟踪的文件和目录时( man )可能会很慢,因为 Git 必须搜索整个工作树来枚举它们。
当速度太慢时,Git 会打印包含已用搜索时间的建议以及使用该-uno选项禁用搜索的建议。
该建议还带有一个警告,可能会吓跑一些用户。

然而,如今,-uno这并不是唯一的选择。当启用和功能时,
Git 可以通过缓存先前调用的结果来减少枚举未跟踪文件所需的时间。git statuscore.untrackedCachecore.fsmonitor

更新git status手册页以解释这些配置选项,并更新建议以提供有关当前配置的更多详细信息并参考更新的文档。

git status现在包含在其手册页中:

未跟踪的文件和性能

git status如果/当需要搜索未跟踪的文件和目录时,在大型工作树中可能会非常慢。

有许多配置选项可以通过避免工作或利用以前 Git 命令的缓存结果来加速这一过程。
没有一套适合所有人的最佳设置。

我们将列出相关选项的摘要来帮助您,但在进入列表之前,您可能需要git status 再次运行,因为您的配置可能已经缓存git status 结果,因此后续运行可能会更快。

  • 标志--untracked-files=nostatus.showUntrackedfiles=false配置(两者均见上文):指示不应git status报告未跟踪的文件。这是最快的选择。git status不会列出未跟踪的文件,因此您需要小心记住是否创建了任何新文件并手动创建git add它们。

  • advice.statusUoption=false(请参阅git config):设置此变量以false禁用在枚举未跟踪文件花费超过 2 秒时给出的警告消息。在大型项目中,可能需要更长的时间,并且用户可能已经接受了权衡(例如,使用“-uno”可能不是用户可接受的选项),在这种情况下,没有必要发出警告消息,在这种情况下,禁用警告可能是最好的选择。

  • core.untrackedCache=true(请参阅git update-index):启用未跟踪的缓存功能,并且仅搜索自上一个命令以来已修改的目录git status
    Git 会记住每个目录中未跟踪的文件集,并假设如果目录未被修改,则其中的未跟踪文件集不会更改。

    这比枚举每个目录的内容要快得多,但仍然不是没有成本,因为 Git 仍然需要搜索已修改的目录集。未跟踪的缓存存储在 .git/index文件中。搜索未跟踪文件的成本降低被索引大小的增加和保持其最新的成本略微抵消。减少的搜索时间通常值得额外的大小。

  • core.untrackedCache=truecore.fsmonitor=truecore.fsmonitor=<hook_command_pathname>(请参阅 git update-index):启用未跟踪的缓存和 FSMonitor 功能,并且仅搜索自上一个命令以来已修改的目录git status

    这比单独使用未跟踪的缓存更快,因为 Git 还可以避免搜索已修改的目录。
    Git 只需枚举最近更改的确切目录集。虽然可以在没有未跟踪缓存的情况下启用 FSMMonitor 功能,但在这种情况下,好处会大大降低。

请注意,打开未跟踪的缓存和/或 FSMonitor 功能后,可能需要执行一些git status命令才能使各种缓存预热,然后才能看到命令时间的缩短。
这个是正常的。