Subject: [PATCH 4/9] stash: restore the index by default when breaking changes are enabled

From: "D. Ben Knoble" <[email-masked]>
Date: Sat, 10 May 2025 14:33:39 -0400

This footgun is described in the previous commit to
Documentation/BreakingChanges.adoc; without --index, stash apply and
stash pop confusingly drop stashed index changes.

When compiling with breaking changes, instead restore the index unless
asked not to. Adjust both argument parsing and handling, as well as help
synopses. Don't forget to adjust the error message when application
fails to point to --no-index instead.

Signed-off-by: D. Ben Knoble <[email-masked]>
---

Notes:
    Tests will follow in separate patches, as some changes are rather complicated.

 Documentation/git-stash.adoc |  6 ++++++
 builtin/stash.c              | 38 ++++++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/Documentation/git-stash.adoc b/Documentation/git-stash.adoc
index 1a5177f498..3b01f494a3 100644
--- a/Documentation/git-stash.adoc
+++ b/Documentation/git-stash.adoc
@@ -11,8 +11,14 @@ SYNOPSIS
 'git stash' list [<log-options>]
 'git stash' show [-u | --include-untracked | --only-untracked] [<diff-options>] [<stash>]
 'git stash' drop [-q | --quiet] [<stash>]
+ifndef::with-breaking-changes[]
 'git stash' pop [--index] [-q | --quiet] [<stash>]
 'git stash' apply [--index] [-q | --quiet] [<stash>]
+endif::with-breaking-changes[]
+ifdef::with-breaking-changes[]
+'git stash' pop [--no-index] [-q | --quiet] [<stash>]
+'git stash' apply [--no-index] [-q | --quiet] [<stash>]
+endif::with-breaking-changes[]
 'git stash' branch <branchname> [<stash>]
 'git stash' [push [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet]
 	     [-u | --include-untracked] [-a | --all] [(-m | --message) <message>]
diff --git a/builtin/stash.c b/builtin/stash.c
index cfbd92852a..4ffa586d07 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -38,10 +38,17 @@
 	N_("git stash show [-u | --include-untracked | --only-untracked] [<diff-options>] [<stash>]")
 #define BUILTIN_STASH_DROP_USAGE \
 	N_("git stash drop [-q | --quiet] [<stash>]")
+#ifdef WITH_BREAKING_CHANGES
+#define BUILTIN_STASH_POP_USAGE \
+	N_("git stash pop [--no-index] [-q | --quiet] [<stash>]")
+#define BUILTIN_STASH_APPLY_USAGE \
+	N_("git stash apply [--no-index] [-q | --quiet] [<stash>]")
+#else
 #define BUILTIN_STASH_POP_USAGE \
 	N_("git stash pop [--index] [-q | --quiet] [<stash>]")
 #define BUILTIN_STASH_APPLY_USAGE \
 	N_("git stash apply [--index] [-q | --quiet] [<stash>]")
+#endif /* WITH_BREAKING_CHANGES */
 #define BUILTIN_STASH_BRANCH_USAGE \
 	N_("git stash branch <branchname> [<stash>]")
 #define BUILTIN_STASH_STORE_USAGE \
@@ -562,8 +569,13 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
 			ret = apply_cached(&out);
 			strbuf_release(&out);
 			if (ret)
+#ifdef WITH_BREAKING_CHANGES
+				return error(_("conflicts in index. "
+					       "Try with --no-index."));
+#else
 				return error(_("conflicts in index. "
 					       "Try without --index."));
+#endif /* WITH_BREAKING_CHANGES */
 
 			discard_index(the_repository->index);
 			repo_read_index(the_repository);
@@ -658,12 +670,21 @@ static int apply_stash(int argc, const char **argv, const char *prefix,
 {
 	int ret = -1;
 	int quiet = 0;
+#ifdef WITH_BREAKING_CHANGES
+	int no_index = 0;
+#else
 	int index = 0;
+#endif /* WITH_BREAKING_CHANGES */
 	struct stash_info info = STASH_INFO_INIT;
 	struct option options[] = {
 		OPT__QUIET(&quiet, N_("be quiet, only report errors")),
+#ifdef WITH_BREAKING_CHANGES
+		OPT_BOOL(0, "no-index", &no_index,
+			 N_("do not attempt to recreate the index")),
+#else
 		OPT_BOOL(0, "index", &index,
 			 N_("attempt to recreate the index")),
+#endif /* WITH_BREAKING_CHANGES */
 		OPT_END()
 	};
 
@@ -673,7 +694,11 @@ static int apply_stash(int argc, const char **argv, const char *prefix,
 	if (get_stash_info(&info, argc, argv))
 		goto cleanup;
 
+#ifdef WITH_BREAKING_CHANGES
+	ret = do_apply_stash(prefix, &info, !no_index, quiet);
+#else
 	ret = do_apply_stash(prefix, &info, index, quiet);
+#endif /* WITH_BREAKING_CHANGES */
 cleanup:
 	free_stash_info(&info);
 	return ret;
@@ -755,13 +780,22 @@ static int pop_stash(int argc, const char **argv, const char *prefix,
 		     struct repository *repo UNUSED)
 {
 	int ret = -1;
+#ifdef WITH_BREAKING_CHANGES
+	int no_index = 0;
+#else
 	int index = 0;
+#endif /* WITH_BREAKING_CHANGES */
 	int quiet = 0;
 	struct stash_info info = STASH_INFO_INIT;
 	struct option options[] = {
 		OPT__QUIET(&quiet, N_("be quiet, only report errors")),
+#ifdef WITH_BREAKING_CHANGES
+		OPT_BOOL(0, "no-index", &no_index,
+			 N_("do not attempt to recreate the index")),
+#else
 		OPT_BOOL(0, "index", &index,
 			 N_("attempt to recreate the index")),
+#endif /* WITH_BREAKING_CHANGES */
 		OPT_END()
 	};
 
@@ -771,7 +805,11 @@ static int pop_stash(int argc, const char **argv, const char *prefix,
 	if (get_stash_info_assert(&info, argc, argv))
 		goto cleanup;
 
+#ifdef WITH_BREAKING_CHANGES
+	if ((ret = do_apply_stash(prefix, &info, !no_index, quiet)))
+#else
 	if ((ret = do_apply_stash(prefix, &info, index, quiet)))
+#endif /* WITH_BREAKING_CHANGES */
 		printf_ln(_("The stash entry is kept in case "
 			    "you need it again."));
 	else
-- 
2.48.1