public inbox for git@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] fix git add :!x exiting with error when x is in .gitignore
@ 2026-02-04 13:30 Remy D. Farley
  2026-02-04 16:48 ` Junio C Hamano
  0 siblings, 1 reply; 6+ messages in thread
From: Remy D. Farley @ 2026-02-04 13:30 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Tian Yuchen, Remy D. Farley

`git add :!x .`, which is also executed as part of `git stash :!x`,
seems to treat pathspec with and without exclude magic the same, exiting
with error when "x" exists and is in gitignore.

Git-add manpage doesn't specify that exclude pathspecs should be treated
anyhow differently from normal ones, which seems like a bug. Two
inconsistencies I noticed: `git add :!ignored .` succeeds when "ignored"
file doesn't exist, and `git add :!ignored/x .` succeeds even when
"ignored/x" file exists.

This commit makes makes `git add :!x` not error on x being excluded path.


| $ sh repro.sh
| [...]
| + echo x >.gitignore
| + echo x >x
| + git stash --include-untracked -- ':!x'
| Saved working directory and index state WIP on main: c8a842d Init
| The following paths are ignored by one of your .gitignore files:
| x
| hint: Use -f if you really want to add them.
| hint: Disable this message with "git config set advice.addIgnoredFile false"
| + echo exited with code 1
| exited with code 1


| # repro.sh
| rm -rf repro; mkdir repro; cd repro
| trap 'echo exited with code $?' EXIT
| set -euo pipefail -o xtrace
|
| git init
| git commit -m Init --allow-empty
|
| # Commenting out either of the following lines makes git add/stash below succeed
| echo x >.gitignore
| echo x >x
|
| # Git add . is executed as part of git stash, as can be seen using strace -ffeexecve:
| git add -- ":!x" . # fails
| # git stash --include-untracked -- ":!x" # fails

---
I'm not sure who else to cc, last commit touching this code is 2ec87741
from 10 year ago, being a mere refactoring. I think this bug was simply
overlooked when introducing PATHSPEC_EXCLUDE.

Thanks to Tian Yuchen for looking at my earlier submission (and noticing
an awkwardly stupid bug there).
---
 dir.c                              |  3 +++
 t/t2204-add-ignored.sh             | 14 ++++++++++++++
 t/t3905-stash-include-untracked.sh | 23 +++++++++++++++++++++++
 3 files changed, 40 insertions(+)

diff --git a/dir.c b/dir.c
index b00821f294..ed6b99e337 100644
--- a/dir.c
+++ b/dir.c
@@ -2280,6 +2280,9 @@ static int exclude_matches_pathspec(const char *path, int pathlen,
 		const struct pathspec_item *item = &pathspec->items[i];
 		int len = item->nowildcard_len;
 
+		if (item->magic & PATHSPEC_EXCLUDE)
+			continue;
+
 		if (len == pathlen &&
 		    !ps_strncmp(item, item->match, path, pathlen))
 			return 1;
diff --git a/t/t2204-add-ignored.sh b/t/t2204-add-ignored.sh
index 31eb233df5..76c53fbfde 100755
--- a/t/t2204-add-ignored.sh
+++ b/t/t2204-add-ignored.sh
@@ -47,6 +47,20 @@ do
 	test_expect_success "complaints for ignored $i with unignored file output" '
 		test_grep -e "Use -f if" err
 	'
+
+	test_expect_success "no complaints for unignored file with ignored :!$i" '
+		rm -f .git/index &&
+		git add file ":!$i" &&
+		git ls-files file "$i" >out &&
+		test -s out
+	'
+
+	test_expect_success "complaints for ignored $i with ignored :!ign" '
+		rm -f .git/index &&
+		test_must_fail git add "$i" :!ign 2>err &&
+		git ls-files "$i" ign >out &&
+		test_must_be_empty out
+	'
 done
 
 for i in sub sub/*
diff --git a/t/t3905-stash-include-untracked.sh b/t/t3905-stash-include-untracked.sh
index 7704709054..028ff3efc0 100755
--- a/t/t3905-stash-include-untracked.sh
+++ b/t/t3905-stash-include-untracked.sh
@@ -206,6 +206,29 @@ test_expect_success 'stash push --include-untracked with pathspec' '
 	test_path_is_file foo
 '
 
+test_expect_success 'stash push --include-untracked with :!pathspec' '
+	>foo &&
+	>bar &&
+	git stash push --include-untracked -- :!bar &&
+	test_path_is_file bar &&
+	test_path_is_missing foo &&
+	git stash pop &&
+	test_path_is_file bar &&
+	test_path_is_file foo
+'
+
+test_expect_success 'stash push --include-untracked with :!pathspec in .gitignore' '
+	echo ignored > .gitignore &&
+	>foo &&
+	>ignored &&
+	git stash push --include-untracked -- :!ignored &&
+	test_path_is_file ignored &&
+	test_path_is_missing foo &&
+	git stash pop &&
+	test_path_is_file ignored &&
+	test_path_is_file foo
+'
+
 test_expect_success 'stash push with $IFS character' '
 	>"foo bar" &&
 	>foo &&
-- 
2.51.2



^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-02-04 20:47 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-04 13:30 [PATCH] fix git add :!x exiting with error when x is in .gitignore Remy D. Farley
2026-02-04 16:48 ` Junio C Hamano
2026-02-04 17:53   ` Tian Yuchen
2026-02-04 18:47     ` Junio C Hamano
2026-02-04 20:11       ` Remy D. Farley
2026-02-04 20:47         ` Junio C Hamano

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox