{"thread":{"id":"66713","subject":"Q: .gitignore and asterisk \"*\"","startedAt":"2026-10-30T10:46:01Z","lastAt":"2026-11-03T22:40:32Z","messageCount":7,"participants":["Windl, Ulrich","Junio C Hamano","Tuomas Ahola"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"556892","messageId":"07b3498d83424cac87221724b371839a@ukr.de","threadId":"66713","inReplyTo":null,"subject":"Q: .gitignore and asterisk \"*\"","fromName":"Windl, Ulrich","fromEmail":"u.windl@ukr.de","sentAt":"2026-10-30T10:46:01Z","receivedAt":"2026-10-30T10:46:01Z","isPatch":false,"sender":{"key":"u.windl@ukr.de","avatar":null},"body":"Hi!\n\nI think the documentation for gitignore(5) could be improved regarding \"*\":\nIt's nor clear whether \"*\" matches an empty string.\nSo when I have\nfoo.log\nfoo.msg\nfoo.sh\nfoo-whatever.log\nfoo-whetever.msg\nWould e.g. \"foo*.log\" cover all the logs?\n\nThe manual says:\n       •   An asterisk \"*\" matches anything except a slash. The character \"?\"\n           matches any one character except \"/\". The range notation, e.g.\n           [a-zA-Z], can be used to match one of the characters in a range.\n           See fnmatch(3) and the FNM_PATHNAME flag for a more detailed\n           description.\n\nKind regards,\nUlrich Windl\n\n"},{"id":"556936","messageId":"xmqq5wyjxgyn.fsf@gitster.g","threadId":"66713","inReplyTo":"07b3498d83424cac87221724b371839a@ukr.de","subject":"Re: Q: .gitignore and asterisk \"*\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-10-30T16:59:12Z","receivedAt":"2026-10-30T16:59:12Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Windl, Ulrich\" <u.windl@ukr.de> writes:\n\n> I think the documentation for gitignore(5) could be improved regarding \"*\":\n> It's nor clear whether \"*\" matches an empty string.\n> So when I have\n> foo.log\n> foo.msg\n> foo.sh\n> foo-whatever.log\n> foo-whetever.msg\n> Would e.g. \"foo*.log\" cover all the logs?\n>\n> The manual says:\n>        •   An asterisk \"*\" matches anything except a slash. The character \"?\"\n>            matches any one character except \"/\". The range notation, e.g.\n>            [a-zA-Z], can be used to match one of the characters in a range.\n>            See fnmatch(3) and the FNM_PATHNAME flag for a more detailed\n>            description.\n\nVery good point.\n\nThe reference to fnmatch(3) may not make readers to consult the\ndocumentation for the library function.  The system they are on may\nnot even have \"man\".  fnmatch(3) often refers to glob(7), which\ntypically would say that a '*' (not between brackets) matches any\nstring, including the empty string.  The reference to FNM_PATHNAME\nwe have there is an attempt to refer back to fnmatch(3) that would\ntypically say that the wildcard does not match a slash.\n\nHow about rewriting the entry like so to reduce external references?\n\n----- >8 -----\nSubject: gitignore: rewrite wildcard description\n\nThe documentation for '.gitignore' makes reference to fnmatch(3) and\nFNM_PATHNAME to describe how an asterisk \"*\" and a question mark \"?\"\nbehave.  Even though it spells out that these wildcard characters\ndo not match a slash, it does not say if an asterisk matches an\nempty string (it does).\n\nRewrite the section so that the readers would get a more complete\npicture without requiring them to know what fnmatch(3) and glob(7)\nsays.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Documentation/gitignore.adoc | 15 ++++++++++-----\n 1 file changed, 10 insertions(+), 5 deletions(-)\n\ndiff --git c/Documentation/gitignore.adoc w/Documentation/gitignore.adoc\nindex 7979e50f18..671a5a4c99 100644\n--- c/Documentation/gitignore.adoc\n+++ w/Documentation/gitignore.adoc\n@@ -110,11 +110,16 @@ PATTERN FORMAT\n    and `a/frotz` that is a directory (all paths are relative from\n    the `.gitignore` file).\n \n- - An asterisk \"`*`\" matches anything except a slash.\n-   The character \"`?`\" matches any one character except \"`/`\".\n-   The range notation, e.g. `[a-zA-Z]`, can be used to match\n-   one of the characters in a range. See fnmatch(3) and the\n-   FNM_PATHNAME flag for a more detailed description.\n+ - An asterisk \"`*`\" matches string of any length, and a question mark\n+   \"`?`\" matches any single character, but these wildcard characters\n+   do not match a slash \"`/`\".\n+\n+ - A pair of brackets that enclose characters match one of the listed\n+   characters, and a range notation inside them, e.g., \"`[a-zA-Z]`\",\n+   would behave as if all the characters in the range were listed there\n+   instead.  Wildcard characters \"`*`\" and \"`?`\" lose their special\n+   meaning inside a pair of brackets, e.g., \"`[*]`\" would match an\n+   asterisk and nothing else.\n \n  - A backslash (\"`\\`\") can be used to escape any character. E.g., \"`\\*`\"\n    matches a literal asterisk (and \"`\\a`\" matches \"`a`\", even though\n\n"},{"id":"557270","messageId":"20261103073317.DATcL%taahol@utu.fi","threadId":"66713","inReplyTo":"xmqq5wyjxgyn.fsf@gitster.g","subject":"Re: Q: .gitignore and asterisk \"*\"","fromName":"Tuomas Ahola","fromEmail":"taahol@utu.fi","sentAt":"2026-11-03T07:33:17Z","receivedAt":"2026-11-03T07:33:17Z","isPatch":false,"sender":{"key":"taahol@utu.fi","avatar":"https://avatars.githubusercontent.com/u/114303477?v=4"},"body":"Junio C Hamano <gitster@pobox.com> wrote:\n\n> \"Windl, Ulrich\" <u.windl@ukr.de> writes:\n> \n> > I think the documentation for gitignore(5) could be improved regarding \"*\":\n> > It's nor clear whether \"*\" matches an empty string.\n> > So when I have\n> > foo.log\n> > foo.msg\n> > foo.sh\n> > foo-whatever.log\n> > foo-whetever.msg\n> > Would e.g. \"foo*.log\" cover all the logs?\n> >\n> > The manual says:\n> >        •   An asterisk \"*\" matches anything except a slash. The character \"?\"\n> >            matches any one character except \"/\". The range notation, e.g.\n> >            [a-zA-Z], can be used to match one of the characters in a range.\n> >            See fnmatch(3) and the FNM_PATHNAME flag for a more detailed\n> >            description.\n> \n> Very good point.\n> \n> The reference to fnmatch(3) may not make readers to consult the\n> documentation for the library function.  The system they are on may\n> not even have \"man\".  fnmatch(3) often refers to glob(7), which\n> typically would say that a '*' (not between brackets) matches any\n> string, including the empty string.  The reference to FNM_PATHNAME\n> we have there is an attempt to refer back to fnmatch(3) that would\n> typically say that the wildcard does not match a slash.\n> \n> How about rewriting the entry like so to reduce external references?\n> \n> ----- >8 -----\n> Subject: gitignore: rewrite wildcard description\n> \n> The documentation for '.gitignore' makes reference to fnmatch(3) and\n> FNM_PATHNAME to describe how an asterisk \"*\" and a question mark \"?\"\n> behave.  Even though it spells out that these wildcard characters\n> do not match a slash, it does not say if an asterisk matches an\n> empty string (it does).\n> \n> Rewrite the section so that the readers would get a more complete\n> picture without requiring them to know what fnmatch(3) and glob(7)\n> says.\n> \n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n>  Documentation/gitignore.adoc | 15 ++++++++++-----\n>  1 file changed, 10 insertions(+), 5 deletions(-)\n> \n> diff --git c/Documentation/gitignore.adoc w/Documentation/gitignore.adoc\n> index 7979e50f18..671a5a4c99 100644\n> --- c/Documentation/gitignore.adoc\n> +++ w/Documentation/gitignore.adoc\n> @@ -110,11 +110,16 @@ PATTERN FORMAT\n>     and `a/frotz` that is a directory (all paths are relative from\n>     the `.gitignore` file).\n>  \n> - - An asterisk \"`*`\" matches anything except a slash.\n> -   The character \"`?`\" matches any one character except \"`/`\".\n> -   The range notation, e.g. `[a-zA-Z]`, can be used to match\n> -   one of the characters in a range. See fnmatch(3) and the\n> -   FNM_PATHNAME flag for a more detailed description.\n> + - An asterisk \"`*`\" matches string of any length, and a question mark\n\nIt's not unreasonable at all to call the empty string \"a string of no length\",\nso it is still a bit ambiguous whether it qualifies as a string of any length.\nI would suggest s/of any length/of length of zero or more/.\n\n> +   \"`?`\" matches any single character, but these wildcard characters\n> +   do not match a slash \"`/`\".\n> +\n> + - A pair of brackets that enclose characters match one of the listed\n> +   characters, and a range notation inside them, e.g., \"`[a-zA-Z]`\",\n> +   would behave as if all the characters in the range were listed there\n> +   instead.  Wildcard characters \"`*`\" and \"`?`\" lose their special\n> +   meaning inside a pair of brackets, e.g., \"`[*]`\" would match an\n> +   asterisk and nothing else.\n>  \n>   - A backslash (\"`\\`\") can be used to escape any character. E.g., \"`\\*`\"\n>     matches a literal asterisk (and \"`\\a`\" matches \"`a`\", even though\n\n"},{"id":"557302","messageId":"ea470151c8c6448caec64f26c3d35498@ukr.de","threadId":"66713","inReplyTo":"20261103073317.DATcL%taahol@utu.fi","subject":"RE: [EXT] Re: Q: .gitignore and asterisk \"*\"","fromName":"Windl, Ulrich","fromEmail":"u.windl@ukr.de","sentAt":"2026-11-03T12:00:05Z","receivedAt":"2026-11-03T12:00:05Z","isPatch":false,"sender":{"key":"u.windl@ukr.de","avatar":null},"body":"Hi!\n\nI think the original \" matches anything except a slash.\" \"kind of suggests\" that is has to match \"something\" (non-zero length) to succeed, while the proposed \"string of any length\" would include zero-size for me.\nStill, the latest proposal is just as clear IMHO.\n\nKind regards,\nUlrich Windl\n \nKlinikum der Universität Regensburg\nIT / Infrastruktur\n \nFranz-Josef-Strauß-Allee 11\nD-93053 Regensburg\n\nTel: +49 941 944-13816\nSoftphone: +49 941 944-801142\nFAX: +49 941 944-5882\n\n> -----Original Message-----\n> From: Tuomas Ahola <taahol@utu.fi>\n> Sent: Tuesday, November 3, 2026 8:33 AM\n> To: Junio C Hamano <gitster@pobox.com>\n> Cc: Windl, Ulrich <u.windl@ukr.de>; git@vger.kernel.org\n> Subject: [EXT] Re: Q: .gitignore and asterisk \"*\"\n> \n> Junio C Hamano <gitster@pobox.com> wrote:\n> \n> > \"Windl, Ulrich\" <u.windl@ukr.de> writes:\n> >\n> > > I think the documentation for gitignore(5) could be improved regarding\n> \"*\":\n> > > It's nor clear whether \"*\" matches an empty string.\n> > > So when I have\n> > > foo.log\n> > > foo.msg\n> > > foo.sh\n> > > foo-whatever.log\n> > > foo-whetever.msg\n> > > Would e.g. \"foo*.log\" cover all the logs?\n> > >\n> > > The manual says:\n> > >        •   An asterisk \"*\" matches anything except a slash. The character \"?\"\n> > >            matches any one character except \"/\". The range notation, e.g.\n> > >            [a-zA-Z], can be used to match one of the characters in a range.\n> > >            See fnmatch(3) and the FNM_PATHNAME flag for a more detailed\n> > >            description.\n> >\n> > Very good point.\n> >\n> > The reference to fnmatch(3) may not make readers to consult the\n> > documentation for the library function.  The system they are on may\n> > not even have \"man\".  fnmatch(3) often refers to glob(7), which\n> > typically would say that a '*' (not between brackets) matches any\n> > string, including the empty string.  The reference to FNM_PATHNAME\n> > we have there is an attempt to refer back to fnmatch(3) that would\n> > typically say that the wildcard does not match a slash.\n> >\n> > How about rewriting the entry like so to reduce external references?\n> >\n> > ----- >8 -----\n> > Subject: gitignore: rewrite wildcard description\n> >\n> > The documentation for '.gitignore' makes reference to fnmatch(3) and\n> > FNM_PATHNAME to describe how an asterisk \"*\" and a question mark \"?\"\n> > behave.  Even though it spells out that these wildcard characters\n> > do not match a slash, it does not say if an asterisk matches an\n> > empty string (it does).\n> >\n> > Rewrite the section so that the readers would get a more complete\n> > picture without requiring them to know what fnmatch(3) and glob(7)\n> > says.\n> >\n> > Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> > ---\n> >  Documentation/gitignore.adoc | 15 ++++++++++-----\n> >  1 file changed, 10 insertions(+), 5 deletions(-)\n> >\n> > diff --git c/Documentation/gitignore.adoc\n> w/Documentation/gitignore.adoc\n> > index 7979e50f18..671a5a4c99 100644\n> > --- c/Documentation/gitignore.adoc\n> > +++ w/Documentation/gitignore.adoc\n> > @@ -110,11 +110,16 @@ PATTERN FORMAT\n> >     and `a/frotz` that is a directory (all paths are relative from\n> >     the `.gitignore` file).\n> >\n> > - - An asterisk \"`*`\" matches anything except a slash.\n> > -   The character \"`?`\" matches any one character except \"`/`\".\n> > -   The range notation, e.g. `[a-zA-Z]`, can be used to match\n> > -   one of the characters in a range. See fnmatch(3) and the\n> > -   FNM_PATHNAME flag for a more detailed description.\n> > + - An asterisk \"`*`\" matches string of any length, and a question mark\n> \n> It's not unreasonable at all to call the empty string \"a string of no length\",\n> so it is still a bit ambiguous whether it qualifies as a string of any length.\n> I would suggest s/of any length/of length of zero or more/.\n> \n> > +   \"`?`\" matches any single character, but these wildcard characters\n> > +   do not match a slash \"`/`\".\n> > +\n> > + - A pair of brackets that enclose characters match one of the listed\n> > +   characters, and a range notation inside them, e.g., \"`[a-zA-Z]`\",\n> > +   would behave as if all the characters in the range were listed there\n> > +   instead.  Wildcard characters \"`*`\" and \"`?`\" lose their special\n> > +   meaning inside a pair of brackets, e.g., \"`[*]`\" would match an\n> > +   asterisk and nothing else.\n> >\n> >   - A backslash (\"`\\`\") can be used to escape any character. E.g., \"`\\*`\"\n> >     matches a literal asterisk (and \"`\\a`\" matches \"`a`\", even though\n"},{"id":"557337","messageId":"xmqqzevpald4.fsf@gitster.g","threadId":"66713","inReplyTo":"20261103073317.DATcL%taahol@utu.fi","subject":"Re: Q: .gitignore and asterisk \"*\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-11-03T17:13:59Z","receivedAt":"2026-11-03T17:13:59Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Tuomas Ahola <taahol@utu.fi> writes:\n\n> Junio C Hamano <gitster@pobox.com> wrote:\n>\n>> \"Windl, Ulrich\" <u.windl@ukr.de> writes:\n\nPlease trim the lines that do not have any relevance to what you are\ngoing to comment on from your quoted material.\n\n>> - - An asterisk \"`*`\" matches anything except a slash.\n>> -   The character \"`?`\" matches any one character except \"`/`\".\n>> -   The range notation, e.g. `[a-zA-Z]`, can be used to match\n>> -   one of the characters in a range. See fnmatch(3) and the\n>> -   FNM_PATHNAME flag for a more detailed description.\n>> + - An asterisk \"`*`\" matches string of any length, and a question mark\n>\n> It's not unreasonable at all to call the empty string \"a string of no length\",\n> so it is still a bit ambiguous whether it qualifies as a string of any length.\n> I would suggest s/of any length/of length of zero or more/.\n\nA string of no length falls within the set of strings of any length,\nso I do not see any ambiguity there.\n\n\"A string of length of zero or more\" is a roundabout way to say \"any\nstring\" as by definition there is no string of negative length.\nPerhaps that is good enough?\n\n\n"},{"id":"557342","messageId":"20261103172943.DKwn8%taahol@utu.fi","threadId":"66713","inReplyTo":"xmqqzevpald4.fsf@gitster.g","subject":"Re: Q: .gitignore and asterisk \"*\"","fromName":"Tuomas Ahola","fromEmail":"taahol@utu.fi","sentAt":"2026-11-03T17:29:43Z","receivedAt":"2026-11-03T17:29:43Z","isPatch":false,"sender":{"key":"taahol@utu.fi","avatar":"https://avatars.githubusercontent.com/u/114303477?v=4"},"body":"Junio C Hamano <gitster@pobox.com> wrote:\n\n> Tuomas Ahola <taahol@utu.fi> writes:\n> \n> > Junio C Hamano <gitster@pobox.com> wrote:\n> >\n> >> \"Windl, Ulrich\" <u.windl@ukr.de> writes:\n> \n> Please trim the lines that do not have any relevance to what you are\n> going to comment on from your quoted material.\n> \n> >> - - An asterisk \"`*`\" matches anything except a slash.\n> >> -   The character \"`?`\" matches any one character except \"`/`\".\n> >> -   The range notation, e.g. `[a-zA-Z]`, can be used to match\n> >> -   one of the characters in a range. See fnmatch(3) and the\n> >> -   FNM_PATHNAME flag for a more detailed description.\n> >> + - An asterisk \"`*`\" matches string of any length, and a question mark\n> >\n> > It's not unreasonable at all to call the empty string \"a string of no length\",\n> > so it is still a bit ambiguous whether it qualifies as a string of any length.\n> > I would suggest s/of any length/of length of zero or more/.\n> \n> A string of no length falls within the set of strings of any length,\n> so I do not see any ambiguity there.\n> \n> \"A string of length of zero or more\" is a roundabout way to say \"any\n> string\" as by definition there is no string of negative length.\n> Perhaps that is good enough?\n\nAs you wish, although I would like to point that both Linux and BSD versions of\nglob(7) are quite explicit in their wording:\n\n\tA '*' (not between brackets) matches any string, including the empty string.\n\nand\n\n\t*  Matches any sequence of zero or more characters.\n\n(Just thinking aloud.)\n\n"},{"id":"557386","messageId":"xmqqh5hx4jz3.fsf_-_@gitster.g","threadId":"66713","inReplyTo":"xmqq5wyjxgyn.fsf@gitster.g","subject":"[PATCH v2] gitignore: rewrite wildcard description","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-11-03T22:40:32Z","receivedAt":"2026-11-03T22:40:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The documentation for '.gitignore' makes reference to fnmatch(3) and\nFNM_PATHNAME to describe how an asterisk \"*\" and a question mark \"?\"\nbehave.  Even though it spells out that these wildcard characters\ndo not match a slash, it does not say if an asterisk matches an\nempty string (it does).\n\nRewrite the section so that the readers would get a more complete\npicture without requiring them to know what fnmatch(3) and glob(7)\nsays.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n * let's adopt the most explicit \"(including the empty string)\"\n   from glob(7).\n\n Documentation/gitignore.adoc | 15 ++++++++++-----\n 1 file changed, 10 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/gitignore.adoc b/Documentation/gitignore.adoc\nindex 7979e50f18..87f37c2b0c 100644\n--- a/Documentation/gitignore.adoc\n+++ b/Documentation/gitignore.adoc\n@@ -110,11 +110,16 @@ PATTERN FORMAT\n    and `a/frotz` that is a directory (all paths are relative from\n    the `.gitignore` file).\n \n- - An asterisk \"`*`\" matches anything except a slash.\n-   The character \"`?`\" matches any one character except \"`/`\".\n-   The range notation, e.g. `[a-zA-Z]`, can be used to match\n-   one of the characters in a range. See fnmatch(3) and the\n-   FNM_PATHNAME flag for a more detailed description.\n+ - An asterisk \"`*`\" matches any string (including the empty string),\n+   and a question mark \"`?`\" matches any single character, but these\n+   wildcard characters do not match a slash \"`/`\".\n+\n+ - A pair of brackets that enclose characters match one of the listed\n+   characters, and a range notation inside them, e.g., \"`[a-zA-Z]`\",\n+   would behave as if all the characters in the range were listed there\n+   instead.  Wildcard characters \"`*`\" and \"`?`\" lose their special\n+   meaning inside a pair of brackets, e.g., \"`[*]`\" would match an\n+   asterisk and nothing else.\n \n  - A backslash (\"`\\`\") can be used to escape any character. E.g., \"`\\*`\"\n    matches a literal asterisk (and \"`\\a`\" matches \"`a`\", even though\n\nInterdiff:\n  diff --git a/Documentation/gitignore.adoc b/Documentation/gitignore.adoc\n  index 671a5a4c99..87f37c2b0c 100644\n  --- a/Documentation/gitignore.adoc\n  +++ b/Documentation/gitignore.adoc\n  @@ -110,9 +110,9 @@ PATTERN FORMAT\n      and `a/frotz` that is a directory (all paths are relative from\n      the `.gitignore` file).\n   \n  - - An asterisk \"`*`\" matches string of any length, and a question mark\n  -   \"`?`\" matches any single character, but these wildcard characters\n  -   do not match a slash \"`/`\".\n  + - An asterisk \"`*`\" matches any string (including the empty string),\n  +   and a question mark \"`?`\" matches any single character, but these\n  +   wildcard characters do not match a slash \"`/`\".\n   \n    - A pair of brackets that enclose characters match one of the listed\n      characters, and a range notation inside them, e.g., \"`[a-zA-Z]`\",\n-- \n2.56.0-511-g14903f623d\n\n"}]}