简体   繁体   English

git stash 在 Windows 上运行缓慢

[英]git stash is slow on windows

On my windows machine git stash has about 3.5 seconds overhead on each invocation, which adds about 7 seconds to my git commit hook.在我的 Windows 机器上,每次调用git stash大约有 3.5 秒的开销,这为我的 git commit 钩子增加了大约 7 秒。

The same command under linux (same machine) takes about 0.01 seconds. linux(同一台机器)下同样的命令大约需要0.01秒。 The performance issue applies to empty repositories as well.性能问题也适用于空存储库。

I have tried the following from this thread and this thread :我已经从这个线程这个线程尝试了以下内容:

  • core.fscache is set to true core.fscache设置为true
  • core.preloadindex is set to true core.preloadindex设置为true
  • gc.auto is set to 256 gc.auto设置为256
  • Setting PS1='$ '设置 PS1='$'
  • Running cmd in administration mode在管理模式下运行 cmd
  • Running inside cmd.exe instead of git-bashcmd.exe而不是 git-bash 中运行

Running GIT_TRACE=true git stash list运行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

Running GIT_TRACE_PERFORMANCE=true git stash list运行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                                                                                                                                                                                          

From the log we see that it takes around 3 seconds between the git-stash command is run and the git-rev-parse is run.从日志中我们可以看到,在运行 git-stash 命令和运行 git-rev-parse 之间大约需要 3 秒。 Are there any other flags I can run to find the bottleneck?我可以运行任何其他标志来找到瓶颈吗?

With Git for Windows 2.19 (Sept. 2018), git stash (and git rebase ) are no longer script-only, but actually a binary compiled with git.exe .使用Git for Windows 2.19 (2018 年 9 月), git stash (和git rebase )不再是纯脚本,而是实际上是用git.exe编译的二进制文件。
See git-for-windows/build-extra PR 203 .请参阅git-for-windows/build-extra PR 203

To activate them, type要激活它们,请键入:

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

Warning :警告

As nice as the speed-ups are, the patches in question are still in flux, and they are not battle-tested at all.与加速一样好,有问题的补丁仍然在不断变化,它们根本没有经过实战测试。

So, for now, the script version of git stash remains the default, that way:所以,现在, git stash的脚本版本仍然是默认的,这样:

  • users who want the raw speed improvement we got through three Google Summer of Code projects working in parallel can have that,希望我们通过三个并行工作的 Google Summer of Code 项目获得原始速度改进的用户可以拥有,
  • while others who are reluctant to play guinea pig by running only well-tested code can stay on the safe side.而其他不愿意通过仅运行经过良好测试的代码来玩小白鼠的人可以保持安全。

The point remains: in the next versions of Git, the bash script for git-stash will eventually disappear, and its replacement is and will be faster.重点仍然是:在 Git 的下一个版本中, git-stash的 bash 脚本最终将消失,并且它的替代品将会更快。

Note: that next version will be Git 2.27 (Q2 2020): " git stash " has kept an escape hatch to use the scripted version for a few releases, which got stale.注意:下一个版本将是 Git 2.27(2020 年第 2 季度):“ git stash ”保留了一个逃生舱,以便在一些版本中使用脚本版本,但这些版本已经过时了。

It has been removed.它已被移除。

See commit 8a2cd3f , commit b0c7362 (03 Mar 2020) by Thomas Gummerer ( tgummerer ) .请参阅Thomas Gummerer ( tgummerer ) 提交 8a2cd3f提交 b0c7362 (2020 年 3 月 3 日
(Merged by Junio C Hamano -- gitster -- in commit 369ae75 , 27 Mar 2020) (由Junio C gitster合并-- gitster -- in commit 36​​9ae75 ,2020 年 3 月 27 日)

stash : remove the stash.useBuiltin setting stash :删除stash.useBuiltin设置

Signed-off-by: Thomas Gummerer签字人:Thomas Gummerer

Remove the stash.useBuiltin setting which was added as an escape hatch to disable the builtin version of stash first released with Git 2.22.删除stash.useBuiltin设置,该设置作为逃逸舱口添加以禁用首次随 Git 2.22 发布的内置版本的 stash。

Carrying the legacy version is a maintenance burden, and has in fact become out of date failing a test since the 2.23 release, without anyone noticing until now.携带旧版本是一种维护负担,事实上,自 2.23 版本以来,测试失败已经过时,直到现在没有人注意到。

So users would be getting a hint to fall back to a potentially buggy version of the tool.因此,用户会得到提示,可以退回到该工具的潜在错误版本。

We used to shell out to git config to get the useBuiltin configuration to avoid changing any global state before spawning legacy-stash.我们过去常常使用git config来获取useBuiltin配置,以避免在生成 legacy-stash 之前更改任何全局状态。
However that is no longer necessary, so just use the ' git_config ' function to get the setting instead.然而,这不再是必要的,所以只需使用 ' git_config ' 函数来获取设置。

Similar to what we've done in d03ebd411c (" rebase : remove the rebase.useBuiltin setting", 2019-03-18, Git v2.22.0-rc0 -- merge listed in batch #5 ), where we remove the corresponding setting for rebase, we leave the documentation in place, so people can refer back to it when searching for it online, and so we can refer to it in the commit message.类似于我们在d03ebd411c所做的(“ rebase : remove the rebase.useBuiltin setting”, 2019-03-18, Git v2.22.0-rc0 -- merge列在第 5 批中),我们删除了相应的设置rebase,我们保留文档,以便人们在网上搜索时可以参考它,因此我们可以在提交消息中参考它。


Update Q2 2019, with Git 2.22, git stash is entirely rewritten in C. ² See commit 40af146 , commit 48ee24a , commit ef0f0b4 , commit 64fe9c2 , commit 1ac528c , commit d553f53 , commit d4788af , commit 41e0dd5 , commit dc7bd38 , commit 130f269 , commit bef55dc , commit dac566c , commit ab8ad46 (25 Feb 2019) by Paul-Sebastian Ungureanu ( weekly-digest[bot] ) . 2019 年第 2 季度更新,使用 Git 2.22, git stash完全用 C 重写。 ² 参见commit 40af146commit 48ee24acommit ef0f0b4commit 64fe9c2commit 1ac528ccommit d553f53,8 commit d , 05dc commit3,8commit05dccommit d37commit d37 , commit dac566c , commit ab8ad46 (25 Feb 2019) by Paul-Sebastian Ungureanu ( weekly-digest[bot] )
See commit c4de61d , commit 577c199 , commit 4e2dd39 , commit 8a0fc8d (25 Feb 2019) by Joel Teichroeb ( klusark ) .请参阅Joel Teichroeb ( klusark ) 的commit c4de61dcommit 577c199commit 4e2dd39commit 8a0fc8d (2019 年 2 月 25 日
See commit 7906af0 , commit 90a4627 , commit 8d8e9c2 (25 Feb 2019) by Johannes Schindelin ( dscho ) .请参阅Johannes Schindelin ( dscho ) 的commit 7906af0commit 90a4627commit 8d8e9c2 (2019 年 2 月 25 日
(Merged by Junio C Hamano -- gitster -- in commit e36adf7 , 22 Apr 2019) (由Junio C gitster合并-- gitster -- in commit e36adf7,2019年 4 月 22 日)

You can still use the shell script with git legacy-stash .您仍然可以将 shell 脚本与git legacy-stash

And:并且:

stash : convert stash--helper.c into stash.c stash : 将stash--helper.c转换为stash.c

The old shell script git-stash.sh was removed and replaced entirely by builtin/stash.c .旧的 shell 脚本git-stash.sh被删除并完全替换为builtin/stash.c
In order to do that, create and push were adapted to work without stash.sh .为了做到这一点, createpush适合在没有stash.sh情况下stash.sh

For example, before this commit, git stash create called git stash--helper create --message "$*" .例如,在此提交之前, git stash create调用git stash--helper create --message "$*" If it called git stash--helper create "$@" , then some of these changes wouldn't have been necessary.如果它调用git stash--helper create "$@" ,那么其中一些更改就没有必要了。

This commit also removes the word helper since now stash is called directly and not by a shell script.此提交还删除了helper一词,因为现在 stash 是直接调用的,而不是由 shell 脚本调用的。

There are optimizations:有优化:

stash : optimize get_untracked_files() and check_changes() stash :优化get_untracked_files()check_changes()

This commits introduces a optimization by avoiding calling the same functions again.此提交通过避免再次调用相同的函数来引入优化。
For example, git stash push -u would call at some points the following functions:例如, git stash push -u会在某些时候调用以下函数:

  • check_changes() (inside do_push_stash() ) check_changes() (在do_push_stash()
  • do_create_stash() , which calls: check_changes() and get_untracked_files() do_create_stash() ,它调用: check_changes()get_untracked_files()

Note that check_changes() also calls get_untracked_files() .请注意, check_changes()也调用get_untracked_files()
So, check_changes() is called 2 times and get_untracked_files() 3 times.所以, check_changes()被调用2次, get_untracked_files()的3倍。

The old function check_changes() now consists of two functions: get_untracked_files() and check_changes_tracked_files() .旧函数check_changes()现在由两个函数组成: get_untracked_files()check_changes_tracked_files()

These are the call chains for push and create :这些是pushcreate的调用链:

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

To prevent calling the same functions over and over again, check_changes() inside do_create_stash() is now placed in the caller functions ( create_stash() and do_push_stash() ).为了防止一遍check_changes()调用相同的函数, check_changes() do_create_stash()现在被放置在调用者函数中( create_stash()do_push_stash() )。
This way check_changes() and get_untracked files() are called only one time.这样check_changes()get_untracked files()只被调用一次。

git-stash is a script, not a command compiled in the git.exe binary. git-stash是一个脚本,而不是在git.exe二进制文件中编译的命令。

On linux : I can find git-stash at /usr/lib/git-core/git-stash - I will let you look for the correct path on windows ...在Linux上:我能找到git-stash/usr/lib/git-core/git-stash -我会让你看起来对于Windows上的正确的路径...


This script uses #!/bin/sh to run, I don't know what shell implementation is used when you run this on windows.这个脚本使用#!/bin/sh来运行,我不知道你在windows上运行的时候用的是什么shell实现。

You can try to run it with another compatible shell (here: bash) :您可以尝试使用另一个兼容的 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

You can also turn the -x flag, which will print a trace of all commands executed, and visually check if one of the sub commands seems to be the hanger :您还可以打开-x标志,该标志将打印所有已执行命令的跟踪,并直观地检查其中一个子命令是否似乎是 hanger :

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM