stash: avoid recursive hard reset on submodules

git stash push does not recursively stash submodules, but if submodule.recurse is set, it may recursively reset --hard them. Having only the destructive action recurse is likely to be surprising behaviour, and unlikely to be desirable, so the easiest fix should be to ensure that the call to git reset --hard never recurses into submodules. This matches the behavior of check_changes_tracked_files, which ignores submodules. Signed-off-by: Jakob Jarmar <jakob@jarmar.se> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jakob Jarmar committed Oct 12, 2019 at 17:38 UTC 556895d0c8e95a8c2fb41434a5b9bf453e9367f6
3 files changed +43 -3
builtin/stash.c
+1 -1
@@ -1383,7 +1383,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
1383 struct child_process cp = CHILD_PROCESS_INIT;
1384 cp.git_cmd = 1;
1385 argv_array_pushl(&cp.args, "reset", "--hard", "-q",
1386 - NULL);
1386 + "--no-recurse-submodules", NULL);
1387 if (run_command(&cp)) {
1388 ret = -1;
1389 goto done;
git-legacy-stash.sh
+1 -1
@@ -370,7 +370,7 @@ push_stash () {
370 git diff-index -p --cached --binary HEAD -- "$@" |
371 git apply --index -R
372 else
373 - git reset --hard -q
373 + git reset --hard -q --no-recurse-submodules
374 fi
375
376 if test "$keep_index" = "t" && test -n "$i_tree"
t/t3906-stash-submodule.sh
+41 -1
@@ -1,6 +1,6 @@
1 #!/bin/sh
2
3 -test_description='stash apply can handle submodules'
3 +test_description='stash can handle submodules'
4
5 . ./test-lib.sh
6 . "$TEST_DIRECTORY"/lib-submodule-update.sh
@@ -21,4 +21,44 @@ KNOWN_FAILURE_CHERRY_PICK_SEES_EMPTY_COMMIT=1
21 KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1
22 test_submodule_switch "git_stash"
23
24 +setup_basic () {
25 + test_when_finished "rm -rf main sub" &&
26 + git init sub &&
27 + (
28 + cd sub &&
29 + test_commit sub_file
30 + ) &&
31 + git init main &&
32 + (
33 + cd main &&
34 + git submodule add ../sub &&
35 + test_commit main_file
36 + )
37 +}
38 +
39 +test_expect_success 'stash push with submodule.recurse=true preserves dirty submodule worktree' '
40 + setup_basic &&
41 + (
42 + cd main &&
43 + git config submodule.recurse true &&
44 + echo "x" >main_file.t &&
45 + echo "y" >sub/sub_file.t &&
46 + git stash push &&
47 + test_must_fail git -C sub diff --quiet
48 + )
49 +'
50 +
51 +test_expect_success 'stash push and pop with submodule.recurse=true preserves dirty submodule worktree' '
52 + setup_basic &&
53 + (
54 + cd main &&
55 + git config submodule.recurse true &&
56 + echo "x" >main_file.t &&
57 + echo "y" >sub/sub_file.t &&
58 + git stash push &&
59 + git stash pop &&
60 + test_must_fail git -C sub diff --quiet
61 + )
62 +'
63 +
64 test_done