【问题标题】:git stash is slow on windowsgit stash 在 Windows 上运行缓慢
【发布时间】:2016-09-28 11:33:09
【问题描述】:

在我的 Windows 机器上,git stash 每次调用有大约 3.5 秒的开销,这给我的 git commit 钩子增加了大约 7 秒。

linux下(同一台机器)下相同的命令大约需要0.01秒。性能问题也适用于空存储库。

我从this threadthis thread 尝试了以下方法:

  • core.fscache 设置为 true
  • core.preloadindex 设置为 true
  • gc.auto 设置为 256
  • 设置 PS1='$'
  • 在管理模式下运行 cmd
  • cmd.exe 中运行而不是 git-bash

运行GIT_TRACE=true git stash list

16:58:16.844591 git.c:563               trace: exec: 'git-stash' 'list'
16:58:16.844591 run-command.c:336       trace: run_command: 'git-stash' 'list'
16:58:19.699591 git.c:350               trace: built-in: git 'rev-parse' '--git-dir'
16:58:19.859591 git.c:350               trace: built-in: git 'rev-parse' '--git-path' 'objects'
16:58:20.069591 git.c:350               trace: built-in: git 'rev-parse' '--show-toplevel'
16:58:20.154591 git.c:350               trace: built-in: git 'rev-parse' '--git-path' 'index'
16:58:20.244591 git.c:350               trace: built-in: git 'config' '--get-colorbool' 'color.interactive'
16:58:20.334591 git.c:350               trace: built-in: git 'config' '--get-color' 'color.interactive.help' 'red bold'
16:58:20.424591 git.c:350               trace: built-in: git 'config' '--get-color' '' 'reset'
16:58:20.514591 git.c:350               trace: built-in: git 'rev-parse' '--verify' '--quiet' 'refs/stash'

real    0m3.845s
user    0m0.000s
sys     0m0.047s

运行GIT_TRACE_PERFORMANCE=true git stash list

16:59:18.414591 trace.c:420             performance: 0.001078046 s: git command: 'C:\Program Files\Git\mingw64\libexec\git-core\git.exe' 'rev-parse' '--git-dir'                                          
16:59:18.569591 trace.c:420             performance: 0.000947184 s: git command: 'C:\Program Files\Git\mingw64\libexec\git-core\git.exe' 'rev-parse' '--git-path' 'objects'                               
16:59:18.779591 trace.c:420             performance: 0.001253627 s: git command: 'C:\Program Files\Git\mingw64\libexec\git-core\git.exe' 'rev-parse' '--show-toplevel'                                    
16:59:18.869591 trace.c:420             performance: 0.001285517 s: git command: 'C:\Program Files\Git\mingw64\libexec\git-core\git.exe' 'rev-parse' '--git-path' 'index'                                 
16:59:18.955591 trace.c:420             performance: 0.001139994 s: git command: 'C:\Program Files\Git\mingw64\libexec\git-core\git.exe' 'config' '--get-colorbool' 'color.interactive'                   
16:59:19.040591 trace.c:420             performance: 0.001182881 s: git command: 'C:\Program Files\Git\mingw64\libexec\git-core\git.exe' 'config' '--get-color' 'color.interactive.help' 'red bold'       
16:59:19.125591 trace.c:420             performance: 0.001128997 s: git command: 'C:\Program Files\Git\mingw64\libexec\git-core\git.exe' 'config' '--get-color' '' 'reset'                                
16:59:19.215591 trace.c:420             performance: 0.001567766 s: git command: 'C:\Program Files\Git\mingw64\libexec\git-core\git.exe' 'rev-parse' '--verify' '--quiet' 'refs/stash'                    
16:59:19.295591 trace.c:420             performance: 3.730583540 s: git command: 'C:\Program Files\Git\mingw64\bin\git.exe' 'stash' 'list'                                                                

real    0m3.819s                                                                                                                                                                                          
user    0m0.000s                                                                                                                                                                                          
sys     0m0.062s                                                                                                                                                                                          

从日志中我们看到,从运行 git-stash 命令到运行 git-rev-parse 大约需要 3 秒。我可以运行其他任何标志来查找瓶颈吗?

【问题讨论】:

  • 您的存储库可能很大,您可以尝试在本地和远程存储库上启动git gc 吗?
  • 在空存储库中花费相同的时间。我已经更新了问题。
  • 本地 git repo 是托管在本地驱动器上还是远程/网络上?
  • 如果你只是想让事情更快地工作,你可以尝试创建一个临时分支,在那里提交所有内容,你将获得与隐藏更改相同的效果(我经常这样做)。但是,如果您提出这个问题是为了更好地了解 stash 功能的工作原理,那么您可以查看 git 源代码:github.com/git/git

标签: windows git git-bash git-stash


【解决方案1】:

对于Git for Windows 2.19(2018 年 9 月),git stash(和 git rebase)不再是纯脚本,而是实际上是使用 git.exe 编译的二进制文件。
git-for-windows/build-extra PR 203

要激活它们,请输入

git config --global rebase.useBuiltin true
git config --global stash.useBuiltin true

警告

尽管加速效果不错,但相关补丁仍在不断变化,而且根本没有经过实战考验。

所以,目前,git stash 的脚本版本仍然是默认的,这样:

  • 希望我们通过三个并行工作的 Google Summer of Code 项目获得的原始速度改进的用户可以拥有,
  • 而其他不愿通过只运行经过良好测试的代码来扮演豚鼠的人可以保持安全。

重点仍然存在:在 Git 的下一个版本中,git-stash 的 bash 脚本最终会消失,并且它的替换速度会更快。

注意:下一个版本将是 Git 2.27(2020 年第二季度):“git stash”保留了一个逃生口,以便在几个版本中使用脚本版本,这些版本已经过时了。

它已被删除。

参见Thomas Gummerer (tgummerer)commit 8a2cd3fcommit b0c7362(2020 年 3 月 3 日)。
(由 Junio C Hamano -- gitster -- 合并到 commit 369ae75,2020 年 3 月 27 日)

stash:删除stash.useBuiltin 设置

签字人:Thomas Gummerer

删除 stash.useBuiltin 设置,该设置是作为逃生舱口添加的,以禁用首次随 Git 2.22 发布的内置版本的 stash。

携带旧版本是一种维护负担,事实上,自 2.23 版本以来,测试失败已经过时了,直到现在还没有人注意到。

因此,用户会得到提示,以回退到该工具可能存在错误的版本。

我们过去常常使用git config 来获取useBuiltin 配置,以避免在生成legacy-stash 之前更改任何全局状态。
但是,这不再是必需的,因此只需使用 'git_config' 函数来获取设置。

类似于我们在d03ebd411c 中所做的(“rebase:删除 rebase.useBuiltin 设置”,2019-03-18,Git v2.22.0-rc0 -- mergebatch #5 中列出),我们删除了 rebase 的相应设置,我们将文档保留在原处,这样人们在网上搜索时可以参考它,因此我们可以在提交消息中参考它。


2019 年第二季度更新,使用 Git 2.22,git stash 完全用 C 重写。 ² 见commit 40af146commit 48ee24acommit ef0f0b4commit 64fe9c2commit 1ac528ccommit d553f53commit d4788afcommit 41e0dd5commit dc7bd38,@9876543442@,@9876543442@,@9876543442@,@9876543442@ 987654345@(2019 年 2 月 25 日)Paul-Sebastian Ungureanu (weekly-digest[bot])
请参阅commit c4de61dcommit 577c199commit 4e2dd39commit 8a0fc8d(2019 年 2 月 25 日)Joel Teichroeb (klusark)
请参阅 Johannes Schindelin (dscho)commit 7906af0commit 90a4627commit 8d8e9c2(2019 年 2 月 25 日)。
(由 Junio C Hamano -- gitster -- 合并到 commit e36adf7,2019 年 4 月 22 日)

你仍然可以use the shell script with git legacy-stash

还有:

stash: convert stash--helper.c into stash.c

旧的 shell 脚本 git-stash.sh 已被删除并完全由 builtin/stash.c 替换。
为了做到这一点,createpush 适应了在没有 stash.sh 的情况下工作。

例如,在这次提交之前,git stash create 调用了git stash--helper create --message "$*"。如果它调用git stash--helper create "$@",那么 其中一些更改是不必要的。

此提交还删除了 helper 这个词,因为现在 stash 是 直接调用,而不是由 shell 脚本调用。

有优化:

stash: optimize get_untracked_files() and check_changes()

此提交通过避免调用 再次使用相同的功能。
例如,git stash push -u 会在某些时候调用以下函数:

  • check_changes()(在do_push_stash()内)
  • do_create_stash(),它调用:check_changes()get_untracked_files()

注意check_changes() 也调用get_untracked_files()
所以,check_changes() 被调用了 2 次,get_untracked_files() 3 次。

旧函数check_changes() 现在包含两个函数: get_untracked_files()check_changes_tracked_files()

这些是pushcreate 的调用链:

  • push_stash() -> do_push_stash() -> do_create_stash()
  • create_stash() -> do_create_stash()

为了防止反复调用相同的函数,do_create_stash() 内的 check_changes() 现在被放置在调用函数中(create_stash()do_push_stash())。
这样check_changes()get_untracked files() 被调用 只有一次。

【讨论】:

【解决方案2】:

git-stash 是一个脚本,而不是在git.exe 二进制文件中编译的命令。

在 linux 上:我可以在 /usr/lib/git-core/git-stash 找到 git-stash - 我会让你在 windows 上寻找正确的路径...


这个脚本使用#!/bin/sh运行,不知道你在windows上运行的时候用的是什么shell实现。

您可以尝试使用另一个兼容的 shell(这里:bash)运行它:

# the git-core/ dir needs to be in the PATH,
# obviously  you will need to provide the correct path for your git-core dir

$ PATH=/usr/lib/git-core:$PATH bash /usr/lib/git-core/git-stash

您还可以打开-x 标志,这将打印所有执行的命令的跟踪,并目视检查其中一个子命令是否似乎是挂起:

$ PATH=/usr/lib/git-core:$PATH bash -x /usr/lib/git-core/git-stash

【讨论】:

    猜你喜欢
    • 2017-09-04
    • 1970-01-01
    • 2018-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多