You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Git 2.36.1未跟踪缓存失效及git status性能优化问题

Mac端Git操作性能异常排查与解决

问题现象

  • 运行环境:Mac设备,初始使用Git 2.35.1版本
  • 初始性能表现:克隆仓库后枚举未跟踪文件耗时7秒,执行time git status耗时约2秒;切换其他分支耗时约15秒,切回主分支后git status耗时达15秒,远超出正常预期。
  • 版本升级后异常:升级到Git 2.36.1版本后,原有未跟踪缓存优化方案失效,所有分支下Git相关操作耗时均达到20秒左右。

Git 2.35.1版本临时优化方案

该版本下可通过开启未跟踪缓存减少文件系统遍历开销,配置生效后git status耗时可优化至约4秒:

git config core.untrackedCache true
export GIT_FORCE_UNTRACKED_CACHE=1

该方案为社区通用的未跟踪缓存优化手段,核心逻辑是强制缓存未跟踪文件列表,避免每次执行状态查询时全量遍历工作区文件。

Git 2.36.1版本优化失效原因

对比两个版本dir.c源码中未跟踪缓存的判断逻辑,可见2.36.1版本调整了环境变量的默认取值规则:

Git 2.35.1版本dir.c相关逻辑

if (dir->untracked) {
        static int force_untracked_cache = -1;

        if (force_untracked_cache < 0)
            force_untracked_cache =
                git_env_bool("GIT_FORCE_UNTRACKED_CACHE", 0);
        if (force_untracked_cache &&
            dir->untracked == istate->untracked &&
            (dir->untracked->dir_opened ||
             dir->untracked->gitignore_invalidated ||
             dir->untracked->dir_invalidated))
            istate->cache_changed |= UNTRACKED_CHANGED;
        if (dir->untracked != istate->untracked) {
            FREE_AND_NULL(dir->untracked);
        }
    }

Git 2.36.1版本dir.c相关逻辑

if (dir->untracked) {
        static int force_untracked_cache = -1;

        if (force_untracked_cache < 0)
            force_untracked_cache =
                git_env_bool("GIT_FORCE_UNTRACKED_CACHE", -1);
        if (force_untracked_cache < 0)
            force_untracked_cache = (istate->repo->settings.core_untracked_cache == UNTRACKED_CACHE_WRITE);
        if (force_untracked_cache &&
            dir->untracked == istate->untracked &&
            (dir->untracked->dir_opened ||
             dir->untracked->gitignore_invalidated ||
             dir->untracked->dir_invalidated))
            istate->cache_changed |= UNTRACKED_CHANGED;
        if (dir->untracked != istate->untracked) {
            FREE_AND_NULL(dir->untracked);
        }
    }

逻辑差异点:2.36.1版本中,若未显式设置GIT_FORCE_UNTRACKED_CACHE环境变量,不会再默认取0值,而是回退读取core.untracked_cache配置判断是否允许写入缓存。旧方案中仅设置配置项+临时环境变量的组合,在切分支等场景下无法稳定触发缓存更新,最终导致优化失效。

性能瓶颈定位

通过GIT_TRACE_PERFORMANCE=1 git status采集全链路性能数据:

首次执行性能日志

12:44:54.433726 read-cache.c:2437       performance: 0.092473000 s: read cache .git/index
12:44:54.915510 read-cache.c:2480       performance: 0.481510000 s: read cache .git/sharedindex.f6119c27ffbee28b22e1baa47e66f355491292e
12:45:05.369546 preload-index.c:154     performance: 10.374954000 s: preload index
Refresh index: 100% (1164397/1164397), done.
12:45:05.421952 read-cache.c:1721       performance: 10.427363000 s: refresh index
12:45:05.464869 diff-lib.c:266          performance: 0.040042000 s:  diff-files
12:45:05.478549 unpack-trees.c:1884     performance: 0.000028000 s: traverse_trees
12:45:05.493406 unpack-trees.c:424      performance: 0.000008000 s:check_updates
12:45:05.493444 unpack-trees.c:1974     performance: 0.028052000 s: unpack_trees
12:45:05.493454 diff-lib.c:629          performance: 0.028099000 s:  diff-index
On branch default

Your branch is up to date with 'origin/default'.

首次执行时共享索引(.git/sharedindex.*)读取仅耗时0.48s,核心开销集中在preload index阶段,耗时10.37s。

切分支后返回default分支性能日志

GIT_TRACE_PERFORMANCE=1 git status
12:22:24.343325 read-cache.c:2437       performance: 0.112630000 s: read cache .git/index
12:22:42.618493 read-cache.c:2480       performance: 18.274836000 s:read cache .git/sharedindex.5ad8766e997830f32884b42ca5b17c2be6a19f1
12:22:53.559907 preload-index.c:154     performance: 10.840555000 s: preload index
Refresh index: 100% (1164397/1164397), done.
12:22:53.646110 read-cache.c:1721       performance: 10.926760000 s: refresh index
12:22:53.685650 diff-lib.c:266          performance: 0.038002000 s:  diff-files
12:22:53.713422 unpack-trees.c:1884     performance: 0.000042000 s: traverse_trees
12:22:53.726052 unpack-trees.c:424      performance: 0.000008000 s: check_updates
12:22:53.726085 unpack-trees.c:1974     performance: 0.028672000 s:unpack_trees
12:22:53.726094 diff-lib.c:629          performance: 0.039895000 s:  diff-index
12:23:03.568051 read-cache.c:3121       performance: 0.161937000 s: write index, changed mask = c
On branch default

Your branch is up to date with 'origin/default'.

You are in a sparse checkout with  tracked files present.
Changes not staged for commit:
 Modified:
 Modified:
….

切分支后共享索引读取耗时飙升至18.27s,成为第一大性能瓶颈。经确认,.git/sharedindex.*是开启core.splitindex=true配置后生成的共享索引文件,切分支时会生成新的全量共享索引,Mac文件系统下大体积共享索引的读取、校验开销极高,是导致性能异常的核心诱因。

可行临时解决方案

  • 关闭splitindex特性,消除共享索引开销:
git config core.splitindex false
rm -f .git/sharedindex.*

执行后索引回退为单文件模式,切分支时不会生成新的共享索引文件,可直接消除10s+的共享索引读取耗时。

  • 适配2.36+版本的未跟踪缓存规则:显式全局设置GIT_FORCE_UNTRACKED_CACHE=1环境变量(不依赖配置项的回退逻辑),同时强制刷新未跟踪缓存:
# 若使用zsh/bash,可将export命令写入shell配置文件永久生效
export GIT_FORCE_UNTRACKED_CACHE=1
git update-index --untracked-cache
git config core.untrackedCache true
  • 针对百万级文件的超大型仓库,额外开启文件系统监控,减少索引刷新阶段的文件元数据遍历开销:
git config core.fsmonitor true
git config core.untrackedCache true

内容的提问来源于stack exchange,提问作者checked

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 11:18:36