Skip to content

Commit fd56fba

Browse files
vdyegitster
authored andcommitted
reset: introduce --[no-]refresh option to --mixed
Add a new --[no-]refresh option that is intended to explicitly determine whether a mixed reset should end in an index refresh. Starting at 9ac8125 (reset: don't compute unstaged changes after reset when --quiet, 2018-10-23), using the '--quiet' option results in skipping the call to 'refresh_index(...)' at the end of a mixed reset with the goal of improving performance. However, by coupling behavior that modifies the index with the option that silences logs, there is no way for users to have one without the other (i.e., silenced logs with a refreshed index) without incurring the overhead of a separate call to 'git update-index --refresh'. Furthermore, there is minimal user-facing documentation indicating that --quiet skips the index refresh, potentially leading to unexpected issues executing commands after 'git reset --quiet' that do not themselves refresh the index (e.g., internals of 'git stash', 'git read-tree'). To mitigate these issues, '--[no-]refresh' and 'reset.refresh' are introduced to provide a dedicated mechanism for refreshing the index. When either is set, '--quiet' and 'reset.quiet' revert to controlling only whether logs are silenced and do not affect index refresh. Helped-by: Derrick Stolee <[email protected]> Helped-by: Junio C Hamano <[email protected]> Signed-off-by: Victoria Dye <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent e86ec71 commit fd56fba

File tree

3 files changed

+87
-8
lines changed

3 files changed

+87
-8
lines changed

Documentation/git-reset.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,15 @@ OPTIONS
110110
`reset.quiet` config option. `--quiet` and `--no-quiet` will
111111
override the default behavior.
112112

113+
--refresh::
114+
--no-refresh::
115+
Proactively refresh the index after a mixed reset. If unspecified, the
116+
behavior falls back on the `reset.refresh` config option. If neither
117+
`--[no-]refresh` nor `reset.refresh` are set, the default behavior is
118+
decided by the `--[no-]quiet` option and/or `reset.quiet` config.
119+
If `--quiet` is specified or `reset.quiet` is set with no command-line
120+
"quiet" setting, refresh is disabled. Otherwise, refresh is enabled.
121+
113122
--pathspec-from-file=<file>::
114123
Pathspec is passed in `<file>` instead of commandline args. If
115124
`<file>` is exactly `-` then standard input is used. Pathspec

builtin/reset.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,13 +392,16 @@ static int git_reset_config(const char *var, const char *value, void *cb)
392392
int cmd_reset(int argc, const char **argv, const char *prefix)
393393
{
394394
int reset_type = NONE, update_ref_status = 0, quiet = 0;
395+
int refresh = -1;
395396
int patch_mode = 0, pathspec_file_nul = 0, unborn;
396397
const char *rev, *pathspec_from_file = NULL;
397398
struct object_id oid;
398399
struct pathspec pathspec;
399400
int intent_to_add = 0;
400401
const struct option options[] = {
401402
OPT__QUIET(&quiet, N_("be quiet, only report errors")),
403+
OPT_BOOL(0, "refresh", &refresh,
404+
N_("skip refreshing the index after reset")),
402405
OPT_SET_INT(0, "mixed", &reset_type,
403406
N_("reset HEAD and index"), MIXED),
404407
OPT_SET_INT(0, "soft", &reset_type, N_("reset only HEAD"), SOFT),
@@ -421,11 +424,19 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
421424

422425
git_config(git_reset_config, NULL);
423426
git_config_get_bool("reset.quiet", &quiet);
427+
git_config_get_bool("reset.refresh", &refresh);
424428

425429
argc = parse_options(argc, argv, prefix, options, git_reset_usage,
426430
PARSE_OPT_KEEP_DASHDASH);
427431
parse_args(&pathspec, argv, prefix, patch_mode, &rev);
428432

433+
/*
434+
* If refresh is completely unspecified (either by config or by command
435+
* line option), decide based on 'quiet'.
436+
*/
437+
if (refresh < 0)
438+
refresh = !quiet;
439+
429440
if (pathspec_from_file) {
430441
if (patch_mode)
431442
die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--patch");
@@ -517,7 +528,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
517528
if (read_from_tree(&pathspec, &oid, intent_to_add))
518529
return 1;
519530
the_index.updated_skipworktree = 1;
520-
if (!quiet && get_git_work_tree()) {
531+
if (refresh && get_git_work_tree()) {
521532
uint64_t t_begin, t_delta_in_ms;
522533

523534
t_begin = getnanotime();

t/t7102-reset.sh

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -462,14 +462,73 @@ test_expect_success 'resetting an unmodified path is a no-op' '
462462
git diff-index --cached --exit-code HEAD
463463
'
464464

465+
test_reset_refreshes_index () {
466+
467+
# To test whether the index is refreshed in `git reset --mixed` with
468+
# the given options, create a scenario where we clearly see different
469+
# results depending on whether the refresh occurred or not.
470+
471+
# Step 0: start with a clean index
472+
git reset --hard HEAD &&
473+
474+
# Step 1: remove file2, but only in the index (no change to worktree)
475+
git rm --cached file2 &&
476+
477+
# Step 2: reset index & leave worktree unchanged from HEAD
478+
git $1 reset $2 --mixed HEAD &&
479+
480+
# Step 3: verify whether the index is refreshed by checking whether
481+
# file2 still has staged changes in the index differing from HEAD (if
482+
# the refresh occurred, there should be no such changes)
483+
git diff-files >output.log &&
484+
test_must_be_empty output.log
485+
}
486+
465487
test_expect_success '--mixed refreshes the index' '
466-
cat >expect <<-\EOF &&
467-
Unstaged changes after reset:
468-
M file2
469-
EOF
470-
echo 123 >>file2 &&
471-
git reset --mixed HEAD >output &&
472-
test_cmp expect output
488+
# Verify default behavior (with no config settings or command line
489+
# options)
490+
test_reset_refreshes_index
491+
'
492+
test_expect_success '--mixed --[no-]quiet sets default refresh behavior' '
493+
# Verify that --[no-]quiet and `reset.quiet` (without --[no-]refresh)
494+
# determine refresh behavior
495+
496+
# Config setting
497+
! test_reset_refreshes_index "-c reset.quiet=true" &&
498+
test_reset_refreshes_index "-c reset.quiet=false" &&
499+
500+
# Command line option
501+
! test_reset_refreshes_index "" --quiet &&
502+
test_reset_refreshes_index "" --no-quiet &&
503+
504+
# Command line option overrides config setting
505+
! test_reset_refreshes_index "-c reset.quiet=false" --quiet &&
506+
test_reset_refreshes_index "-c reset.refresh=true" --no-quiet
507+
'
508+
509+
test_expect_success '--mixed --[no-]refresh sets refresh behavior' '
510+
# Verify that --[no-]refresh and `reset.refresh` control index refresh
511+
512+
# Config setting
513+
test_reset_refreshes_index "-c reset.refresh=true" &&
514+
! test_reset_refreshes_index "-c reset.refresh=false" &&
515+
516+
# Command line option
517+
test_reset_refreshes_index "" --refresh &&
518+
! test_reset_refreshes_index "" --no-refresh &&
519+
520+
# Command line option overrides config setting
521+
test_reset_refreshes_index "-c reset.refresh=false" --refresh &&
522+
! test_reset_refreshes_index "-c reset.refresh=true" --no-refresh
523+
'
524+
525+
test_expect_success '--mixed --refresh overrides --quiet refresh behavior' '
526+
# Verify that *both* --refresh and `reset.refresh` override the
527+
# default non-refresh behavior of --quiet
528+
test_reset_refreshes_index "" "--quiet --refresh" &&
529+
test_reset_refreshes_index "-c reset.quiet=true" --refresh &&
530+
test_reset_refreshes_index "-c reset.refresh=true" --quiet &&
531+
test_reset_refreshes_index "-c reset.refresh=true -c reset.quiet=true"
473532
'
474533

475534
test_expect_success '--mixed preserves skip-worktree' '

0 commit comments

Comments
 (0)