在我的存储库中,git diff
和 git stash
都运行得很快,不到一秒。然而 git stash -p 花了整整 20 秒才显示第一个 block 。为什么会这样?
最佳答案
Git 2.25.2(2020 年 3 月)应该会改进这一点,它会简化代码。
请参阅discussion .
参见commit 26f924d (2020 年 1 月 7 日)作者:Elijah Newren (newren
) .
(由 Junio C Hamano -- gitster
-- 于 commit a3648c0 merge ,2020 年 1 月 22 日)
unpack-trees
: exitcheck_updates()
early if updates are not wantedSigned-off-by: Elijah Newren
check_updates()
has a lot of code that repeatedly checks whethero->update
oro->dry_run
are set.(Note that
o->dry_run
is a near-synonym for!o->update,
but not quite as per commit 2c9078d05bf2 ("unpack-trees
: add thedry_run
flag tounpack_trees_options
", 2011-05-25, Git v1.7.6-rc0).)
In fact, this function almost turns into a no-op whenever the condition!o->update || o->dry_run
is met.
Simplify the code by checking this condition at the beginning of the function, and when it is true, do the few things that are relevant and return early.
There are a few things that make the conversion not quite obvious:
- The fact that check_updates() does not actually turn into a no-op when updates are not wanted may be slightly surprising.
However, commit 33ecf7eb61 (Discard "deleted
" cache entries after using them to update the working tree, 2008-02-07, Git v1.5.5-rc0) put the discarding of unused cache entries incheck_updates()
so we still need to keep the call toremove_marked_cache_entries()
.
It's possible this call belongs in another function, but it is certainly needed as tests will fail if it is removed.- The original called
remove_scheduled_dirs()
unconditionally.
Technically, commit 7847892716 (unlink_entry()
: introduceschedule_dir_for_removal()
, 2009-02-09, Git v1.6.3-rc0) should have made that call conditional, but it didn't matter in practice becauseremove_scheduled_dirs()
becomes a no-op when all the calls to unlink_entry() are skipped.
As such, we do not need to call it.- When
(o->dry_run && o->update)
, the original would have two calls togit_attr_set_direction()
surrounding a bunch of skipped updates.
These two calls togit_attr_set_direction()
cancel each other out and thus can be omitted wheno->dry_run
is true just as they already are when!o->update
.- The code would previously call
setup_collided_checkout_detection()
andreport_collided_checkout()
even wheno->dry_run
.
However, this was just an expensive no-op becausesetup_collided_checkout_detection()
merely cleared theCE_MATCHED
flag for each cache entry, andreport_collided_checkout()
reported which ones had it set.
Since a dry-run would skip all thecheckout_entry()
calls,CE_MATCHED
would never get set and thus no collisions would be reported.
Since we can't detect the collisions anyway without doing updates, skipping the collisions detection setup and reporting is an optimization.- The code previously would call
get_progress()
anddisplay_progress()
even when(!o->update || o->dry_run)
.
This served to show how long it took to skip all the updates, which is somewhat useless.
Since we are skipping the updates, we can skip showing how long it takes to skip them.
关于git - 为什么 git stash -p 需要很长时间才能启动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49149297/