问题
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?
回答1:
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.
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.
See commit 3136776 (29 Aug 2019) by Derrick Stolee (derrickstolee).
(Merged by Junio C Hamano -- gitster -- in commit 3ff6af7, 30 Sep 2019)
checkout
: add simple check for 'git checkout -b'The 'git switch' command was created to separate half of the behavior of 'git checkout'.
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.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 settingcheckout.optimizeNewBranch
when the sparse-checkout feature is required.
The way this change detected if this behavior change is safe was through theskip_merge_working_tree()
method.
This method was complex and needed to be updated as new options were introduced.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 thecheckout_opts struct
were used to distinguish between 'git checkout
' and 'git switch
':* `switch_branch_doing_nothing_is_ok` * `only_merge_on_switching_branches`
These settings have opposite values depending on if we start in
cmd_checkout
orcmd_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.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 incmd_checkout
to avoid the arguments being consumed by the option parsing logic.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) will improve a git checkout
speed:
"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.
See commit fa655d8 (16 Aug 2018) by Ben Peart (benpeart).
(Merged by Junio C Hamano -- gitster -- in commit 0faaf7e, 17 Sep 2018)
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.If
sparse_checkout
is on, require the user to manually opt in to this optimized behavior by setting the config settingcheckout.optimizeNewBranch
to true as we will no longer update theskip-worktree
bit in the index, nor add/remove files in the working directory to reflect the current sparse checkout settings.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 (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.
Running it immediately after "git clone --no-checkout
" is one of these
cases that an earlier optimization kicked in incorrectly, which has
been fixed.
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
: fix regression incheckout -b
on intitial checkoutWhen 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).
回答2:
You should running git gc
to helps performance.
git gc
‘s purpose is twofold: Deleting loose objects and packing objects to use disk space more efficiently.
Runs a number of housekeeping tasks within the current repository, such as compressing file revisions (to reduce disk space and increase performance) and removing unreachable objects which may have been created from prior invocations of git add.
https://git-scm.com/docs/git-gc
来源:https://stackoverflow.com/questions/48823520/git-checkout-to-a-branch-takes-long-time