git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] fix git add :!x exiting with error when x is in .gitignore

From
RFRemy D. Farley <one-d-wide@protonmail.com>
Date
Feb 4, 2026, 20:11 UTC
Message-ID
<24VdqZCRHE7M9q7Rp-IH60MmQrEOW5lzhtd1-SUNqEhV_OTzGiCUkVDL5ngVJbyWRMDZ2GlWCJ9wkMSJLsJh8QYO4gRhDMGyzhfuGAODOs8=@protonmail.com>
In-Reply-To
<xmqq5x8cpcrd.fsf@gitster.g>
Junio C Hamano <gitster@pobox.com> wrote:
Show 22 quoted lines
> A question that immediately comes to mind is if it is appropriate
> for a negated pathspec element to recuse itself like this from the
> decision process and let other pathspec elements decide the fate of
> the path, or if a negated pathspec element should take a more active
> role of saying "no" (no, not by immediately returning 0, but this
> loop may have to become a two step process if we wanted to implement
> e.g., for the function to yield "yes", it has to match at least one
> positive pathspec element and zero negated one, or something like
> that).
>
> What should
>
>     git add "$x" ":!$y"
>
> do when a path <matches, does not match> $X and <matches, does not
> match> $Y? We have four combinations to consider in such a case.
> The code in the patch says it should behave identically to
>
>     git add "$x"
>
> and negated ":!$y" should not make any difference. Is that what we
> want?

I indeed failed to consider cases where pathspecs could interfere with each other, sorry.

It does seems like we don't want to just blanketly ignore negated pathspecs, at least for the sake of consistency:

    git add -n :!a a/ignored/c # is ok (even on mainline, nothing is added)
    git add -n :!a/b a/b # ok (same)

Probably the same should hold after this patch if "a" or "a/b" were excluded. I'll try to think this through.

Tian Yuchen <a3205153416@gmail.com> wrote:
> By the way, I think extreme cases like 'git add x :!x' should be added
> into the test scripts.
I think this was already covered, though with a simplistic (wrong) approach.
Show 10 quoted lines
>  for i in ign dir/ign dir/sub dir/sub/*ign sub/file sub sub/*
>  do
>  	[...]
> +	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
Junio C Hamano <gitster@pobox.com> wrote:
Show 13 quoted lines
> One caveat.  The case without any positive pathspec entries needs
> special consideration.  I suspect, but can be totally wrong as I
> didn't think things through thoroughly, that
> 
>     git add "!$y"
> 
> would want to behave as if an implicit "everything matches" was
> given, i.e.,
> 
>     git add "!$y" .
>
> while a pathspec with one or more positive entries would not need
> and want such an implicit "everything" treatment.
This case is actually already handled by the pathspec itself.
From pathspec.c:
Show 14 quoted lines
> void parse_pathspec(struct pathspec *pathspec,
> 		    unsigned magic_mask, unsigned flags,
> 		    const char *prefix, const char **argv)
> {
> 	[...]
> 	/*
> 	 * If everything is an exclude pattern, add one positive pattern
> 	 * that matches everything. We allocated an extra one for this.
> 	 */
> 	if (nr_exclude == n) {
> 		int plen = (!(flags & PATHSPEC_PREFER_CWD)) ? 0 : prefixlen;
> 		init_pathspec_item(item + n, 0, prefix, plen, ".");
> 		pathspec->nr++;
> 	}
Previous: Junio C HamanoNext: Junio C Hamano
Message 5 of 6 in “fix git add :!x exiting with error when x is in .gitignore”
  1. fix git add :!x exiting with error when x is in .gitignoreRemy D. Farley, Feb 4, 2026
  2. Junio C HamanoFeb 4, 2026
  3. Tian YuchenFeb 4, 2026
  4. Junio C HamanoFeb 4, 2026
  5. fix git add :!x exiting with error when x is in .gitignoreRemy D. Farley, Feb 4, 2026
  6. Junio C HamanoFeb 4, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.