{"thread":{"id":"46428","subject":"Expected behavior of \"git check-ignore\"...","startedAt":"2017-07-20T10:37:18Z","lastAt":"2017-07-30T15:57:33Z","messageCount":7,"participants":["John Szakmeister","Philip Oakley","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"324798","messageId":"CAEBDL5URsbMazLBy-kWLJzECTEQ=61DN07xuu5NaO2Hw6r=j+w@mail.gmail.com","threadId":"46428","inReplyTo":null,"subject":"Expected behavior of \"git check-ignore\"...","fromName":"John Szakmeister","fromEmail":"john@szakmeister.net","sentAt":"2017-07-20T10:37:11Z","receivedAt":"2017-07-20T10:37:18Z","isPatch":false,"sender":{"key":"john@szakmeister.net","avatar":"https://avatars.githubusercontent.com/u/448087?v=4"},"body":"A StackOverflow user posted a question about how to reliably check\nwhether a file would be ignored by \"git add\" and expected \"git\ncheck-ignore\" to return results that matched git add's behavior.  It\nturns out that it doesn't.  If there is a negation rule, we end up\nreturning that exclude and printing it and exiting with 0 (there are\nsome ignored files) even though the file has been marked to not be\nignored.\n\nIs the expected behavior of \"git check-ignore\" to return 0 even if the\nfile is not ignore when a negation is present?\n\n>>>>\ngit init .\necho 'foo/*' > .gitignore\necho '!foo/bar' > .gitignore\nmkdir foo\ntouch foo/bar\ngit check-ignore foo/bar\n<<<<\n\nI expect the last command to return 1 (no files are ignored), but it\ndoesn't.  The StackOverflow user had the same expectation, and imagine\nothers do as well.  OTOH, it looks like the command is really meant to\nbe a debugging tool--to show me the line in a .gitignore associated\nwith this file, if there is one.  In which case, the behavior is\ncorrect but the return code description is a bit misleading (0 means\nthe file is ignored, which isn't true here).\n\nThoughts?  It seems like this question was asked before several years\nago but didn't get a response.\n\nThanks!\n\n-John\n\nPS The SO question is here:\nhttps://stackoverflow.com/questions/45210790/how-to-reliably-check-whether-a-file-is-ignored-by-git\n"},{"id":"324916","messageId":"1E42613B0CD743C6ADA24B9F1B43F0F9@PhilipOakley","threadId":"46428","inReplyTo":"CAEBDL5URsbMazLBy-kWLJzECTEQ=61DN07xuu5NaO2Hw6r=j+w@mail.gmail.com","subject":"Re: Expected behavior of \"git check-ignore\"...","fromName":"Philip Oakley","fromEmail":"philipoakley@iee.org","sentAt":"2017-07-23T16:33:42Z","receivedAt":"2017-07-23T16:33:49Z","isPatch":false,"sender":{"key":"philipoakley@iee.email","avatar":"https://avatars.githubusercontent.com/u/914343?v=4"},"body":"From: \"John Szakmeister\" <john@szakmeister.net>\nSent: Thursday, July 20, 2017 11:37 AM\n>A StackOverflow user posted a question about how to reliably check\n> whether a file would be ignored by \"git add\" and expected \"git\n> check-ignore\" to return results that matched git add's behavior.  It\n> turns out that it doesn't.  If there is a negation rule, we end up\n> returning that exclude and printing it and exiting with 0 (there are\n> some ignored files) even though the file has been marked to not be\n> ignored.\n>\n> Is the expected behavior of \"git check-ignore\" to return 0 even if the\n> file is not ignore when a negation is present?\n\nI'm testing this on..\n$ git --version\n\ngit version 2.10.0.windows.1\n\n\n>\n>>>>>\n> git init .\n> echo 'foo/*' > .gitignore\n> echo '!foo/bar' > .gitignore\n\nIs this missing the >> append to get the full two line .gitignore?\nadding in a `cat .gitignore` would help check.\n\n\n> mkdir foo\n> touch foo/bar\nI don't think you need these. It's the given pathnames that are checked, not \nthe file system content.\n\n> git check-ignore foo/bar\n\nDoes this need the `-q` option to set the exit status?\n\necho $? # to display the status.\n\n\n> <<<<\n>\n> I expect the last command to return 1 (no files are ignored), but it\n> doesn't.  The StackOverflow user had the same expectation, and imagine\n> others do as well.  OTOH, it looks like the command is really meant to\n> be a debugging tool--to show me the line in a .gitignore associated\n> with this file, if there is one.  In which case, the behavior is\n> correct but the return code description is a bit misleading (0 means\n> the file is ignored, which isn't true here).\n\nMaybe the logic isn't that clear? Maybe it is simply detecting if any one of \nthe ignore lines is active, and doesn't reset the status for a negation?\n\nI appear to get the same response as yourself, but I haven't spent much time \non it - I'm clearing a backlog of work at the moment.\n\nI also tried the -v -n options, and if I swap the ignore lines around it \nstill says line 2 is the one that ignores.\nIt gets more interesting if two paths are given `foo/bar foo/baz`, to see \nwhich line picks up which pathname (and with the swapped ignore lines).\n\nIs there a test for this in the test suite?\n\n>\n> Thoughts?  It seems like this question was asked before several years\n> ago but didn't get a response.\n>\n> Thanks!\n>\n> -John\n>\n> PS The SO question is here:\n> https://stackoverflow.com/questions/45210790/how-to-reliably-check-whether-a-file-is-ignored-by-git\n\n--\nPhilip \n\n"},{"id":"324946","messageId":"CAEBDL5X3wr=4A+W_sQzSE9BazoxoS2bwcOBZV5Jw=WCWZHAi6A@mail.gmail.com","threadId":"46428","inReplyTo":"1E42613B0CD743C6ADA24B9F1B43F0F9@PhilipOakley","subject":"Re: Expected behavior of \"git check-ignore\"...","fromName":"John Szakmeister","fromEmail":"john@szakmeister.net","sentAt":"2017-07-24T09:33:45Z","receivedAt":"2017-07-24T09:33:52Z","isPatch":false,"sender":{"key":"john@szakmeister.net","avatar":"https://avatars.githubusercontent.com/u/448087?v=4"},"body":"On Sun, Jul 23, 2017 at 12:33 PM, Philip Oakley <philipoakley@iee.org> wrote:\n[snip]\n>>\n>>>>>>\n>> git init .\n>> echo 'foo/*' > .gitignore\n>> echo '!foo/bar' > .gitignore\n>\n>\n> Is this missing the >> append to get the full two line .gitignore?\n> adding in a `cat .gitignore` would help check.\n\nYes, sorry about that.\n\n>\n>> mkdir foo\n>> touch foo/bar\n>\n> I don't think you need these. It's the given pathnames that are checked, not\n> the file system content.\n\nIt was there so you could see that `git status` ignores foo/bar\n(though that wasn't part of the little script).\n\n>> git check-ignore foo/bar\n>\n> Does this need the `-q` option to set the exit status?\n\nNo, it's always set.\n\n> echo $? # to display the status.\n\nSure.  So, to recap the update reproduction recipe would be:\n\n>>>>\ngit init .\necho 'foo/*' > .gitignore\necho '!foo/bar' >> .gitignore\nmkdir foo\ntouch foo/bar\ngit status # foo/ shows as untracked because bar is present\ngit check-ignore foo/bar\necho $? # show the exit status\n<<<<\n\nIt seems like it should print \"1\", but it prints \"0\".\n\n>> I expect the last command to return 1 (no files are ignored), but it\n>> doesn't.  The StackOverflow user had the same expectation, and imagine\n>> others do as well.  OTOH, it looks like the command is really meant to\n>> be a debugging tool--to show me the line in a .gitignore associated\n>> with this file, if there is one.  In which case, the behavior is\n>> correct but the return code description is a bit misleading (0 means\n>> the file is ignored, which isn't true here).\n>\n>\n> Maybe the logic isn't that clear? Maybe it is simply detecting if any one of\n> the ignore lines is active, and doesn't reset the status for a negation?\n>\n> I appear to get the same response as yourself, but I haven't spent much time\n> on it - I'm clearing a backlog of work at the moment.\n\nCorrect, it appears that if any line in the ignore matches, then it\nexits with 0.  So it's not that it's ignored, but that there is a\nmatching line in an ignore file somewhere.  I can see the logic in\nthis if it's meant to be a debugging tools, especially combined with\n-v.  Simply changing it does affect quite a few tests, but I'm not\nsure that it was intentional for negation to be treated this way.\n\n> I also tried the -v -n options, and if I swap the ignore lines around it\n> still says line 2 is the one that ignores.\n> It gets more interesting if two paths are given `foo/bar foo/baz`, to see\n> which line picks up which pathname (and with the swapped ignore lines).\n>\n> Is there a test for this in the test suite?\n\nThere are several.  But line 427, test_expect_success_multi 'nested\ninclude', is one that I think is pretty direct about testing this.  I\nimagine what happened is that gitignores used to contain only things\nyou wanted to ignore and when the ability to negate came along the\nsemantics of this was never changed--and possibly for good reason.\nI'm just wondering if it should change, or if the documentation should\nbe updated to reflect how it actually behaves (the file may not be\nignored, but a line is present in a gitignore that affects its\nstatus).  The behavior is definitely a little unexpected as it stands,\ngiven the documentation though.\n\nThanks for taking a look Philip!\n\n-John\n"},{"id":"324974","messageId":"xmqq4lu1ej0d.fsf@gitster.mtv.corp.google.com","threadId":"46428","inReplyTo":"CAEBDL5X3wr=4A+W_sQzSE9BazoxoS2bwcOBZV5Jw=WCWZHAi6A@mail.gmail.com","subject":"Re: Expected behavior of \"git check-ignore\"...","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-07-24T19:23:46Z","receivedAt":"2017-07-24T19:24:20Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"John Szakmeister <john@szakmeister.net> writes:\n\n> Correct, it appears that if any line in the ignore matches, then it\n> exits with 0.  So it's not that it's ignored, but that there is a\n> matching line in an ignore file somewhere.  I can see the logic in\n> this if it's meant to be a debugging tools, especially combined with\n> -v.  Simply changing it does affect quite a few tests, but I'm not\n> sure that it was intentional for negation to be treated this way.\n\nI am reasonably sure that the command started its life as a pure\ndebugging aid.  \n\nThe treatment of the negation _might_ impose conflicting goals to\nits purpose as a debugging aid---a user who debugs his .gitignore\nfile would want to know what causes a thing that wants to be ignored\nis not or vice versa, and use of the exit status to indicate if it\nis ignored may not mesh well with its goal as a debugging aid, but I\ndidn't think about the potential issues deeply myself while writing\nthis response.  As you mentioned, use of (or not using) \"-v\" could\nbe used as a sign to see which behaviour the end-user expects, I\nguess.\n\n\n"},{"id":"325182","messageId":"CAEBDL5U=pcqwzeQstiBBJpXngXeB4xTfKb7mos68kRAeumc5Rg@mail.gmail.com","threadId":"46428","inReplyTo":"xmqq4lu1ej0d.fsf@gitster.mtv.corp.google.com","subject":"Re: Expected behavior of \"git check-ignore\"...","fromName":"John Szakmeister","fromEmail":"john@szakmeister.net","sentAt":"2017-07-27T11:20:12Z","receivedAt":"2017-07-27T11:20:18Z","isPatch":false,"sender":{"key":"john@szakmeister.net","avatar":"https://avatars.githubusercontent.com/u/448087?v=4"},"body":"On Mon, Jul 24, 2017 at 3:23 PM, Junio C Hamano <gitster@pobox.com> wrote:\n[snip]\n> I am reasonably sure that the command started its life as a pure\n> debugging aid.\n>\n> The treatment of the negation _might_ impose conflicting goals to\n> its purpose as a debugging aid---a user who debugs his .gitignore\n> file would want to know what causes a thing that wants to be ignored\n> is not or vice versa, and use of the exit status to indicate if it\n> is ignored may not mesh well with its goal as a debugging aid, but I\n> didn't think about the potential issues deeply myself while writing\n> this response.  As you mentioned, use of (or not using) \"-v\" could\n> be used as a sign to see which behaviour the end-user expects, I\n> guess.\n\nIs there another way of checking to see if a file is ignored?  If so,\nmaybe we could suggest that instead.  Perhaps using `git status\n--porcelain --ignored` and examining the output?  I'm not sure how\nwell that would work with directories.\n\nThanks for the insight Junio.  I'm going to let the exit status thing\ndrop for now.  You don't seem like it's a good thing to do, and I'm\nnot particularly fond of having it behave two different ways based on\n`-v` being present.\n\n-John\n"},{"id":"325193","messageId":"xmqqd18lolnm.fsf@gitster.mtv.corp.google.com","threadId":"46428","inReplyTo":"CAEBDL5U=pcqwzeQstiBBJpXngXeB4xTfKb7mos68kRAeumc5Rg@mail.gmail.com","subject":"Re: Expected behavior of \"git check-ignore\"...","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-07-27T17:05:33Z","receivedAt":"2017-07-27T17:05:47Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"John Szakmeister <john@szakmeister.net> writes:\n\n> On Mon, Jul 24, 2017 at 3:23 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> [snip]\n>> I am reasonably sure that the command started its life as a pure\n>> debugging aid.\n>>\n>> The treatment of the negation _might_ impose conflicting goals to\n>> its purpose as a debugging aid---a user who debugs his .gitignore\n>> file would want to know what causes a thing that wants to be ignored\n>> is not or vice versa, and use of the exit status to indicate if it\n>> is ignored may not mesh well with its goal as a debugging aid, but I\n>> didn't think about the potential issues deeply myself while writing\n>> this response.  As you mentioned, use of (or not using) \"-v\" could\n>> be used as a sign to see which behaviour the end-user expects, I\n>> guess.\n>\n> Is there another way of checking to see if a file is ignored?  If so,...\n\nMaybe I sounded like waffling, but I do think \"check-ignore\" when\nused as an end-user tool should be that command, to get a preview of\nwhat would happen if you gave the path to \"git add\".  \n\nI was merely giving a possible explanation why it may not behave\nlike so in the current code, i.e. those who used it for debugging\ntheir .gitignore files may have felt that the current way to handle\nnegation were more convenient during their debugging session.\n\nBut I think there is a way out to satisfy both groups of people.\n\nWhat if we (re)define that \"-v\" is a way to ask \"which entry, if\nany, decides the final fate of this path?\" question, and that is a\nsign that the user is using it to debug their .gitignore?  And we\nuse the exit status to mean \"Yeah, there is an explicit entry that\ndecides the fate of the path\" in that case, which is what the\ncurrent behaviour seems to be---the command exits with non-zero\nstatus only when there is nothing that matches in the exclude\nmechanism (which makes the final fate of the path to be 'not\nignored').\n\nAnd we interpret the lack of \"-v\" as a signal that the user wants to\nlearn the fate of a given path via the exit status of the command,\nwhich will \"fix\" the exit code to match the expectation in your\ninitial message in this thread.\n\nWould that work well?\n"},{"id":"325279","messageId":"9C6ADE7816804DDDB398A5D64920FEA0@PhilipOakley","threadId":"46428","inReplyTo":"xmqqd18lolnm.fsf@gitster.mtv.corp.google.com","subject":"Re: Expected behavior of \"git check-ignore\"...","fromName":"Philip Oakley","fromEmail":"philipoakley@iee.org","sentAt":"2017-07-30T15:57:26Z","receivedAt":"2017-07-30T15:57:33Z","isPatch":false,"sender":{"key":"philipoakley@iee.email","avatar":"https://avatars.githubusercontent.com/u/914343?v=4"},"body":"From: \"Junio C Hamano\" <gitster@pobox.com>\nSent: Thursday, July 27, 2017 6:05 PM\n> John Szakmeister <john@szakmeister.net> writes:\n>\n>> On Mon, Jul 24, 2017 at 3:23 PM, Junio C Hamano <gitster@pobox.com> \n>> wrote:\n>> [snip]\n>>> I am reasonably sure that the command started its life as a pure\n>>> debugging aid.\n>>>\n>>> The treatment of the negation _might_ impose conflicting goals to\n>>> its purpose as a debugging aid---a user who debugs his .gitignore\n>>> file would want to know what causes a thing that wants to be ignored\n>>> is not or vice versa, and use of the exit status to indicate if it\n>>> is ignored may not mesh well with its goal as a debugging aid, but I\n>>> didn't think about the potential issues deeply myself while writing\n>>> this response.  As you mentioned, use of (or not using) \"-v\" could\n>>> be used as a sign to see which behaviour the end-user expects, I\n>>> guess.\n>>\n>> Is there another way of checking to see if a file is ignored?  If so,...\n>\n> Maybe I sounded like waffling, but I do think \"check-ignore\" when\n> used as an end-user tool should be that command, to get a preview of\n> what would happen if you gave the path to \"git add\".\n>\n> I was merely giving a possible explanation why it may not behave\n> like so in the current code, i.e. those who used it for debugging\n> their .gitignore files may have felt that the current way to handle\n> negation were more convenient during their debugging session.\n>\n> But I think there is a way out to satisfy both groups of people.\n>\n> What if we (re)define that \"-v\" is a way to ask \"which entry, if\n> any, decides the final fate of this path?\" question, and that is a\n> sign that the user is using it to debug their .gitignore?  And we\n> use the exit status to mean \"Yeah, there is an explicit entry that\n> decides the fate of the path\" in that case, which is what the\n> current behaviour seems to be---the command exits with non-zero\n> status only when there is nothing that matches in the exclude\n> mechanism (which makes the final fate of the path to be 'not\n> ignored').\n>\n> And we interpret the lack of \"-v\" as a signal that the user wants to\n> learn the fate of a given path via the exit status of the command,\n> which will \"fix\" the exit code to match the expectation in your\n> initial message in this thread.\n>\n> Would that work well?\n\nThe old answer on StackOverflow \nhttps://stackoverflow.com/questions/12144633/which-gitignore-rule-is-ignoring-my-file \nhas some of the older gory detail.\n\nI also see that one of the changes was reverted (Revert \"Merge branch \n'nd/exclusion-regression-fix', 5cee3493, 18 Mar 2016 \nhttps://github.com/git/git/commit/5cee349370bd2dce48d0d653ab4ce99bb79a3415#diff-b9ad88b4882e66b5be4541046b713b51). \nIt doesn't look like any follow up happened to the check-ignore docs.\n\nTo me, the return status for the plain vanilla case should always work \ncorrectly. So that is, given one path, using the current index, we know if \nit is, or is not, ignored.\n\nThe verbose output for debugging should be able to be varied at will (e.g. \nre-inclusion can show all operative lines in the debug output). It shouldn't \nbe a backward compatibility issue.\n\nMaybe that, verbosely, for each path given, the summary status is also given \nnow that re-inclusion should be possible, which would not have been required \nbefore.\n--\nPhilip \n\n"}]}