Merge branch 'rr/status-untracked-advice'
The advice message given by "git status" when it takes long time to enumerate untracked paths has been updated. * rr/status-untracked-advice: status: modernize git-status "slow untracked files" advice
This commit is contained in:
commit
f3d9bc801a
@ -457,6 +457,66 @@ during the write may conflict with other simultaneous processes, causing
|
|||||||
them to fail. Scripts running `status` in the background should consider
|
them to fail. Scripts running `status` in the background should consider
|
||||||
using `git --no-optional-locks status` (see linkgit:git[1] for details).
|
using `git --no-optional-locks status` (see linkgit:git[1] for details).
|
||||||
|
|
||||||
|
UNTRACKED FILES AND PERFORMANCE
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
`git status` can be very slow in large worktrees if/when it
|
||||||
|
needs to search for untracked files and directories. There are
|
||||||
|
many configuration options available to speed this up by either
|
||||||
|
avoiding the work or making use of cached results from previous
|
||||||
|
Git commands. There is no single optimum set of settings right
|
||||||
|
for everyone. We'll list a summary of the relevant options to help
|
||||||
|
you, but before going into the list, you may want to run `git status`
|
||||||
|
again, because your configuration may already be caching `git status`
|
||||||
|
results, so it could be faster on subsequent runs.
|
||||||
|
|
||||||
|
* The `--untracked-files=no` flag or the
|
||||||
|
`status.showUntrackedfiles=false` config (see above for both):
|
||||||
|
indicate that `git status` should not report untracked
|
||||||
|
files. This is the fastest option. `git status` will not list
|
||||||
|
the untracked files, so you need to be careful to remember if
|
||||||
|
you create any new files and manually `git add` them.
|
||||||
|
|
||||||
|
* `advice.statusUoption=false` (see linkgit:git-config[1]):
|
||||||
|
setting this variable to `false` disables the warning message
|
||||||
|
given when enumerating untracked files takes more than 2
|
||||||
|
seconds. In a large project, it may take longer and the user
|
||||||
|
may have already accepted the trade off (e.g. using "-uno" may
|
||||||
|
not be an acceptable option for the user), in which case, there
|
||||||
|
is no point issuing the warning message, and in such a case,
|
||||||
|
disabling the warning may be the best.
|
||||||
|
|
||||||
|
* `core.untrackedCache=true` (see linkgit:git-update-index[1]):
|
||||||
|
enable the untracked cache feature and only search directories
|
||||||
|
that have been modified since the previous `git status` command.
|
||||||
|
Git remembers the set of untracked files within each directory
|
||||||
|
and assumes that if a directory has not been modified, then
|
||||||
|
the set of untracked files within has not changed. This is much
|
||||||
|
faster than enumerating the contents of every directory, but still
|
||||||
|
not without cost, because Git still has to search for the set of
|
||||||
|
modified directories. The untracked cache is stored in the
|
||||||
|
`.git/index` file. The reduced cost of searching for untracked
|
||||||
|
files is offset slightly by the increased size of the index and
|
||||||
|
the cost of keeping it up-to-date. That reduced search time is
|
||||||
|
usually worth the additional size.
|
||||||
|
|
||||||
|
* `core.untrackedCache=true` and `core.fsmonitor=true` or
|
||||||
|
`core.fsmonitor=<hook_command_pathname>` (see
|
||||||
|
linkgit:git-update-index[1]): enable both the untracked cache
|
||||||
|
and FSMonitor features and only search directories that have
|
||||||
|
been modified since the previous `git status` command. This
|
||||||
|
is faster than using just the untracked cache alone because
|
||||||
|
Git can also avoid searching for modified directories. Git
|
||||||
|
only has to enumerate the exact set of directories that have
|
||||||
|
changed recently. While the FSMonitor feature can be enabled
|
||||||
|
without the untracked cache, the benefits are greatly reduced
|
||||||
|
in that case.
|
||||||
|
|
||||||
|
Note that after you turn on the untracked cache and/or FSMonitor
|
||||||
|
features it may take a few `git status` commands for the various
|
||||||
|
caches to warm up before you see improved command times. This is
|
||||||
|
normal.
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
--------
|
--------
|
||||||
linkgit:gitignore[5]
|
linkgit:gitignore[5]
|
||||||
|
@ -1676,4 +1676,74 @@ test_expect_success 'racy timestamps will be fixed for dirty worktree' '
|
|||||||
! test_is_magic_mtime .git/index
|
! test_is_magic_mtime .git/index
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'setup slow status advice' '
|
||||||
|
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main git init slowstatus &&
|
||||||
|
(
|
||||||
|
cd slowstatus &&
|
||||||
|
cat >.gitignore <<-\EOF &&
|
||||||
|
/actual
|
||||||
|
/expected
|
||||||
|
/out
|
||||||
|
EOF
|
||||||
|
git add .gitignore &&
|
||||||
|
git commit -m "Add .gitignore" &&
|
||||||
|
git config advice.statusuoption true
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'slow status advice when core.untrackedCache and fsmonitor are unset' '
|
||||||
|
(
|
||||||
|
cd slowstatus &&
|
||||||
|
git config core.untrackedCache false &&
|
||||||
|
git config core.fsmonitor false &&
|
||||||
|
GIT_TEST_UF_DELAY_WARNING=1 git status >actual &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
On branch main
|
||||||
|
|
||||||
|
It took 3.25 seconds to enumerate untracked files.
|
||||||
|
See '\''git help status'\'' for information on how to improve this.
|
||||||
|
|
||||||
|
nothing to commit, working tree clean
|
||||||
|
EOF
|
||||||
|
test_cmp expected actual
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'slow status advice when core.untrackedCache true, but not fsmonitor' '
|
||||||
|
(
|
||||||
|
cd slowstatus &&
|
||||||
|
git config core.untrackedCache true &&
|
||||||
|
git config core.fsmonitor false &&
|
||||||
|
GIT_TEST_UF_DELAY_WARNING=1 git status >actual &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
On branch main
|
||||||
|
|
||||||
|
It took 3.25 seconds to enumerate untracked files.
|
||||||
|
See '\''git help status'\'' for information on how to improve this.
|
||||||
|
|
||||||
|
nothing to commit, working tree clean
|
||||||
|
EOF
|
||||||
|
test_cmp expected actual
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'slow status advice when core.untrackedCache true, and fsmonitor' '
|
||||||
|
(
|
||||||
|
cd slowstatus &&
|
||||||
|
git config core.untrackedCache true &&
|
||||||
|
git config core.fsmonitor true &&
|
||||||
|
GIT_TEST_UF_DELAY_WARNING=1 git status >actual &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
On branch main
|
||||||
|
|
||||||
|
It took 3.25 seconds to enumerate untracked files,
|
||||||
|
but the results were cached, and subsequent runs may be faster.
|
||||||
|
See '\''git help status'\'' for information on how to improve this.
|
||||||
|
|
||||||
|
nothing to commit, working tree clean
|
||||||
|
EOF
|
||||||
|
test_cmp expected actual
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
28
wt-status.c
28
wt-status.c
@ -18,8 +18,10 @@
|
|||||||
#include "worktree.h"
|
#include "worktree.h"
|
||||||
#include "lockfile.h"
|
#include "lockfile.h"
|
||||||
#include "sequencer.h"
|
#include "sequencer.h"
|
||||||
|
#include "fsmonitor-settings.h"
|
||||||
|
|
||||||
#define AB_DELAY_WARNING_IN_MS (2 * 1000)
|
#define AB_DELAY_WARNING_IN_MS (2 * 1000)
|
||||||
|
#define UF_DELAY_WARNING_IN_MS (2 * 1000)
|
||||||
|
|
||||||
static const char cut_line[] =
|
static const char cut_line[] =
|
||||||
"------------------------ >8 ------------------------\n";
|
"------------------------ >8 ------------------------\n";
|
||||||
@ -1205,6 +1207,13 @@ static void wt_longstatus_print_tracking(struct wt_status *s)
|
|||||||
strbuf_release(&sb);
|
strbuf_release(&sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int uf_was_slow(struct wt_status *s)
|
||||||
|
{
|
||||||
|
if (getenv("GIT_TEST_UF_DELAY_WARNING"))
|
||||||
|
s->untracked_in_ms = 3250;
|
||||||
|
return UF_DELAY_WARNING_IN_MS < s->untracked_in_ms;
|
||||||
|
}
|
||||||
|
|
||||||
static void show_merge_in_progress(struct wt_status *s,
|
static void show_merge_in_progress(struct wt_status *s,
|
||||||
const char *color)
|
const char *color)
|
||||||
{
|
{
|
||||||
@ -1814,6 +1823,7 @@ static void wt_longstatus_print(struct wt_status *s)
|
|||||||
{
|
{
|
||||||
const char *branch_color = color(WT_STATUS_ONBRANCH, s);
|
const char *branch_color = color(WT_STATUS_ONBRANCH, s);
|
||||||
const char *branch_status_color = color(WT_STATUS_HEADER, s);
|
const char *branch_status_color = color(WT_STATUS_HEADER, s);
|
||||||
|
enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(s->repo);
|
||||||
|
|
||||||
if (s->branch) {
|
if (s->branch) {
|
||||||
const char *on_what = _("On branch ");
|
const char *on_what = _("On branch ");
|
||||||
@ -1870,13 +1880,21 @@ static void wt_longstatus_print(struct wt_status *s)
|
|||||||
wt_longstatus_print_other(s, &s->untracked, _("Untracked files"), "add");
|
wt_longstatus_print_other(s, &s->untracked, _("Untracked files"), "add");
|
||||||
if (s->show_ignored_mode)
|
if (s->show_ignored_mode)
|
||||||
wt_longstatus_print_other(s, &s->ignored, _("Ignored files"), "add -f");
|
wt_longstatus_print_other(s, &s->ignored, _("Ignored files"), "add -f");
|
||||||
if (advice_enabled(ADVICE_STATUS_U_OPTION) && 2000 < s->untracked_in_ms) {
|
if (advice_enabled(ADVICE_STATUS_U_OPTION) && uf_was_slow(s)) {
|
||||||
status_printf_ln(s, GIT_COLOR_NORMAL, "%s", "");
|
status_printf_ln(s, GIT_COLOR_NORMAL, "%s", "");
|
||||||
|
if (fsm_mode > FSMONITOR_MODE_DISABLED) {
|
||||||
|
status_printf_ln(s, GIT_COLOR_NORMAL,
|
||||||
|
_("It took %.2f seconds to enumerate untracked files,\n"
|
||||||
|
"but the results were cached, and subsequent runs may be faster."),
|
||||||
|
s->untracked_in_ms / 1000.0);
|
||||||
|
} else {
|
||||||
|
status_printf_ln(s, GIT_COLOR_NORMAL,
|
||||||
|
_("It took %.2f seconds to enumerate untracked files."),
|
||||||
|
s->untracked_in_ms / 1000.0);
|
||||||
|
}
|
||||||
status_printf_ln(s, GIT_COLOR_NORMAL,
|
status_printf_ln(s, GIT_COLOR_NORMAL,
|
||||||
_("It took %.2f seconds to enumerate untracked files. 'status -uno'\n"
|
_("See 'git help status' for information on how to improve this."));
|
||||||
"may speed it up, but you have to be careful not to forget to add\n"
|
status_printf_ln(s, GIT_COLOR_NORMAL, "%s", "");
|
||||||
"new files yourself (see 'git help status')."),
|
|
||||||
s->untracked_in_ms / 1000.0);
|
|
||||||
}
|
}
|
||||||
} else if (s->committable)
|
} else if (s->committable)
|
||||||
status_printf_ln(s, GIT_COLOR_NORMAL, _("Untracked files not listed%s"),
|
status_printf_ln(s, GIT_COLOR_NORMAL, _("Untracked files not listed%s"),
|
||||||
|
Loading…
Reference in New Issue
Block a user