Subject: [PATCH] stash: honor --no-overwrite-ignore when updating index

From: Pushkar Singh <[email-masked]>
Date: Mon, 2 Feb 2026 13:19:22 +0000

The stash code unconditionally cleared opts.preserve_ignored when
updating the index, leaving a FIXME suggesting this should depend on
an overwrite_ignore flag.

Introduce overwrite_ignore plumbing for git stash push/save and use it
to control preserve_ignored during reset_tree(). Add a test to verify
that --no-overwrite-ignore preserves ignored files.

This removes the long-standing FIXME and aligns stash behavior with
checkout/reset/merge.
---
 builtin/stash.c                    | 11 ++++++++++-
 t/t3905-stash-include-untracked.sh | 13 +++++++++++++
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/builtin/stash.c b/builtin/stash.c
index 193e3ea47a..82d10520fe 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -150,6 +150,7 @@ static int show_stat = 1;
 static int show_patch;
 static int show_include_untracked;
 static int use_index;
+static int overwrite_ignore = 1;
 
 /*
  * w_commit is set to the commit containing the working tree
@@ -360,7 +361,7 @@ static int reset_tree(struct object_id *i_tree, int update, int reset)
 	opts.reset = reset ? UNPACK_RESET_PROTECT_UNTRACKED : 0;
 	opts.update = update;
 	if (update)
-		opts.preserve_ignored = 0; /* FIXME: !overwrite_ignore */
+		opts.preserve_ignored = !overwrite_ignore;
 	opts.fn = oneway_merge;
 
 	if (unpack_trees(nr_trees, t, &opts))
@@ -1856,6 +1857,10 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 			 N_("include untracked files in stash")),
 		OPT_SET_INT('a', "all", &include_untracked,
 			    N_("include ignore files"), 2),
+		OPT_BOOL(0, "overwrite-ignore", &overwrite_ignore,
+			N_("update ignored files (default)")),
+		OPT_BOOL(0, "no-overwrite-ignore", &overwrite_ignore,
+			N_("do not update ignored files")),
 		OPT_STRING('m', "message", &stash_msg, N_("message"),
 			   N_("stash message")),
 		OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
@@ -1959,6 +1964,10 @@ static int save_stash(int argc, const char **argv, const char *prefix,
 			 N_("include untracked files in stash")),
 		OPT_SET_INT('a', "all", &include_untracked,
 			    N_("include ignore files"), 2),
+		OPT_BOOL(0, "overwrite-ignore", &overwrite_ignore,
+				N_("update ignored files (default)")),
+		OPT_BOOL(0, "no-overwrite-ignore", &overwrite_ignore,
+				N_("do not update ignored files")),
 		OPT_STRING('m', "message", &stash_msg, "message",
 			   N_("stash message")),
 		OPT_END()
diff --git a/t/t3905-stash-include-untracked.sh b/t/t3905-stash-include-untracked.sh
index 7704709054..9c5421cd76 100755
--- a/t/t3905-stash-include-untracked.sh
+++ b/t/t3905-stash-include-untracked.sh
@@ -427,4 +427,17 @@ test_expect_success 'stash -u ignores sub-repository' '
 	git stash -u
 '
 
+test_expect_success 'stash push --no-overwrite-ignore preserves ignored files' '
+	echo ignored.txt >>.gitignore &&
+	echo before >ignored.txt &&
+	git add .gitignore &&
+	git commit -m "add ignore" &&
+
+	echo after >ignored.txt &&
+	git stash push --no-overwrite-ignore &&
+
+	test_path_is_file ignored.txt &&
+	grep after ignored.txt
+'
+
 test_done
-- 
2.43.0