Git stash on windows 与 Libgit2 相比极慢

Git stash on windows extremly slow compared to Libgit2

最近我一直在使用 git stash 很多次,我一直认为它真的很慢,即使在只有一个文件的新存储库上也是如此。我已阅读 about git stash slowness and this other one 并尝试了这些问题的所有答案,但实际上没有任何效果。

例如,我已经完成了以下步骤来重现它:

  1. git init
  2. touch file.txt
  3. vim file.txt(编辑文件添加 2 行)
  4. git add .
  5. git commit -m "Initial commit"
  6. vim file.txt(再次编辑添加 1 行)
  7. time git stash

输出:

$ time git stash
Saved working directory and index state WIP on master: b9454ed Initial commit
HEAD is now at b9454ed Initial commit    
real    0m8.042s
user    0m0.000s
sys     0m0.046s

8 秒用于隐藏一行,时间太多了。 现在使用 libgit2sharp:

进行测试
static void Main(string[] args)
{
    Repository repo=new Repository(@"C:\Users\UserTest\TestGitRepo");

    repo.Stashes.Add(new Signature("test", "test@test.com", new DateTimeOffset(DateTime.Now)), "Stash on master");
}

此代码需要 74 毫秒来存储相同的更改。 如果 Libgit2 这么快,那么应该可以加速 git stash 命令。我怎样才能做到这一点?

实际使用 windows 10 64 位和 git 2.11 64 位。其他 git 命令(如状态、添加、提交等)工作正常。

更新:我已经更新到 git 2.13,现在 git stash 是 14,53s...

更新 2:我已经更新到 git 2.15 并尝试相同的测试 time git stash returns real 0m6,553s。还是很慢...

因为 Git 2.22

从 Git 2.22 开始,之前的实验性功能现已稳定且成为默认选项。

低于Git2.22

一年后,安装 Git 2.19 我在 git 安装期间看到一个复选框,用于启用新的 experimental 内置存储。

在我的例子中,它工作正常,我注意到与旧的实现(使用脚本)相比,性能有了 巨大的 改进,实际上它与使用linux.

中的相同命令

这里的结果遵循完全相同的步骤:

$ time git stash
Saved working directory and index state WIP on master: 7a29b92 Initial commit

real    0m0,120s
user    0m0,000s
sys     0m0,015s

要添加到现有答案,如果您已经安装了 2.19 或更高版本,则可以启用新功能:

git config --global stash.usebuiltin true

这也适用于便携版。

请注意,此功能似乎不适用于子模块。 https://github.com/git-for-windows/git/issues/1820

git stash will be faster with Git 2.25 (Q1 2020), where users of oneway_merge() (like "reset --hard") learned to take advantage of fsmonitor to avoid unnecessary lstat(2) 调用。

(自 2019 年第 2 季度 Git 2.22 起,,并且是默认值)

参见 commit 679f2f9 (20 Nov 2019) by Utsav Shah (Utsav2)
(由 Junio C Hamano -- gitster -- in commit 473b431 合并,2019 年 12 月 5 日)

unpack-trees: skip stat on fsmonitor-valid files

Helped-by: Junio C Hamano
Helped-by: Kevin Willford
Signed-off-by: Utsav Shah

The index might be aware that a file hasn't modified via fsmonitor, but unpack-trees did not pay attention to it and checked via ie_match_stat which can be inefficient on certain filesystems.
This significantly slows down commands that run oneway_merge, like checkout and git reset --hard.

This patch makes oneway_merge check whether a file is considered unchanged through fsmonitor and skips ie_match_stat on it.
unpack-trees also now correctly copies over fsmonitor validity state from the source index.
Finally, for correctness, we force a refresh of fsmonitor state in tweak_fsmonitor.

After this change, commands like stash (that use git reset --hard internally) go from 8s or more to ~2s on a 250k file repository on a mac.