public inbox for git@vger.kernel.org
 help / color / mirror / Atom feed
* Bug: git add :!x . exits with error when x is in .gitignore
@ 2026-01-31 19:43 Remy D. Farley
  2026-02-02 18:04 ` Tian Yuchen
  0 siblings, 1 reply; 3+ messages in thread
From: Remy D. Farley @ 2026-01-31 19:43 UTC (permalink / raw)
  To: git; +Cc: Remy D. Farley

`git add :!x .`, which is executed as part `git stash :!x`, seems to treat
pathspec with and without exclude magic the same, exiting with error when "x"
is in gitignore file. If file "x" isn't present, `git add x` still exits with
error as expected (although with a different one), but `git add :!x .` succeeds.

Git-add manpage doesn't specify that exclude pathspecs are treated anyhow
differently from normal ones, so I'm not sure if it's really a bug. But it does
seem like one. I originally tried to exclude certain files from scripted stashes
using pathspec, but had to switch to reusing core.excludesFile (which is
probably a better fit for my use case).


```sh
$ sh repro.sh
[...]
+ echo x >.gitignore
+ echo x >x
+ git add -- ':!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
```


```sh
# 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

# If we comment out either of the following lines, git add/stash commands 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

echo ok
```

---
 dir.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/dir.c b/dir.c
index b00821f2..0026bd65 100644
--- a/dir.c
+++ b/dir.c
@@ -2264,7 +2264,7 @@ static int exclude_matches_pathspec(const char *path, int pathlen,
 {
 	int i;
 
-	if (!pathspec || !pathspec->nr)
+	if (!pathspec || !pathspec->nr || pathspec->magic & PATHSPEC_EXCLUDE)
 		return 0;
 
 	GUARD_PATHSPEC(pathspec,
-- 
2.51.2



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

* Re: Bug: git add :!x . exits with error when x is in .gitignore
  2026-01-31 19:43 Bug: git add :!x . exits with error when x is in .gitignore Remy D. Farley
@ 2026-02-02 18:04 ` Tian Yuchen
  2026-02-02 21:25   ` Remy D. Farley
  0 siblings, 1 reply; 3+ messages in thread
From: Tian Yuchen @ 2026-02-02 18:04 UTC (permalink / raw)
  To: Remy D. Farley, git

On 2/1/26 03:43, Remy D. Farley wrote:

Thanks for the report and the patch! I also agree that the behavior you 
described seems like a bug.

However, though I'm new to git community, I still have concerns about 
the fix in 'dir.c':
   > -	if (!pathspec || !pathspec->nr)
> +	if (!pathspec || !pathspec->nr || pathspec->magic & PATHSPEC_EXCLUDE)
>   		return 0;

I tried to analyze the logic and I believe this patch breaks the basic 
functionality of the negative pathspec (:!):

(I didn't check the caller of exclude_matches_pathspec and I only focus 
on the function itself. Tell me if I'm wrong :)

By returning 0 whenever PATHSPEC_EXCLUDE is set globally, 
exclude_matches_pathspec will report "no match" for all files, 
effectively disabling the exclusion mechanism entirely.

Instead of fixing the issue with ignored files, this patch causes valid 
exclusions to be ignored.

We must check if the specific path matches the exclude pattern, not 
short-circuit based on the global flag.

It will be great if we set a test script for this. I will be working on 
it in the next few days.

Regards,

Yuchen


























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

* Re: Bug: git add :!x . exits with error when x is in .gitignore
  2026-02-02 18:04 ` Tian Yuchen
@ 2026-02-02 21:25   ` Remy D. Farley
  0 siblings, 0 replies; 3+ messages in thread
From: Remy D. Farley @ 2026-02-02 21:25 UTC (permalink / raw)
  To: a3205153416; +Cc: git, one-d-wide

> Thanks for the report and the patch! I also agree that the behavior you
> described seems like a bug.
> 
> However, though I'm new to git community, I still have concerns about
> the fix in 'dir.c':
> 
> > - if (!pathspec || !pathspec->nr)
> > + if (!pathspec || !pathspec->nr || pathspec->magic & PATHSPEC_EXCLUDE)
> > return 0;
> 
> 
> I tried to analyze the logic and I believe this patch breaks the basic
> functionality of the negative pathspec (:!):
> 
> (I didn't check the caller of exclude_matches_pathspec and I only focus
> on the function itself. Tell me if I'm wrong :)
> 
> By returning 0 whenever PATHSPEC_EXCLUDE is set globally,
> exclude_matches_pathspec will report "no match" for all files,
> effectively disabling the exclusion mechanism entirely.
> 
> Instead of fixing the issue with ignored files, this patch causes valid
> exclusions to be ignored.
> 
> We must check if the specific path matches the exclude pattern, not
> short-circuit based on the global flag.


Oops. Somehow I was convinced struct pathspec represents only a single path.
This way something like this would silently succeed, without actually indexing x:

  touch x
  echo x >.gitignore
  git add -n ":(exclude)smth/else" x

Thank you for pointing out.


> It will be great if we set a test script for this. I will be working on
> it in the next few days.

---
 dir.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/dir.c b/dir.c
index b00821f2..ed6b99e3 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;
-- 
2.51.2



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

end of thread, other threads:[~2026-02-02 21:25 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-31 19:43 Bug: git add :!x . exits with error when x is in .gitignore Remy D. Farley
2026-02-02 18:04 ` Tian Yuchen
2026-02-02 21:25   ` Remy D. Farley

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