{"thread":{"id":"63855","subject":"Why does git-grep appear to treat exclude pathspecs differently?","startedAt":"2025-07-26T13:44:43Z","lastAt":"2025-08-05T20:06:48Z","messageCount":12,"participants":["D. Ben Knoble","Junio C Hamano","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"522789","messageId":"CALnO6CAOOTBQf3s9B1G8AgwcbYnv5VNY63q-6bGPeoaLy208rg@mail.gmail.com","threadId":"63855","inReplyTo":null,"subject":"Why does git-grep appear to treat exclude pathspecs differently?","fromName":"D. Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2025-07-26T13:44:30Z","receivedAt":"2025-07-26T13:44:43Z","isPatch":false,"sender":{"key":"ben.knoble@gmail.com","avatar":"https://avatars.githubusercontent.com/u/22802209?v=4"},"body":"With Git 2.48.1, I observe the following behavior:\n\n- \"git ls-files :^:Documentation/RelNotes | grep Rel\" yields\n\"RelNotes\", as expected\n- \"git grep squash :^:Documentation/RelNotes\" yields the error\n\nfatal: ambiguous argument ':^:Documentation/RelNotes': unknown\nrevision or path not in the working tree.\nUse '--' to separate paths from revisions, like this:\n'git <command> [<revision>...] -- [<file>...]'\n\n- \"git grep squash :^Documentation/RelNotes\", \"git grep squash\n:^:Documentation/RelNotes/\\*\", and \"git grep squash --\n:^:Documentation/RelNotes\" all work as expected\n\nSo I suppose, upon re-reading, that my question is really: what about\n\":^:Documentation/RelNotes\" is ambiguous when handed to git-grep here?\nThere are a few revision syntaxes that start with colon, but none that\nare followed directly by a caret, I think—and :^… can't be \"revision\n:'s parent…\"\n\n-- \nD. Ben Knoble\n"},{"id":"522819","messageId":"xmqqv7nezdw2.fsf@gitster.g","threadId":"63855","inReplyTo":"CALnO6CAOOTBQf3s9B1G8AgwcbYnv5VNY63q-6bGPeoaLy208rg@mail.gmail.com","subject":"Re: Why does git-grep appear to treat exclude pathspecs differently?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-07-27T00:16:45Z","receivedAt":"2025-07-27T00:16:48Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"D. Ben Knoble\" <ben.knoble@gmail.com> writes:\n\n> With Git 2.48.1, I observe the following behavior:\n>\n> - \"git ls-files :^:Documentation/RelNotes | grep Rel\" yields\n> \"RelNotes\", as expected\n\nIt is deliberately confusing to spell \":(exclude)\" as \":^:\".\n\n> - \"git grep squash :^:Documentation/RelNotes\" yields the error\n>\n> fatal: ambiguous argument ':^:Documentation/RelNotes': unknown\n> revision or path not in the working tree.\n\nI think if you write it in longhand,\n\n    $ git grep squash ':(exclude)Documentation/RelNotes'\n\nyou would not see such an error.\n\nThe error message comes from setup.c:die_verify_filename(), I think,\nand setup.c:looks_like_pathspec() allows the control flow to avoid\ncalling that filename verification code path.  It knows to let the\nlonghand magic pathspec go, and it may be trivial to teach it a\nshorthand magic too, but I offhand do not know the implications of\nsuch a change---there might be unintended consequences.\n\n\n\n"},{"id":"523037","messageId":"CALnO6CDNDfx6L7CmPwE0eBZFkd_JkZf6hDwrADccAb14QhJGDg@mail.gmail.com","threadId":"63855","inReplyTo":"xmqqv7nezdw2.fsf@gitster.g","subject":"Re: Why does git-grep appear to treat exclude pathspecs differently?","fromName":"D. Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2025-07-30T21:49:29Z","receivedAt":"2025-07-30T21:49:42Z","isPatch":false,"sender":{"key":"ben.knoble@gmail.com","avatar":"https://avatars.githubusercontent.com/u/22802209?v=4"},"body":"On Sat, Jul 26, 2025 at 8:16 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> \"D. Ben Knoble\" <ben.knoble@gmail.com> writes:\n>\n> > With Git 2.48.1, I observe the following behavior:\n> >\n> > - \"git ls-files :^:Documentation/RelNotes | grep Rel\" yields\n> > \"RelNotes\", as expected\n>\n> It is deliberately confusing to spell \":(exclude)\" as \":^:\".\n\nWhat makes you say that? It's documented in \"git help revisions\":\n\n           A pathspec that begins with a colon : has special meaning. In the\n           short form, the leading colon : is followed by zero or more \"magic\n           signature\" letters (which optionally is terminated by another colon\n           :), and the remainder is the pattern to match against the path.\n\nand\n\n           exclude\n               After a path matches any non-exclude pathspec, it will be run\n               through all exclude pathspecs (magic signature: ! or its synonym\n               ^).\n\n>\n> > - \"git grep squash :^:Documentation/RelNotes\" yields the error\n> >\n> > fatal: ambiguous argument ':^:Documentation/RelNotes': unknown\n> > revision or path not in the working tree.\n>\n> I think if you write it in longhand,\n>\n>     $ git grep squash ':(exclude)Documentation/RelNotes'\n>\n> you would not see such an error.\n\nIndeed, I left this syntax out of my original, but it works.\n\n> The error message comes from setup.c:die_verify_filename(), I think,\n> and setup.c:looks_like_pathspec() allows the control flow to avoid\n> calling that filename verification code path.  It knows to let the\n> longhand magic pathspec go, and it may be trivial to teach it a\n> shorthand magic too, but I offhand do not know the implications of\n> such a change---there might be unintended consequences.\n\nHm. Running a debugger, this looks accurate. We are in the\n\"!seen_dashdash\" case of builtin/grep.c, with the call\n\n    verify_filename(prefix=0x0000000000000000,\narg=\":^:Documentation/RelNotes\", diagnose_misspelt_rev=1)\n\nwhich eventually dies as noted. However:\n\n- looks_like_pathspec() only checks for long magic, as you noted\n- setup.c:check_filename() looks for short-magic, too, but only\nconsiders \":^\" to work like a pathname if we're excluding everything?\n\nI think what I find confusing is that, while this is definitely a DWIM\ncase for git-grep, it doesn't seem to do DWIM :) We are verifying that\nthe remaining arguments are filenames, but couldn't they really be\nfull pathspecs, as long as they aren't revisions?\n\nThe difference for \"^:<path>\" from \":^:<path>\", just to complete the\nstory, is that in setup.c:check_filename() we try to stat whatever\ncomes after \":^\":\n- for the former, that's <path> and we are ok\n- for the latter, that's :<path>, fail.\n\nSo it seems like the places that check for short-magic should also\nconsider the optional trailing colon?\n\n-- \nD. Ben Knoble\n"},{"id":"523266","messageId":"20250802094657.GG3711639@coredump.intra.peff.net","threadId":"63855","inReplyTo":"CALnO6CDNDfx6L7CmPwE0eBZFkd_JkZf6hDwrADccAb14QhJGDg@mail.gmail.com","subject":"Re: Why does git-grep appear to treat exclude pathspecs differently?","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2025-08-02T09:46:57Z","receivedAt":"2025-08-02T09:46:58Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Jul 30, 2025 at 05:49:29PM -0400, D. Ben Knoble wrote:\n\n> which eventually dies as noted. However:\n> \n> - looks_like_pathspec() only checks for long magic, as you noted\n> - setup.c:check_filename() looks for short-magic, too, but only\n> considers \":^\" to work like a pathname if we're excluding everything?\n> \n> I think what I find confusing is that, while this is definitely a DWIM\n> case for git-grep, it doesn't seem to do DWIM :) We are verifying that\n> the remaining arguments are filenames, but couldn't they really be\n> full pathspecs, as long as they aren't revisions?\n> \n> The difference for \"^:<path>\" from \":^:<path>\", just to complete the\n> story, is that in setup.c:check_filename() we try to stat whatever\n> comes after \":^\":\n> - for the former, that's <path> and we are ok\n> - for the latter, that's :<path>, fail.\n> \n> So it seems like the places that check for short-magic should also\n> consider the optional trailing colon?\n\nYeah, I'd think so. But it's worse than that, even. According to the\nglossary definition you showed:\n\n  In the short form, the leading colon `:` is followed by zero or more\n  \"magic signature\" letters (which optionally is terminated by another\n  colon `:`)\n\nwe allow multiple bits of magic. So the code in check_filename() that\nlooks for \":/\", \":^\", etc would be fooled when seeing more than one\ncharacter, like: \":/^exclude-from-root\". AFAICT there are only two short\nmagic types, so I guess nobody has really run into this before.\n\nAlso, I guess this function ought to be respecting the literal_pathspecs\nglobal? The actual pathspec parser does.\n\nIf we can, we probably ought to be feeding the paths to a function like\npathspec.c:parse_element_magic() and then checking the resulting flags\n(and skipping past the prefix as it indicates).\n\n-Peff\n\nPS I didn't even know that we allowed multiple short items or a trailing\n   colon until your email! Hidden corners of Git.\n"},{"id":"523274","messageId":"CALnO6CALb-_RjNZw9u-0R33O+KfccfZK0+mF-W7G659wc4PW7Q@mail.gmail.com","threadId":"63855","inReplyTo":"20250802094657.GG3711639@coredump.intra.peff.net","subject":"Re: Why does git-grep appear to treat exclude pathspecs differently?","fromName":"D. Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2025-08-02T16:13:25Z","receivedAt":"2025-08-02T16:13:38Z","isPatch":false,"sender":{"key":"ben.knoble@gmail.com","avatar":"https://avatars.githubusercontent.com/u/22802209?v=4"},"body":"On Sat, Aug 2, 2025 at 5:46 AM Jeff King <peff@peff.net> wrote:\n>\n> On Wed, Jul 30, 2025 at 05:49:29PM -0400, D. Ben Knoble wrote:\n>\n> > which eventually dies as noted. However:\n> >\n> > - looks_like_pathspec() only checks for long magic, as you noted\n> > - setup.c:check_filename() looks for short-magic, too, but only\n> > considers \":^\" to work like a pathname if we're excluding everything?\n> >\n> > I think what I find confusing is that, while this is definitely a DWIM\n> > case for git-grep, it doesn't seem to do DWIM :) We are verifying that\n> > the remaining arguments are filenames, but couldn't they really be\n> > full pathspecs, as long as they aren't revisions?\n> >\n> > The difference for \"^:<path>\" from \":^:<path>\", just to complete the\n> > story, is that in setup.c:check_filename() we try to stat whatever\n> > comes after \":^\":\n> > - for the former, that's <path> and we are ok\n> > - for the latter, that's :<path>, fail.\n> >\n> > So it seems like the places that check for short-magic should also\n> > consider the optional trailing colon?\n>\n> Yeah, I'd think so. But it's worse than that, even. According to the\n> glossary definition you showed:\n>\n>   In the short form, the leading colon `:` is followed by zero or more\n>   \"magic signature\" letters (which optionally is terminated by another\n>   colon `:`)\n>\n> we allow multiple bits of magic. So the code in check_filename() that\n> looks for \":/\", \":^\", etc would be fooled when seeing more than one\n> character, like: \":/^exclude-from-root\". AFAICT there are only two short\n> magic types, so I guess nobody has really run into this before.\n\nGood call out! I also see only 2 magic items (one with a synonym) at the moment.\n\n>\n> Also, I guess this function ought to be respecting the literal_pathspecs\n> global? The actual pathspec parser does.\n>\n> If we can, we probably ought to be feeding the paths to a function like\n> pathspec.c:parse_element_magic() and then checking the resulting flags\n> (and skipping past the prefix as it indicates).\n\nThanks for pointing me at this; maybe I'll find some time for patches\nunless someone beats me to it.\n\n>\n> -Peff\n>\n> PS I didn't even know that we allowed multiple short items or a trailing\n>    colon until your email! Hidden corners of Git.\n\n;)\n\n-- \nD. Ben Knoble\n"},{"id":"523275","messageId":"CALnO6CDgjmDd9kBCLzjb=JS6Rqg33aXesjthr_Q=HCA-ru2k6g@mail.gmail.com","threadId":"63855","inReplyTo":"CALnO6CDNDfx6L7CmPwE0eBZFkd_JkZf6hDwrADccAb14QhJGDg@mail.gmail.com","subject":"Re: Why does git-grep appear to treat exclude pathspecs differently?","fromName":"D. Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2025-08-02T16:14:07Z","receivedAt":"2025-08-02T16:14:20Z","isPatch":false,"sender":{"key":"ben.knoble@gmail.com","avatar":"https://avatars.githubusercontent.com/u/22802209?v=4"},"body":"On Wed, Jul 30, 2025 at 5:49 PM D. Ben Knoble <ben.knoble@gmail.com> wrote:\n>\n> On Sat, Jul 26, 2025 at 8:16 PM Junio C Hamano <gitster@pobox.com> wrote:\n> >\n> > \"D. Ben Knoble\" <ben.knoble@gmail.com> writes:\n> >\n> > > With Git 2.48.1, I observe the following behavior:\n> > >\n> > > - \"git ls-files :^:Documentation/RelNotes | grep Rel\" yields\n> > > \"RelNotes\", as expected\n> >\n> > It is deliberately confusing to spell \":(exclude)\" as \":^:\".\n>\n> What makes you say that? It's documented in \"git help revisions\":\n\nEr, that's \"git help glossary\" for the quotes below—woops!\n\n>\n>            A pathspec that begins with a colon : has special meaning. In the\n>            short form, the leading colon : is followed by zero or more \"magic\n>            signature\" letters (which optionally is terminated by another colon\n>            :), and the remainder is the pattern to match against the path.\n>\n> and\n>\n>            exclude\n>                After a path matches any non-exclude pathspec, it will be run\n>                through all exclude pathspecs (magic signature: ! or its synonym\n>                ^).\n>\n\n-- \nD. Ben Knoble\n"},{"id":"523283","messageId":"xmqqwm7lhcla.fsf@gitster.g","threadId":"63855","inReplyTo":"20250802094657.GG3711639@coredump.intra.peff.net","subject":"Re: Why does git-grep appear to treat exclude pathspecs differently?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-08-02T17:12:33Z","receivedAt":"2025-08-02T17:12:35Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> PS I didn't even know that we allowed multiple short items or a trailing\n>    colon until your email! Hidden corners of Git.\n\nBut once you think about them, it all makes sense.  The trailing\ncolon can help strange folks who have paths that begin with one of\nthese strange byte values ;-).\n\n"},{"id":"523284","messageId":"xmqqo6sxhc3l.fsf@gitster.g","threadId":"63855","inReplyTo":"CALnO6CDgjmDd9kBCLzjb=JS6Rqg33aXesjthr_Q=HCA-ru2k6g@mail.gmail.com","subject":"Re: Why does git-grep appear to treat exclude pathspecs differently?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-08-02T17:23:10Z","receivedAt":"2025-08-02T17:23:13Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"D. Ben Knoble\" <ben.knoble@gmail.com> writes:\n\n>> > > - \"git ls-files :^:Documentation/RelNotes | grep Rel\" yields\n>> > > \"RelNotes\", as expected\n>> >\n>> > It is deliberately confusing to spell \":(exclude)\" as \":^:\".\n>>\n>> What makes you say that? It's documented in \"git help revisions\":\n\nBecause the most natural way to spell it is \":!Documentation/RelNotes\"\nnot \":^:Documentation/RelNotes\"?  \n\nAnd that is why I did not say \"invalid way to spell\".  It just was\nunnecessarily unfamiliar form to say the same thing.\n\nBut as you need more than one \"prefix\" to the real pathname to\ntrigger the bug in the disambiguation code, :! alone would not have\nexhibited the symptom, and you would have needed something\nmulti-letter like :!: or :!/ in front of that path.\n\n"},{"id":"523291","messageId":"20250802185238.GE1773585@coredump.intra.peff.net","threadId":"63855","inReplyTo":"CALnO6CALb-_RjNZw9u-0R33O+KfccfZK0+mF-W7G659wc4PW7Q@mail.gmail.com","subject":"Re: Why does git-grep appear to treat exclude pathspecs differently?","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2025-08-02T18:52:38Z","receivedAt":"2025-08-02T18:52:39Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Aug 02, 2025 at 12:13:25PM -0400, D. Ben Knoble wrote:\n\n> > Also, I guess this function ought to be respecting the literal_pathspecs\n> > global? The actual pathspec parser does.\n> >\n> > If we can, we probably ought to be feeding the paths to a function like\n> > pathspec.c:parse_element_magic() and then checking the resulting flags\n> > (and skipping past the prefix as it indicates).\n> \n> Thanks for pointing me at this; maybe I'll find some time for patches\n> unless someone beats me to it.\n\nSo here's a simple-ish way to use the full pathspec parsing code:\n\ndiff --git a/setup.c b/setup.c\nindex 6f52dab64c..ad27a65d6b 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -176,28 +176,27 @@ int path_inside_repo(const char *prefix, const char *path)\n \n int check_filename(const char *prefix, const char *arg)\n {\n-\tchar *to_free = NULL;\n+\tconst char *args[] = { arg, NULL };\n+\tstruct pathspec ps;\n \tstruct stat st;\n \n-\tif (skip_prefix(arg, \":/\", &arg)) {\n-\t\tif (!*arg) /* \":/\" is root dir, always exists */\n-\t\t\treturn 1;\n-\t\tprefix = NULL;\n-\t} else if (skip_prefix(arg, \":!\", &arg) ||\n-\t\t   skip_prefix(arg, \":^\", &arg)) {\n-\t\tif (!*arg) /* excluding everything is silly, but allowed */\n-\t\t\treturn 1;\n-\t}\n+\tparse_pathspec(&ps, 0, 0, prefix, args);\n+\tif (ps.nr < 1)\n+\t\tBUG(\"pathspec ended up with no items?\");\n+\targ = ps.items[0].match;\n \n-\tif (prefix)\n-\t\targ = to_free = prefix_filename(prefix, arg);\n+\t/* empty paths (after parsing magic) are OK */\n+\tif (!*arg) {\n+\t\tclear_pathspec(&ps);\n+\t\treturn 1;\n+\t}\n \n \tif (!lstat(arg, &st)) {\n-\t\tfree(to_free);\n+\t\tclear_pathspec(&ps);\n \t\treturn 1; /* file exists */\n \t}\n \tif (is_missing_file_error(errno)) {\n-\t\tfree(to_free);\n+\t\tclear_pathspec(&ps);\n \t\treturn 0; /* file does not exist */\n \t}\n \tdie_errno(_(\"failed to stat '%s'\"), arg);\n\n\nIt does make :^:Documentation work as you'd expect. Curiously, testing\n:/Documentation is hard because that is _also_ a valid rev (the \":/\"\nsearches for a commit with that string in its message). So it will\nalmost always fail anyway as \"hey, this is both a rev and a file\". But\nyou can do \":^/Documentation\" to see how it behaves. ;)\n\nBut here's the interesting part: it breaks a bunch of tests. They all\nseem to be doing things like \":file.txt\". In check_filename() right now\nwe treat that literally. But as a pathspec, it is technically \"colon\nfollowed by zero or more magic signature letters\", and it is eaten.\n\nSo I wonder if we have painted ourselves into a compatibility corner a\nbit, if we have two conflicting expectations. We might be better off\njust teaching check_filename() to parse multiple of [^/!] and the\ntrailing colon. It's horrible and not great for maintainability, but\nthis syntax is not something that changes often.\n\n-Peff\n"},{"id":"523307","messageId":"xmqqbjoxgd83.fsf@gitster.g","threadId":"63855","inReplyTo":"20250802185238.GE1773585@coredump.intra.peff.net","subject":"Re: Why does git-grep appear to treat exclude pathspecs differently?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-08-03T05:56:28Z","receivedAt":"2025-08-03T05:56:31Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> But here's the interesting part: it breaks a bunch of tests. They all\n> seem to be doing things like \":file.txt\". In check_filename() right now\n> we treat that literally. But as a pathspec, it is technically \"colon\n> followed by zero or more magic signature letters\", and it is eaten.\n\nHmph.  Shouldn't the definition be \"colon and then one or more magic\nsignature letters\", then?  \":file.txt\" to name the blob object at\npath file.txt in the index is fairly common \"rev\" and it is a shame\nthat it has to become ambiguous with a pathspec element.\n\n> So I wonder if we have painted ourselves into a compatibility corner a\n> bit, if we have two conflicting expectations. We might be better off\n> just teaching check_filename() to parse multiple of [^/!] and the\n> trailing colon. It's horrible and not great for maintainability, but\n> this syntax is not something that changes often.\n\nAh, OK.\n\nSo the idea is that when given _as_ a pathspec element (e.g., after\nan explicit \"--\" separator), we do want to interpret \":file.txt\" as\nthe same as \"file.txt\", but when dwimming to sift revs and pathspec\nelements apart, prefer to take it as a blob object name in the\nindex?\n\nI guess that would work better than the current code (or straight\n\"use the full pathspec parser\" approach) from the compatibility\nviewpoint.\n\nThanks.\n"},{"id":"523585","messageId":"20250805185703.GC1345110@coredump.intra.peff.net","threadId":"63855","inReplyTo":"xmqqbjoxgd83.fsf@gitster.g","subject":"Re: Why does git-grep appear to treat exclude pathspecs differently?","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2025-08-05T18:57:03Z","receivedAt":"2025-08-05T18:57:05Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Aug 02, 2025 at 10:56:28PM -0700, Junio C Hamano wrote:\n\n> > So I wonder if we have painted ourselves into a compatibility corner a\n> > bit, if we have two conflicting expectations. We might be better off\n> > just teaching check_filename() to parse multiple of [^/!] and the\n> > trailing colon. It's horrible and not great for maintainability, but\n> > this syntax is not something that changes often.\n> \n> Ah, OK.\n> \n> So the idea is that when given _as_ a pathspec element (e.g., after\n> an explicit \"--\" separator), we do want to interpret \":file.txt\" as\n> the same as \"file.txt\", but when dwimming to sift revs and pathspec\n> elements apart, prefer to take it as a blob object name in the\n> index?\n\nYeah, I think that is a good way of framing / justifying it; DWIM can be\nlooser because it's inherently about heuristics.\n\nI don't plan to do anything with this topic anytime soon, but maybe Ben\nwants to produce a patch in that direction.\n\n-Peff\n\nPS I'll be offline for a week or so starting tomorrow, so apologies for\n   any discussions I leave hanging.\n"},{"id":"523603","messageId":"xmqqa54dzg6i.fsf@gitster.g","threadId":"63855","inReplyTo":"20250805185703.GC1345110@coredump.intra.peff.net","subject":"Re: Why does git-grep appear to treat exclude pathspecs differently?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-08-05T20:06:45Z","receivedAt":"2025-08-05T20:06:48Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> On Sat, Aug 02, 2025 at 10:56:28PM -0700, Junio C Hamano wrote:\n>\n>> > So I wonder if we have painted ourselves into a compatibility corner a\n>> > bit, if we have two conflicting expectations. We might be better off\n>> > just teaching check_filename() to parse multiple of [^/!] and the\n>> > trailing colon. It's horrible and not great for maintainability, but\n>> > this syntax is not something that changes often.\n>> \n>> Ah, OK.\n>> \n>> So the idea is that when given _as_ a pathspec element (e.g., after\n>> an explicit \"--\" separator), we do want to interpret \":file.txt\" as\n>> the same as \"file.txt\", but when dwimming to sift revs and pathspec\n>> elements apart, prefer to take it as a blob object name in the\n>> index?\n>\n> Yeah, I think that is a good way of framing / justifying it; DWIM can be\n> looser because it's inherently about heuristics.\n>\n> I don't plan to do anything with this topic anytime soon, but maybe Ben\n> wants to produce a patch in that direction.\n>\n> -Peff\n>\n> PS I'll be offline for a week or so starting tomorrow, so apologies for\n>    any discussions I leave hanging.\n\nThanks for a heads-up, and enjoy your time off away from the list\n;-)\n\n"}]}