diff --git a/Documentation/config.txt b/Documentation/config.txt index b82e0816cb..bc750d5794 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -178,6 +178,10 @@ advice.*:: the template shown when writing commit messages in linkgit:git-commit[1], and in the help message shown by linkgit:git-checkout[1] when switching branch. + statusUoption:: + Advise to consider using the `-u` option to linkgit:git-status[1] + when the command takes more than 2 seconds to enumerate untracked + files. commitBeforeMerge:: Advice shown when linkgit:git-merge[1] refuses to merge to avoid overwriting local changes. diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt index 0412c4017d..9046df98a0 100644 --- a/Documentation/git-status.txt +++ b/Documentation/git-status.txt @@ -46,15 +46,21 @@ OPTIONS Show untracked files. + The mode parameter is optional (defaults to 'all'), and is used to -specify the handling of untracked files; when -u is not used, the -default is 'normal', i.e. show untracked files and directories. +specify the handling of untracked files. + The possible options are: + - - 'no' - Show no untracked files - - 'normal' - Shows untracked files and directories + - 'no' - Show no untracked files. + - 'normal' - Shows untracked files and directories. - 'all' - Also shows individual files in untracked directories. + +When `-u` option is not used, untracked files and directories are +shown (i.e. the same as specifying `normal`), to help you avoid +forgetting to add newly created files. Because it takes extra work +to find untracked files in the filesystem, this mode may take some +time in a large working tree. You can use `no` to have `git status` +return more quickly without showing untracked files. ++ The default can be changed using the status.showUntrackedFiles configuration variable documented in linkgit:git-config[1]. diff --git a/advice.c b/advice.c index 780f58da0f..3bc86260b8 100644 --- a/advice.c +++ b/advice.c @@ -8,6 +8,7 @@ int advice_push_already_exists = 1; int advice_push_fetch_first = 1; int advice_push_needs_force = 1; int advice_status_hints = 1; +int advice_status_u_option = 1; int advice_commit_before_merge = 1; int advice_resolve_conflict = 1; int advice_implicit_identity = 1; @@ -25,6 +26,7 @@ static struct { { "pushfetchfirst", &advice_push_fetch_first }, { "pushneedsforce", &advice_push_needs_force }, { "statushints", &advice_status_hints }, + { "statusuoption", &advice_status_u_option }, { "commitbeforemerge", &advice_commit_before_merge }, { "resolveconflict", &advice_resolve_conflict }, { "implicitidentity", &advice_implicit_identity }, diff --git a/advice.h b/advice.h index fad36df467..af0c983c68 100644 --- a/advice.h +++ b/advice.h @@ -11,6 +11,7 @@ extern int advice_push_already_exists; extern int advice_push_fetch_first; extern int advice_push_needs_force; extern int advice_status_hints; +extern int advice_status_u_option; extern int advice_commit_before_merge; extern int advice_resolve_conflict; extern int advice_implicit_identity; diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh index f4f38a5e73..52ef06b000 100755 --- a/t/t7060-wtstatus.sh +++ b/t/t7060-wtstatus.sh @@ -5,6 +5,7 @@ test_description='basic work tree status reporting' . ./test-lib.sh test_expect_success setup ' + git config --global advice.statusuoption false && test_commit A && test_commit B oneside added && git checkout A^0 && diff --git a/t/t7508-status.sh b/t/t7508-status.sh index a79c032ffd..aecb4d1e5f 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -8,6 +8,7 @@ test_description='git status' . ./test-lib.sh test_expect_success 'status -h in broken repository' ' + git config --global advice.statusuoption false && mkdir broken && test_when_finished "rm -fr broken" && ( diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh index d2da89a5f5..9d4610629d 100755 --- a/t/t7512-status-help.sh +++ b/t/t7512-status-help.sh @@ -14,6 +14,7 @@ test_description='git status advice' set_fake_editor test_expect_success 'prepare for conflicts' ' + git config --global advice.statusuoption false && test_commit init main.txt init && git branch conflicts && test_commit on_master main.txt on_master && diff --git a/wt-status.c b/wt-status.c index 7555817786..54f4391f9c 100644 --- a/wt-status.c +++ b/wt-status.c @@ -499,9 +499,14 @@ static void wt_status_collect_untracked(struct wt_status *s) { int i; struct dir_struct dir; + struct timeval t_begin; if (!s->show_untracked_files) return; + + if (advice_status_u_option) + gettimeofday(&t_begin, NULL); + memset(&dir, 0, sizeof(dir)); if (s->show_untracked_files != SHOW_ALL_UNTRACKED_FILES) dir.flags |= @@ -533,6 +538,14 @@ static void wt_status_collect_untracked(struct wt_status *s) } free(dir.entries); + + if (advice_status_u_option) { + struct timeval t_end; + gettimeofday(&t_end, NULL); + s->untracked_in_ms = + (uint64_t)t_end.tv_sec * 1000 + t_end.tv_usec / 1000 - + ((uint64_t)t_begin.tv_sec * 1000 + t_begin.tv_usec / 1000); + } } void wt_status_collect(struct wt_status *s) @@ -1100,6 +1113,18 @@ void wt_status_print(struct wt_status *s) wt_status_print_other(s, &s->untracked, _("Untracked files"), "add"); if (s->show_ignored_files) wt_status_print_other(s, &s->ignored, _("Ignored files"), "add -f"); + if (advice_status_u_option && 2000 < s->untracked_in_ms) { + status_printf_ln(s, GIT_COLOR_NORMAL, ""); + status_printf_ln(s, GIT_COLOR_NORMAL, + _("It took %.2f seconds to enumerate untracked files." + " 'status -uno'"), + s->untracked_in_ms / 1000.0); + status_printf_ln(s, GIT_COLOR_NORMAL, + _("may speed it up, but you have to be careful not" + " to forget to add")); + status_printf_ln(s, GIT_COLOR_NORMAL, + _("new files yourself (see 'git help status').")); + } } else if (s->commitable) status_printf_ln(s, GIT_COLOR_NORMAL, _("Untracked files not listed%s"), advice_status_hints diff --git a/wt-status.h b/wt-status.h index 81e1dcf84d..74208c06fd 100644 --- a/wt-status.h +++ b/wt-status.h @@ -69,6 +69,7 @@ struct wt_status { struct string_list change; struct string_list untracked; struct string_list ignored; + uint32_t untracked_in_ms; }; struct wt_status_state {