git checkout到分支需要很长时间 [英] git checkout to a branch takes long time

查看:782
本文介绍了git checkout到分支需要很长时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Ubuntu 17.10上,并且正在使用git(2.14.1版).每当我从master创建分支并尝试签出到该分支(或从该分支签出到master)时,它会花费大量时间,大约几分钟,有时甚至是10分钟.的确,我有几GB的数据,但是据我了解,实际上并没有复制整个数据,而是仅保存更改.那么背后的问题是什么呢?

I am on Ubuntu 17.10 and I am using git (version 2.14.1). Whenever I create a branch from master and try to checkout to it (or to the master from it), it takes a whole lot of time, around few minutes, sometimes nearly 10 minutes. True, that I have a few GBs of data, but as far as I understand, the whole data doesn't actually get copied and instead only the changes are saved. What then could be the issue behind this?

推荐答案

尽管Git 2.20和2.21改进了git checkout性能(请参阅下面的下一节),但是自Git 2.23(2019年8月)以来,您应该使用 git switch代替.

While Git 2.20 and 2.21 improve git checkout performance (see next section below), since Git 2.23 (August 2019), you are supposed to use git switch instead.

使用Git 2.24(2019年第四季度)git switch可以恢复性能.
并且确实对OP使用的git checkout -b有影响.

With Git 2.24 (Q4 2019) git switch gets a performance hack back.
And that does have an effect on git checkout -b that the OP uses.

请参见提交3136776 (2019年8月29日)通过 Junio C Hamano合并-gitster-

See commit 3136776 (29 Aug 2019) by Derrick Stolee (derrickstolee).
(Merged by Junio C Hamano -- gitster -- in commit 3ff6af7, 30 Sep 2019)

checkout:为'git checkout -b'添加简单检查

创建了" git switch "命令以将行为的一半分开" git checkout ".

checkout: add simple check for 'git checkout -b'

The 'git switch' command was created to separate half of the behavior of 'git checkout'.

如果用户仅指定创建新分支并将HEAD更改为该分支,则它特别具有不使用索引和工作目录的模式 分支.
这也是大多数用户希望从"git checkout -b",""获得的行为,但是由于历史原因,它还会通过扫描工作目录来执行索引更新.
对于中等大小的存储库,这可能会很慢.

It specifically has the mode to do nothing with the index and working directory if the user only specifies to create a new branch and change HEAD to that branch.
This is also the behavior most users expect from 'git checkout -b', but for historical reasons it also performs an index update by scanning the working directory.
This can be slow for even moderately-sized repos.

fa655d8 (checkout:优化"git checkout -b <new_branch>" 2018-08-16,Git v2.20.0-rc0).
当需要稀疏签出功能时,该更改包括有关配置设置checkout.optimizeNewBranch的详细信息.
如果行为更改是安全的,则可以通过skip_merge_working_tree()方法检测到此更改.
此方法很复杂,需要在引入新选项时进行更新.

A performance fix for 'git checkout -b' was introduced by fa655d8 (checkout: optimize "git checkout -b <new_branch>" 2018-08-16, Git v2.20.0-rc0).
That change includes details about the config setting checkout.optimizeNewBranch when the sparse-checkout feature is required.
The way this change detected if this behavior change is safe was through the skip_merge_working_tree() method.
This method was complex and needed to be updated as new options were introduced.

65f099b ("switch:无工作树状态,除非发生真正的分支切换"(2019-03-29,Git v2.23.0-rc0).
取而代之的是,使用checkout_opts struct的两个成员来区分'git checkout'和'git switch':

This behavior was essentially reverted by 65f099b ("switch: no worktree status unless real branch switch happens" 2019-03-29, Git v2.23.0-rc0).
Instead, two members of the checkout_opts struct were used to distinguish between 'git checkout' and 'git switch':

* `switch_branch_doing_nothing_is_ok`
* `only_merge_on_switching_branches`

这些设置具有相反的值,具体取决于我们是从cmd_checkout还是cmd_switch开始.

These settings have opposite values depending on if we start in cmd_checkout or cmd_switch.

用于 65f099b 包括"鼓励使用大型存储库的用户进行切换."
在'git switch'仍处于试验阶段时进行此更改太过激进了.

The message for 65f099b includes "Users of big repos are encouraged to move to switch."
Making this change while 'git switch' is still experimental is too aggressive.

通过使'git checkout -b <branch>'的行为类似于'git switch',但仅在我们完全读懂这些参数的情况下,才能在这两个选项之间创建一个快乐的介质.
必须在cmd_checkout中完成此操作,以避免参数解析逻辑使用这些参数.

Create a happy medium between these two options by making 'git checkout -b <branch>' behave just like 'git switch', but only if we read exactly those arguments.
This must be done in cmd_checkout to avoid the arguments being consumed by the option parsing logic.

与之前的更改不同, fa655d8 之处在于配置选项仍被删除.
这意味着即使我们有一个稀疏签出文件,"git checkout -b"也将忽略索引合并.
虽然这是'git checkout -b'的行为更改,但与'git switch -c'的行为匹配.

This differs from the previous change by fa655d8 in that the config option checkout.optimizeNewBranch remains deleted.
This means that 'git checkout -b' will ignore the index merge even if we have a sparse-checkout file.
While this is a behavior change for 'git checkout -b', it matches the behavior of 'git switch -c'.


Git 2.20(Q4 2018)将提高git checkout速度:


Git 2.20 (Q4 2018) will improve a git checkout speed:

"git checkout -b newbranch [HEAD]"不必像签出不同于HEAD的提交那样做.
尝试优化这种特殊情况.

"git checkout -b newbranch [HEAD]" should not have to do as much as checking out a commit different from HEAD.
An attempt is made to optimize this special case.

请参见提交fa655d8 (2018年8月16日)通过 Junio C Hamano合并-gitster-

See commit fa655d8 (16 Aug 2018) by Ben Peart (benpeart).
(Merged by Junio C Hamano -- gitster -- in commit 0faaf7e, 17 Sep 2018)

checkout:优化"git checkout -b <new_branch>"

仅当我们通过"git checkout -b <new_branch>."创建新分支时,才跳过合并提交,更新索引和工作目录. 其他任何签出选项仍将通过以前的代码路径.

checkout: optimize "git checkout -b <new_branch>"

Skip merging the commit, updating the index and working directory if and only if we are creating a new branch via "git checkout -b <new_branch>."
Any other checkout options will still go through the former code path.

如果打开sparse_checkout,则要求用户通过将配置设置checkout.optimizeNewBranch设置为true来手动选择此优化行为,因为我们将不再更新索引中的skip-worktree位,也不会添加/删除工作目录中的文件以反映当前的稀疏检出设置.

If sparse_checkout is on, require the user to manually opt in to this optimized behavior by setting the config setting checkout.optimizeNewBranch to true as we will no longer update the skip-worktree bit in the index, nor add/remove files in the working directory to reflect the current sparse checkout settings.

为了进行比较,在大型仓库上运行"git checkout -b <new_branch>"需要:

For comparison, running "git checkout -b <new_branch>" on a large repo takes:

14.6 seconds - without this patch
0.3 seconds - with this patch


Git 2.21(2019年第一季度)进一步优化了git checkout,因为git checkout -b <new> [HEAD]用于从当前提交创建一个新分支,并检查它应该在索引中是空操作,而在工作树中正常情况下,但是有些极端情况确实需要更新索引和工作树.


Git 2.21 (Q1 2019) further optimizes git checkout, in that git checkout -b <new> [HEAD]" used to create a new branch from the current commit and check it out ought to be a no-op in the index and the working tree in normal cases, but there are corner cases that do require updates to the index and the working tree.

在"git clone --no-checkout"之后立即运行它是其中之一 先前的优化未正确启动的情况下, 已修复.

Running it immediately after "git clone --no-checkout" is one of these cases that an earlier optimization kicked in incorrectly, which has been fixed.

请参见提交8424bfd Ben Peart(benpeart).
(由 Junio C Hamano合并-gitster-

See commit 8424bfd, commit 91e3d7c (23 Jan 2019) by Ben Peart (benpeart).
(Merged by Junio C Hamano -- gitster -- in commit 5ad3550, 05 Feb 2019)

checkout:修复了初始结帐时checkout -b中的回归

在执行'checkout -b'时,请进行完整的结帐,包括更新工作 初始结帐时为一棵树.
由于新测试涉及文件系统访问,因此请按顺序在以后进行操作,以便有机会让其他较便宜的测试提早离开.
这修复了由
fa655d8 (checkout:优化"",2018-08-16,Git 2.20).

checkout: fix regression in checkout -b on intitial checkout

When doing a 'checkout -b', do a full checkout including updating the working tree when doing the initial checkout.
As the new test involves an filesystem access, do it later in the sequence to give chance to other cheaper tests to leave early.
This fixes the regression in behavior caused by fa655d8 (checkout: optimize "git checkout -b <new_branch>", 2018-08-16, Git 2.20).

这篇关于git checkout到分支需要很长时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆