stash: honor stash.index in apply, pop modes

With stash.index=true, git-stash(1) command now tries to reinstate the index by default in the "apply" and "pop" modes. Not doing so creates a common trap [1], [2]: "git stash apply" is not the reverse of "git stash push" because carefully staged indices are lost and have to be manually recreated. OTOH, this mode is not always desirable and may create more conflicts when applying stashes. As usual, "--no-index" will disable this behavior if you set "stash.index". [1]: https://lore.kernel.org/git/CAPx1GvcxyDDQmCssMjEnt6JoV6qPc5ZUpgPLX3mpUC_4PNYA1w@mail.gmail.com/ [2]: https://lore.kernel.org/git/c5a811ac-8cd3-c389-ac6d-29020a648c87@gmail.com/ Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

D. Ben Knoble committed Sep 21, 2025 at 21:39 UTC 9842c0c7492d2858d64ef81128f7b1f0b38e326b
3 files changed +49 -2
Documentation/config/stash.adoc
+5
@@ -1,3 +1,8 @@
1 +stash.index::
2 + If this is set to true, `git stash apply` and `git stash pop` will
3 + behave as if `--index` was supplied. Defaults to false. See the
4 + descriptions in linkgit:git-stash[1].
5 +
6 stash.showIncludeUntracked::
7 If this is set to true, the `git stash show` command will show
8 the untracked files of a stash entry. Defaults to false. See
builtin/stash.c
+7 -2
@@ -130,6 +130,7 @@ static struct strbuf stash_index_path = STRBUF_INIT;
130 static int show_stat = 1;
131 static int show_patch;
132 static int show_include_untracked;
133 +static int use_index;
134
135 /*
136 * w_commit is set to the commit containing the working tree
@@ -662,7 +663,7 @@ static int apply_stash(int argc, const char **argv, const char *prefix,
663 {
664 int ret = -1;
665 int quiet = 0;
665 - int index = 0;
666 + int index = use_index;
667 struct stash_info info = STASH_INFO_INIT;
668 struct option options[] = {
669 OPT__QUIET(&quiet, N_("be quiet, only report errors")),
@@ -759,7 +760,7 @@ static int pop_stash(int argc, const char **argv, const char *prefix,
760 struct repository *repo UNUSED)
761 {
762 int ret = -1;
762 - int index = 0;
763 + int index = use_index;
764 int quiet = 0;
765 struct stash_info info = STASH_INFO_INIT;
766 struct option options[] = {
@@ -864,6 +865,10 @@ static int git_stash_config(const char *var, const char *value,
865 show_include_untracked = git_config_bool(var, value);
866 return 0;
867 }
868 + if (!strcmp(var, "stash.index")) {
869 + use_index = git_config_bool(var, value);
870 + return 0;
871 + }
872 return git_diff_basic_config(var, value, ctx, cb);
873 }
874
t/t3903-stash.sh
+37
@@ -1595,4 +1595,41 @@ test_expect_success 'stash apply reports a locked index' '
1595 )
1596 '
1597
1598 +test_expect_success 'stash.index=true implies --index' '
1599 + # setup for a few related tests
1600 + test_commit file base &&
1601 + echo index >file &&
1602 + git add file &&
1603 + echo working >file &&
1604 + git stash &&
1605 +
1606 + test_when_finished "git reset --hard" &&
1607 + git -c stash.index=true stash apply &&
1608 + echo index >expect &&
1609 + git show :0:file >actual &&
1610 + test_cmp expect actual &&
1611 + echo working >expect &&
1612 + test_cmp expect file
1613 +'
1614 +
1615 +test_expect_success 'stash.index=true overridden by --no-index' '
1616 + test_when_finished "git reset --hard" &&
1617 + git -c stash.index=true stash apply --no-index &&
1618 + echo base >expect &&
1619 + git show :0:file >actual &&
1620 + test_cmp expect actual &&
1621 + echo working >expect &&
1622 + test_cmp expect file
1623 +'
1624 +
1625 +test_expect_success 'stash.index=false overridden by --index' '
1626 + test_when_finished "git reset --hard" &&
1627 + git -c stash.index=false stash apply --index &&
1628 + echo index >expect &&
1629 + git show :0:file >actual &&
1630 + test_cmp expect actual &&
1631 + echo working >expect &&
1632 + test_cmp expect file
1633 +'
1634 +
1635 test_done