{"thread":{"id":"21104","subject":"gitignore: how to exclude a directory tree from being ignored","startedAt":"2009-10-01T11:07:11Z","lastAt":"2009-10-01T16:26:58Z","messageCount":7,"participants":["Peter","Johannes Sixt"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"124076","messageId":"4AC48D5F.6060401@mycircuit.org","threadId":"21104","inReplyTo":null,"subject":"gitignore: how to exclude a directory tree from being ignored","fromName":"Peter","fromEmail":"vmail@mycircuit.org","sentAt":"2009-10-01T11:07:11Z","receivedAt":"2009-10-01T11:07:11Z","isPatch":false,"sender":{"key":"vmail@mycircuit.org","avatar":null},"body":"Hi\nI want to exclude binaries except in a dir tree that I do not control.\n\nIn .gitignore  I have:\n\n!vendor/\n*.exe\n*.o\n\nI would expect that all *.exe and *.o are ignored except those somewhere \nin the vendor dir tree.\nHowever, the *.exe and *.o in the vendor dir tree are also ignored.\n\nWhat is wrong ?\nThanks for you help\nP\n"},{"id":"124079","messageId":"4AC4A310.8000507@viscovery.net","threadId":"21104","inReplyTo":"4AC48D5F.6060401@mycircuit.org","subject":"Re: gitignore: how to exclude a directory tree from being ignored","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2009-10-01T12:39:44Z","receivedAt":"2009-10-01T12:39:44Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Peter schrieb:\n> Hi\n> I want to exclude binaries except in a dir tree that I do not control.\n> \n> In .gitignore  I have:\n> \n> \n> I would expect that all *.exe and *.o are ignored except those somewhere\n> in the vendor dir tree.\n> However, the *.exe and *.o in the vendor dir tree are also ignored.\n\nThis works for me:\n\n *.exe\n *.o\n !vendor/*.exe\n !vendor/*.o\n\nNote that git-status does not descend into directories from which no files\nare tracked. Therefore, this will work only after you have git-added at\nleast one file from vendor/.\n\ngit ls-files -o --exclude-standard does descend into the directory.\n\nFurthermore, the !vendor/*.exe patterns are not recursive. Perhaps it is\neasier for you to have a separate vendor/.gitignore that has:\n\n !*.exe\n !*.o\n\nThese _are_ recursive.\n\n-- Hannes\n"},{"id":"124082","messageId":"4AC4A7EF.9030002@mycircuit.org","threadId":"21104","inReplyTo":"4AC4A310.8000507@viscovery.net","subject":"Re: gitignore: how to exclude a directory tree from being ignored","fromName":"Peter","fromEmail":"vmail@mycircuit.org","sentAt":"2009-10-01T13:00:31Z","receivedAt":"2009-10-01T13:00:31Z","isPatch":false,"sender":{"key":"vmail@mycircuit.org","avatar":null},"body":"Johannes Sixt wrote:\n> Peter schrieb:\n>   \n>> Hi\n>> I want to exclude binaries except in a dir tree that I do not control.\n>>\n>> In .gitignore  I have:\n>>\n>>\n>> I would expect that all *.exe and *.o are ignored except those somewhere\n>> in the vendor dir tree.\n>> However, the *.exe and *.o in the vendor dir tree are also ignored.\n>>     \n>\n> This works for me:\n>\n>  *.exe\n>  *.o\n>  !vendor/*.exe\n>  !vendor/*.o\n>\n> Note that git-status does not descend into directories from which no files\n> are tracked. Therefore, this will work only after you have git-added at\n> least one file from vendor/.\n>\n> git ls-files -o --exclude-standard does descend into the directory.\n>\n> Furthermore, the !vendor/*.exe patterns are not recursive. Perhaps it is\n> easier for you to have a separate vendor/.gitignore that has:\n>\n>  !*.exe\n>  !*.o\n>\n> These _are_ recursive.\n>\n> -- Hannes\n>   \nThanks a lot, that clarifies the problem for me. As far as I understand now:\n\n1) I can't have just one .gitignore file in the root dir, if I want to \n_recursively_ inverse the exclude pattern for a sub dir tree.\nIn this case, I have to put individual .gitignore files in the sub trees \nI want to re-include.\n\n2) In order to see what will be staged, I have to use the :\ngit ls-files -o --exclude-standard\ninstead of :\ngit ls-files -o -i --exclude-from=.gitignore\nbecause the latter won't consider .gitignore patterns in subtree\n\nPeter\n"},{"id":"124080","messageId":"4AC4AD25.5010708@viscovery.net","threadId":"21104","inReplyTo":"4AC4A7EF.9030002@mycircuit.org","subject":"Re: gitignore: how to exclude a directory tree from being ignored","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2009-10-01T13:22:45Z","receivedAt":"2009-10-01T13:22:45Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Peter schrieb:\n> Johannes Sixt wrote:\n>> Peter schrieb:\n>>  \n>>> Hi\n>>> I want to exclude binaries except in a dir tree that I do not control.\n>>>\n>>> In .gitignore  I have:\n>>>\n>>>\n>>> I would expect that all *.exe and *.o are ignored except those somewhere\n>>> in the vendor dir tree.\n>>> However, the *.exe and *.o in the vendor dir tree are also ignored.\n>>>     \n>>\n>> This works for me:\n>>\n>>  *.exe\n>>  *.o\n>>  !vendor/*.exe\n>>  !vendor/*.o\n>>\n>> Note that git-status does not descend into directories from which no\n>> files\n>> are tracked. Therefore, this will work only after you have git-added at\n>> least one file from vendor/.\n>>\n>> git ls-files -o --exclude-standard does descend into the directory.\n>>\n>> Furthermore, the !vendor/*.exe patterns are not recursive. Perhaps it is\n>> easier for you to have a separate vendor/.gitignore that has:\n>>\n>>  !*.exe\n>>  !*.o\n>>\n>> These _are_ recursive.\n> \n> 1) I can't have just one .gitignore file in the root dir, if I want to\n> _recursively_ inverse the exclude pattern for a sub dir tree.\n\nNo, it's not the inversion of the pattern, but the slash (if it is not at\nthe end) that makes the pattern non-recursive.\n\n> In this case, I have to put individual .gitignore files in the sub trees\n> I want to re-include.\n\nIf you have only the directory vendor/ with no further interesting\nsubdirectories, then you can use my first suggestion. But if you have your\n*.exe and *.o distributed over several directories of different depths\nbelow vendor/, then it might be easier to have a separate\nvendor/.gitignore with recursive patterns (i.e. that do not contain a slash).\n\n> 2) In order to see what will be staged, I have to use the :\n> git ls-files -o --exclude-standard\n> instead of :\n> git ls-files -o -i --exclude-from=.gitignore\n> because the latter won't consider .gitignore patterns in subtree\n\nAfter reading the documentation, I don't know, and I won't try now ;-)\n\n-- Hannes\n"},{"id":"124084","messageId":"4AC4C125.10609@mycircuit.org","threadId":"21104","inReplyTo":"4AC4AD25.5010708@viscovery.net","subject":"Re: gitignore: how to exclude a directory tree from being ignored","fromName":"Peter","fromEmail":"vmail@mycircuit.org","sentAt":"2009-10-01T14:48:05Z","receivedAt":"2009-10-01T14:48:05Z","isPatch":false,"sender":{"key":"vmail@mycircuit.org","avatar":null},"body":"\n>> 1) I can't have just one .gitignore file in the root dir, if I want to\n>> _recursively_ inverse the exclude pattern for a sub dir tree.\n>>     \n>\n> No, it's not the inversion of the pattern, but the slash (if it is not at\n> the end) that makes the pattern non-recursive.\n>\n>   \nfrom the gitignore manpage:\n >> If the pattern ends with a slash, it is removed for the purpose of \nthe following description, but it would only find a match with a \ndirectory. In other words, foo/ will match a directory foo and paths \nunderneath it, but will not match a regular file or a symbolic link foo \n(this is consistent with the way how pathspec works in general in git). <<\n\nDoesn't this mean, that if I say:\nvendor/\nmatches the directory and ( recursively ) the paths underneath it.?\nAnd, consequently:\n!vendor/\ninverse the exclusion for vendor ( that is: include ) and everything \nthat is contained in it ? ( This is obviously not the case, but this is \nwhat I would expect )\n\n>> In this case, I have to put individual .gitignore files in the sub trees\n>> I want to re-include.\n>>     \n>\n> If you have only the directory vendor/ with no further interesting\n> subdirectories, then you can use my first suggestion. But if you have your\n> *.exe and *.o distributed over several directories of different depths\n> below vendor/, then it might be easier to have a separate\n> vendor/.gitignore with recursive patterns (i.e. that do not contain a slash).\n>\n>   \nThis works for me ( I have indeed distributed them over several dirs )\n>> 2) In order to see what will be staged, I have to use the :\n>> git ls-files -o --exclude-standard\n>> instead of :\n>> git ls-files -o -i --exclude-from=.gitignore\n>> because the latter won't consider .gitignore patterns in subtree\n>>     \n>\n> After reading the documentation, I don't know, and I won't try now ;-)\n>\n>   \nAt least it seams to work here ..\n> -- Hannes\n>   \nThanks !\n"},{"id":"124086","messageId":"4AC4C9DB.2090907@viscovery.net","threadId":"21104","inReplyTo":"4AC4C125.10609@mycircuit.org","subject":"Re: gitignore: how to exclude a directory tree from being ignored","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2009-10-01T15:25:15Z","receivedAt":"2009-10-01T15:25:15Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Peter schrieb:\n>>> 1) I can't have just one .gitignore file in the root dir, if I want to\n>>> _recursively_ inverse the exclude pattern for a sub dir tree.\n>>>     \n>>\n>> No, it's not the inversion of the pattern, but the slash (if it is not at\n>> the end) that makes the pattern non-recursive.\n>>\n>>   \n> from the gitignore manpage:\n>>> If the pattern ends with a slash, it is removed for the purpose of\n> the following description, but it would only find a match with a\n> directory. In other words, foo/ will match a directory foo and paths\n> underneath it, but will not match a regular file or a symbolic link foo\n> (this is consistent with the way how pathspec works in general in git). <<\n> \n> Doesn't this mean, that if I say:\n> vendor/\n> matches the directory and ( recursively ) the paths underneath it.?\n\nThe paragraph you are citing is talking about *what* the pattern matches,\nbut it says nothing about *where* the pattern matches.\n\nWhen I was saying \"recursively\", then I was refering to the \"where\"\naspect, not the \"what\" aspect.\n\nIf you have directories\n\n   src/bar/vendor/\n   src/foo/bar/vendor/\n   src/vendor/\n\nand you have the file src/.gitignore with the single pattern\n\n   vendor/\n\nthen it applies to recursively (\"where\") these directories:\n\n   src/bar/vendor/\n   src/foo/bar/vendor/\n   src/vendor/\n\nand everything (\"what\") below them.\n\nBut if the same src/.gitignore has only this pattern:\n\n   bar/vendor/\n\nthen it will not match (\"where\") recursively and only apply to\n\n   src/bar/vendor/\n\nand everything (\"what\") below it, but will not apply to\n\n   src/foo/bar/vendor/\n\n> And, consequently:\n> !vendor/\n> inverse the exclusion for vendor ( that is: include ) and everything\n> that is contained in it ? ( This is obviously not the case, but this is\n> what I would expect )\n\nYou should update your expectations. ;-)\n\nYou think that git starts with the .gitignore files, and somehow applies\nthe rules that it finds to all files (perhaps recursively).\n\nBut it does not work like this; rather it is in the oppsite direction: git\nstarts with a file name, and then checks the rules in the .gitignore files\nthat it has available.\n\nFor example, take the path \"src/vendor/foo.exe\". git finds the file\nsrc/.gitignore and there it sees the pattern \"*.exe\". The pattern matches,\nand so git obeys the rule (ignores the file). But the pattern \"!vendor/\"\ndoes not match (because the path ends with \"foo.exe\", not \"vendor\").\n\nBefore git had seen the path \"src/vendor/foo.exe\", it had already seen\n\"src/vendor\". This time the pattern \"!vendor/\" did match (because the name\nis identical *and* it is a directory, as per the cited paragraph) and git\nobeyed the rule (which was not to ignore the directory).\n\n-- Hannes\n"},{"id":"124087","messageId":"4AC4D852.8000502@mycircuit.org","threadId":"21104","inReplyTo":"4AC4C9DB.2090907@viscovery.net","subject":"Re: gitignore: how to exclude a directory tree from being ignored","fromName":"Peter","fromEmail":"vmail@mycircuit.org","sentAt":"2009-10-01T16:26:58Z","receivedAt":"2009-10-01T16:26:58Z","isPatch":false,"sender":{"key":"vmail@mycircuit.org","avatar":null},"body":"Johannes Sixt wrote:\n> Peter schrieb:\n>   \n>>>> 1) I can't have just one .gitignore file in the root dir, if I want to\n>>>> _recursively_ inverse the exclude pattern for a sub dir tree.\n>>>>     \n>>>>         \n>>> No, it's not the inversion of the pattern, but the slash (if it is not at\n>>> the end) that makes the pattern non-recursive.\n>>>\n>>>   \n>>>       \n>> from the gitignore manpage:\n>>     \n>>>> If the pattern ends with a slash, it is removed for the purpose of\n>>>>         \n>> the following description, but it would only find a match with a\n>> directory. In other words, foo/ will match a directory foo and paths\n>> underneath it, but will not match a regular file or a symbolic link foo\n>> (this is consistent with the way how pathspec works in general in git). <<\n>>\n>> Doesn't this mean, that if I say:\n>> vendor/\n>> matches the directory and ( recursively ) the paths underneath it.?\n>>     \n>\n> The paragraph you are citing is talking about *what* the pattern matches,\n> but it says nothing about *where* the pattern matches.\n>\n> When I was saying \"recursively\", then I was refering to the \"where\"\n> aspect, not the \"what\" aspect.\n>\n> If you have directories\n>\n>    src/bar/vendor/\n>    src/foo/bar/vendor/\n>    src/vendor/\n>\n> and you have the file src/.gitignore with the single pattern\n>\n>    vendor/\n>\n> then it applies to recursively (\"where\") these directories:\n>\n>    src/bar/vendor/\n>    src/foo/bar/vendor/\n>    src/vendor/\n>\n> and everything (\"what\") below them.\n>\n> But if the same src/.gitignore has only this pattern:\n>\n>    bar/vendor/\n>\n> then it will not match (\"where\") recursively and only apply to\n>\n>    src/bar/vendor/\n>\n> and everything (\"what\") below it, but will not apply to\n>\n>    src/foo/bar/vendor/\n>\n>   \n>> And, consequently:\n>> !vendor/\n>> inverse the exclusion for vendor ( that is: include ) and everything\n>> that is contained in it ? ( This is obviously not the case, but this is\n>> what I would expect )\n>>     \n>\n> You should update your expectations. ;-)\n>\n> You think that git starts with the .gitignore files, and somehow applies\n> the rules that it finds to all files (perhaps recursively).\n>\n> But it does not work like this; rather it is in the oppsite direction: git\n> starts with a file name, and then checks the rules in the .gitignore files\n> that it has available.\n>\n> For example, take the path \"src/vendor/foo.exe\". git finds the file\n> src/.gitignore and there it sees the pattern \"*.exe\". The pattern matches,\n> and so git obeys the rule (ignores the file). But the pattern \"!vendor/\"\n> does not match (because the path ends with \"foo.exe\", not \"vendor\").\n>\n> Before git had seen the path \"src/vendor/foo.exe\", it had already seen\n> \"src/vendor\". This time the pattern \"!vendor/\" did match (because the name\n> is identical *and* it is a directory, as per the cited paragraph) and git\n> obeyed the rule (which was not to ignore the directory).\n>\n> -- Hannes\n>   \n\nOk, In fact, my problem therefore derives from the fact that I can't \nspecify *what* and *where* for one item in the same .gitignore file. ( \nall *.o files - what - underneath vendor - where )\n\n\n*.o\n!vendor/\n\nThe *.o refers to the *what* and !vendor/ to the *where* and this does \nnot work. And this seems to be the reasons why we need to split the \nrules over different .gitignore files:\n\nin the root .gitignore:\n*.o\nand in the vendor/.gitignore:\n!*.o\ndoes exactly what I want.\n\nTo me , the *where* aspect relates indeed to recursion but the *what* \naspect perhaps more to pattern matching...\n\nYou should update your expectations. ;-)\n\nDone !\nAt revision 1238945761623511 :-(\n\nThanks a lot !\nPeter\n"}]}