如何处理未跟踪的文件并提高 git status 性能

che*_*ked 5 git git-config

我目前在 Mac 上。

\n

在 Git 2.35.1 中,当我克隆存储库时,需要 7 秒来枚举未跟踪的文件,而当我这样做时time git status,大约需要 2 秒。\n而且,当我签出到其他分支时,大约需要 15 秒,而当我签出时,大约需要 15 秒。返回我的主仓库git status花了 15 秒(不应该花这么多时间)。

\n

(2.35.1) 中的解决方法是:\n我设置core.untrackedCache=trueGIT_FORCE_UNTRACKED_CACHE=1\n这有助于更新未跟踪的缓存并提高git status大多数 Stack Overflow 答案中提到的性能(大约 4 秒)。\n stack-溢出问题

\n

但现在在 Git 2.36.1 中,这种解决方法似乎不起作用。所有分支大约需要 20 秒。

\n

代码中可能的更改:

\n

在 Git 2.35.1 中,代码如下dir.c

\n
if (dir->untracked) {\n        static int force_untracked_cache = -1;\n\n        if (force_untracked_cache < 0)\n            force_untracked_cache =\n                git_env_bool("GIT_FORCE_UNTRACKED_CACHE", 0);\n        if (force_untracked_cache &&\n            dir->untracked == istate->untracked &&\n            (dir->untracked->dir_opened ||\n             dir->untracked->gitignore_invalidated ||\n             dir->untracked->dir_invalidated))\n            istate->cache_changed |= UNTRACKED_CHANGED;\n        if (dir->untracked != istate->untracked) {\n            FREE_AND_NULL(dir->untracked);\n        }\n    }\n
Run Code Online (Sandbox Code Playgroud)\n

与 Git 2.36.1 相同,代码如下dir.c

\n
if (dir->untracked) {\n        static int force_untracked_cache = -1;\n\n        if (force_untracked_cache < 0)\n            force_untracked_cache =\n                git_env_bool("GIT_FORCE_UNTRACKED_CACHE", -1);\n        if (force_untracked_cache < 0)\n            force_untracked_cache = (istate->repo->settings.core_untracked_cache == UNTRACKED_CACHE_WRITE);\n        if (force_untracked_cache &&\n            dir->untracked == istate->untracked &&\n            (dir->untracked->dir_opened ||\n             dir->untracked->gitignore_invalidated ||\n             dir->untracked->dir_invalidated))\n            istate->cache_changed |= UNTRACKED_CHANGED;\n        if (dir->untracked != istate->untracked) {\n            FREE_AND_NULL(dir->untracked);\n        }\n    }\n
Run Code Online (Sandbox Code Playgroud)\n

编辑1:

\n
GIT_TRACE_PERFORMANCE=1 git status\n\n12:44:54.433726 read-cache.c:2437       performance: 0.092473000 s: read cache .git/index\n12:44:54.915510 read-cache.c:2480       performance: 0.481510000 s: read cache .git/sharedindex.f6119c27ffbee28b22e1baa47e66f355491292e\n12:45:05.369546 preload-index.c:154     performance: 10.374954000 s: preload index\nRefresh index: 100% (1164397/1164397), done.\n12:45:05.421952 read-cache.c:1721       performance: 10.427363000 s: refresh index\n12:45:05.464869 diff-lib.c:266          performance: 0.040042000 s:  diff-files\n12:45:05.478549 unpack-trees.c:1884     performance: 0.000028000 s: traverse_trees\n12:45:05.493406 unpack-trees.c:424      performance: 0.000008000 s:check_updates\n12:45:05.493444 unpack-trees.c:1974     performance: 0.028052000 s: unpack_trees\n12:45:05.493454 diff-lib.c:629          performance: 0.028099000 s:  diff-index\nOn branch default\n\nYour branch is up to date with \'origin/default\'.\n
Run Code Online (Sandbox Code Playgroud)\n

当我切换分支并返回到默认分支时,下面是性能。我不知道为什么下面的 read-cache.c 花费了这么多时间!

\n
GIT_TRACE_PERFORMANCE=1 git status\n12:22:24.343325 read-cache.c:2437       performance: 0.112630000 s: read cache .git/index\n12:22:42.618493 read-cache.c:2480       performance: 18.274836000 s:read cache .git/sharedindex.5ad8766e997830f32884b42ca5b17c2be6a19f1\n12:22:53.559907 preload-index.c:154     performance: 10.840555000 s: preload index\nRefresh index: 100% (1164397/1164397), done.\n12:22:53.646110 read-cache.c:1721       performance: 10.926760000 s: refresh index\n12:22:53.685650 diff-lib.c:266          performance: 0.038002000 s:  diff-files\n12:22:53.713422 unpack-trees.c:1884     performance: 0.000042000 s: traverse_trees\n12:22:53.726052 unpack-trees.c:424      performance: 0.000008000 s: check_updates\n12:22:53.726085 unpack-trees.c:1974     performance: 0.028672000 s:unpack_trees\n12:22:53.726094 diff-lib.c:629          performance: 0.039895000 s:  diff-index\n12:23:03.568051 read-cache.c:3121       performance: 0.161937000 s: write index, changed mask = c\nOn branch default\n\nYour branch is up to date with \'origin/default\'.\n\nYou are in a sparse checkout with  tracked files present.\nChanges not staged for commit:\n Modified:\n Modified:\n\xe2\x80\xa6.\n
Run Code Online (Sandbox Code Playgroud)\n

编辑2:

\n

我做了一些研究,发现 .git/sharedindex。当我设置core.splitindex =true并且共享索引需要时间时创建。那么它与性能有什么关系吗?

\n

如何解决此未跟踪文件缓存性能问题?有什么解决方法吗?

\n

Von*_*onC 2

该更改来自提交 26b8946,我在“如何摆脱警告“未跟踪的缓存在此系统上被禁用。”中提出。
它修复了core.untrackedCache当设置为 时true,无法将未跟踪的缓存扩展添加到索引的设置。

在您的情况下,问题可能是自动将未跟踪的缓存扩展添加到索引中。

请参阅Derrick Stolee ( )的提交 26b8946(2022 年 2 月 17 日)。(由Junio C Hamano 合并 -- --提交 80f7f61中,2022 年 2 月 25 日)derrickstolee
gitster

dir:使用 core.untrackedCache 强制未跟踪缓存

签署人:Derrick Stolee

GIT_FORCE_UNTRACKED_CACHE环境变量比 core.untrackedCache 配置变量更频繁地写入未跟踪的缓存。
这是由于如何read_directory()处理未跟踪缓存的创建而导致的。

在此更改之前,Git 不会为尚不存在的索引创建未跟踪的缓存扩展。在索引实际包含未跟踪的缓存之前,
用户需要运行诸如“ git update-index --untracked-cache( man )之类的命令。

特别是,用户注意到即使使用core.untrackedCache=true.
一些用户报告了GIT_FORCE_UNTRACKED_CACHE=1其工程系统环境中的设置,以确保创建未跟踪的缓存。

在没有环境变量的情况下不写入未跟踪缓存的决定会追溯到fc9ecbe(“ dir.c:不要将索引标记为对未跟踪缓存的更改为脏”,2018-02-05,Git v2.17.0-rc0 --合并在第 8 批中列出)。
该更改的动机是写入索引的成本很高,如果未跟踪的缓存是唯一需要写入的内容,那么它比缓存的好处更昂贵。但是,这也意味着未跟踪的缓存永远不会被填充,因此通过配置启用它的用户在手动运行“ ”或使用环境变量
之前实际上不会获得扩展。git update-index --untracked-cache

microsoft/git我们现在已经在几个主要版本的分支中提供了此更改的版本。
它一直运作良好,让用户进入良好的状态。
是的,第一个索引写入很慢,但其余索引写入比没有此更改时要快得多。

因此,不要设置GIT_FORCE_UNTRACKED_CACHE为 1(保留core.untrackedCachetrue),而是取消设置,并尝试在orgit update-index --untracked-cache之前手动运行(它取代了用于切换分支的 git checkout )。 然后测试性能是否可以接受(再次强调,这只是一个测试,而不是最终的解决方法)。git statusgit switch