{"thread":{"id":"21369","subject":"[PATCH] gitignore: root most patterns at the top-level directory","startedAt":"2009-10-27T01:10:24Z","lastAt":"2009-10-30T21:52:07Z","messageCount":5,"participants":["Jeff King","Junio C Hamano","Johannes Sixt","James Pickens"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"125977","messageId":"20091027011024.GA29361@sigio.peff.net","threadId":"21369","inReplyTo":null,"subject":"[PATCH] gitignore: root most patterns at the top-level directory","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-10-27T01:10:24Z","receivedAt":"2009-10-27T01:10:24Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"Our gitignore doesn't use a preceding \"/\" to root its\npatterns in the top of the repository. This means that if\nyou add a file or directory called \"git\" (for example)\ninside a subdirectory, it will be erroneously ignored.\n\nThis patch was done mechanically with \"s/^[^*]/\\/&/\" with\none exception: instead of ignoring gitk-wish, we should\ngitk-git/gitk-wish (arguably, this should be done in\ngitk-git/.gitignore, but because that is a subtree merge\nfrom elsewhere, this is easier).\n\nAcked-by: Sverre Rabbelier <srabbelier@gmail.com>\nSigned-off-by: Jeff King <peff@peff.net>\n---\n\nThis bit Sverre while I was looking over his shoulder. I doubt it comes\nup very often, but we should probably be modeling good gitignore\nbehavior. I have to admit it looks a lot uglier, though.\n\n .gitignore |  354 ++++++++++++++++++++++++++++++------------------------------\n 1 files changed, 177 insertions(+), 177 deletions(-)\n\ndiff --git a/.gitignore b/.gitignore\nindex 51a37b1..289c3d0 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -1,184 +1,184 @@\n-GIT-BUILD-OPTIONS\n-GIT-CFLAGS\n-GIT-GUI-VARS\n-GIT-VERSION-FILE\n-git\n-git-add\n-git-add--interactive\n-git-am\n-git-annotate\n-git-apply\n-git-archimport\n-git-archive\n-git-bisect\n-git-bisect--helper\n-git-blame\n-git-branch\n-git-bundle\n-git-cat-file\n-git-check-attr\n-git-check-ref-format\n-git-checkout\n-git-checkout-index\n-git-cherry\n-git-cherry-pick\n-git-clean\n-git-clone\n-git-commit\n-git-commit-tree\n-git-config\n-git-count-objects\n-git-cvsexportcommit\n-git-cvsimport\n-git-cvsserver\n-git-daemon\n-git-diff\n-git-diff-files\n-git-diff-index\n-git-diff-tree\n-git-difftool\n-git-difftool--helper\n-git-describe\n-git-fast-export\n-git-fast-import\n-git-fetch\n-git-fetch--tool\n-git-fetch-pack\n-git-filter-branch\n-git-fmt-merge-msg\n-git-for-each-ref\n-git-format-patch\n-git-fsck\n-git-fsck-objects\n-git-gc\n-git-get-tar-commit-id\n-git-grep\n-git-hash-object\n-git-help\n-git-http-fetch\n-git-http-push\n-git-imap-send\n-git-index-pack\n-git-init\n-git-init-db\n-git-instaweb\n-git-log\n-git-lost-found\n-git-ls-files\n-git-ls-remote\n-git-ls-tree\n-git-mailinfo\n-git-mailsplit\n-git-merge\n-git-merge-base\n-git-merge-index\n-git-merge-file\n-git-merge-tree\n-git-merge-octopus\n-git-merge-one-file\n-git-merge-ours\n-git-merge-recursive\n-git-merge-resolve\n-git-merge-subtree\n-git-mergetool\n-git-mergetool--lib\n-git-mktag\n-git-mktree\n-git-name-rev\n-git-mv\n-git-pack-redundant\n-git-pack-objects\n-git-pack-refs\n-git-parse-remote\n-git-patch-id\n-git-peek-remote\n-git-prune\n-git-prune-packed\n-git-pull\n-git-push\n-git-quiltimport\n-git-read-tree\n-git-rebase\n-git-rebase--interactive\n-git-receive-pack\n-git-reflog\n-git-relink\n-git-remote\n-git-remote-curl\n-git-repack\n-git-replace\n-git-repo-config\n-git-request-pull\n-git-rerere\n-git-reset\n-git-rev-list\n-git-rev-parse\n-git-revert\n-git-rm\n-git-send-email\n-git-send-pack\n-git-sh-setup\n-git-shell\n-git-shortlog\n-git-show\n-git-show-branch\n-git-show-index\n-git-show-ref\n-git-stage\n-git-stash\n-git-status\n-git-stripspace\n-git-submodule\n-git-svn\n-git-symbolic-ref\n-git-tag\n-git-tar-tree\n-git-unpack-file\n-git-unpack-objects\n-git-update-index\n-git-update-ref\n-git-update-server-info\n-git-upload-archive\n-git-upload-pack\n-git-var\n-git-verify-pack\n-git-verify-tag\n-git-web--browse\n-git-whatchanged\n-git-write-tree\n-git-core-*/?*\n-gitk-wish\n-gitweb/gitweb.cgi\n-test-chmtime\n-test-ctype\n-test-date\n-test-delta\n-test-dump-cache-tree\n-test-genrandom\n-test-match-trees\n-test-parse-options\n-test-path-utils\n-test-sha1\n-test-sigchain\n-common-cmds.h\n+/GIT-BUILD-OPTIONS\n+/GIT-CFLAGS\n+/GIT-GUI-VARS\n+/GIT-VERSION-FILE\n+/git\n+/git-add\n+/git-add--interactive\n+/git-am\n+/git-annotate\n+/git-apply\n+/git-archimport\n+/git-archive\n+/git-bisect\n+/git-bisect--helper\n+/git-blame\n+/git-branch\n+/git-bundle\n+/git-cat-file\n+/git-check-attr\n+/git-check-ref-format\n+/git-checkout\n+/git-checkout-index\n+/git-cherry\n+/git-cherry-pick\n+/git-clean\n+/git-clone\n+/git-commit\n+/git-commit-tree\n+/git-config\n+/git-count-objects\n+/git-cvsexportcommit\n+/git-cvsimport\n+/git-cvsserver\n+/git-daemon\n+/git-diff\n+/git-diff-files\n+/git-diff-index\n+/git-diff-tree\n+/git-difftool\n+/git-difftool--helper\n+/git-describe\n+/git-fast-export\n+/git-fast-import\n+/git-fetch\n+/git-fetch--tool\n+/git-fetch-pack\n+/git-filter-branch\n+/git-fmt-merge-msg\n+/git-for-each-ref\n+/git-format-patch\n+/git-fsck\n+/git-fsck-objects\n+/git-gc\n+/git-get-tar-commit-id\n+/git-grep\n+/git-hash-object\n+/git-help\n+/git-http-fetch\n+/git-http-push\n+/git-imap-send\n+/git-index-pack\n+/git-init\n+/git-init-db\n+/git-instaweb\n+/git-log\n+/git-lost-found\n+/git-ls-files\n+/git-ls-remote\n+/git-ls-tree\n+/git-mailinfo\n+/git-mailsplit\n+/git-merge\n+/git-merge-base\n+/git-merge-index\n+/git-merge-file\n+/git-merge-tree\n+/git-merge-octopus\n+/git-merge-one-file\n+/git-merge-ours\n+/git-merge-recursive\n+/git-merge-resolve\n+/git-merge-subtree\n+/git-mergetool\n+/git-mergetool--lib\n+/git-mktag\n+/git-mktree\n+/git-name-rev\n+/git-mv\n+/git-pack-redundant\n+/git-pack-objects\n+/git-pack-refs\n+/git-parse-remote\n+/git-patch-id\n+/git-peek-remote\n+/git-prune\n+/git-prune-packed\n+/git-pull\n+/git-push\n+/git-quiltimport\n+/git-read-tree\n+/git-rebase\n+/git-rebase--interactive\n+/git-receive-pack\n+/git-reflog\n+/git-relink\n+/git-remote\n+/git-remote-curl\n+/git-repack\n+/git-replace\n+/git-repo-config\n+/git-request-pull\n+/git-rerere\n+/git-reset\n+/git-rev-list\n+/git-rev-parse\n+/git-revert\n+/git-rm\n+/git-send-email\n+/git-send-pack\n+/git-sh-setup\n+/git-shell\n+/git-shortlog\n+/git-show\n+/git-show-branch\n+/git-show-index\n+/git-show-ref\n+/git-stage\n+/git-stash\n+/git-status\n+/git-stripspace\n+/git-submodule\n+/git-svn\n+/git-symbolic-ref\n+/git-tag\n+/git-tar-tree\n+/git-unpack-file\n+/git-unpack-objects\n+/git-update-index\n+/git-update-ref\n+/git-update-server-info\n+/git-upload-archive\n+/git-upload-pack\n+/git-var\n+/git-verify-pack\n+/git-verify-tag\n+/git-web--browse\n+/git-whatchanged\n+/git-write-tree\n+/git-core-*/?*\n+/gitk-git/gitk-wish\n+/gitweb/gitweb.cgi\n+/test-chmtime\n+/test-ctype\n+/test-date\n+/test-delta\n+/test-dump-cache-tree\n+/test-genrandom\n+/test-match-trees\n+/test-parse-options\n+/test-path-utils\n+/test-sha1\n+/test-sigchain\n+/common-cmds.h\n *.tar.gz\n *.dsc\n *.deb\n-git.spec\n+/git.spec\n *.exe\n *.[aos]\n *.py[co]\n-config.mak\n-autom4te.cache\n-config.cache\n-config.log\n-config.status\n-config.mak.autogen\n-config.mak.append\n-configure\n-tags\n-TAGS\n-cscope*\n+/config.mak\n+/autom4te.cache\n+/config.cache\n+/config.log\n+/config.status\n+/config.mak.autogen\n+/config.mak.append\n+/configure\n+/tags\n+/TAGS\n+/cscope*\n *.obj\n *.lib\n *.sln\n@@ -188,5 +188,5 @@ cscope*\n *.user\n *.idb\n *.pdb\n-Debug/\n-Release/\n+/Debug/\n+/Release/\n-- \n1.6.5.1.203.g342e8\n"},{"id":"126086","messageId":"7vmy3cys0f.fsf@alter.siamese.dyndns.org","threadId":"21369","inReplyTo":"20091027011024.GA29361@sigio.peff.net","subject":"Re: [PATCH] gitignore: root most patterns at the top-level directory","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-10-28T06:03:28Z","receivedAt":"2009-10-28T06:03:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> Our gitignore doesn't use a preceding \"/\" to root its\n> patterns in the top of the repository. This means that if\n> you add a file or directory called \"git\" (for example)\n> inside a subdirectory, it will be erroneously ignored.\n>\n> This patch was done mechanically with \"s/^[^*]/\\/&/\" with\n> one exception: instead of ignoring gitk-wish, we should\n> gitk-git/gitk-wish (arguably, this should be done in\n> gitk-git/.gitignore, but because that is a subtree merge\n> from elsewhere, this is easier).\n>\n> Acked-by: Sverre Rabbelier <srabbelier@gmail.com>\n> Signed-off-by: Jeff King <peff@peff.net>\n> ---\n>\n> This bit Sverre while I was looking over his shoulder. I doubt it comes\n> up very often, but we should probably be modeling good gitignore\n> behavior. I have to admit it looks a lot uglier, though.\n\nHow does .cvsignore and .svnignore work?  Don't they have the same issue,\nand perhaps worse as I do not recall seeing a way to anchor a pattern to a\nparticular directory like we do in their .SCMignore files?  And judging\nfrom the fact that they can get away with the lack of that \"feature\", this\nperhaps is not an issue in real life?\n\nI am actually a bit reluctant to queue this, even though I most likely\nwill, and then hope that we will think of a better solution later, at\nwhich time this file again needs to change.\n\nFor example, it crossed my mind that perhaps we can change the ignore\nrules so that a non-globbing pattern is automatically anchored at the\ncurrent directly but globbing ones are recursive as before.\n\nIf we do so, there is no need to change the current .gitignore entires.\nYou need to spell a concrete filename as a glob pattern that matches only\none path if you want the recursive behaviour.  E.g. if you have a Makefile\nper subdirectory, each of which generates and includes Makefile.depend\nfile, you would write \"Makefile.depen[d]\" in the toplevel .gitignore file.\n\nBut that is a kind of incompatible change whose necessity is unproven and\nhas to cook and wait.\n"},{"id":"126107","messageId":"4AE7F0DC.6010508@viscovery.net","threadId":"21369","inReplyTo":"7vmy3cys0f.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] gitignore: root most patterns at the top-level directory","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2009-10-28T07:21:00Z","receivedAt":"2009-10-28T07:21:00Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Junio C Hamano schrieb:\n> How does .cvsignore and .svnignore work?  Don't they have the same issue,\n> and perhaps worse as I do not recall seeing a way to anchor a pattern to a\n> particular directory like we do in their .SCMignore files?  And judging\n> from the fact that they can get away with the lack of that \"feature\", this\n> perhaps is not an issue in real life?\n\n.cvsignore and .svnignore do not apply recursively to subdirectories, do they?\n\n> For example, it crossed my mind that perhaps we can change the ignore\n> rules so that a non-globbing pattern is automatically anchored at the\n> current directly but globbing ones are recursive as before.\n> \n> If we do so, there is no need to change the current .gitignore entires.\n> You need to spell a concrete filename as a glob pattern that matches only\n> one path if you want the recursive behaviour.  E.g. if you have a Makefile\n> per subdirectory, each of which generates and includes Makefile.depend\n> file, you would write \"Makefile.depen[d]\" in the toplevel .gitignore file.\n\nIn one project that uses autotools, I have \"Makefile\" and \"Makefile.in\" in\nthe top-level .gitignore. I would be forced to use this ugliness instead.\n\nGranted, to write \"/git\", \"/git-add\", etc in .gitignore is not exactly\npretty, either, but the reason that it is so extra-ugly in the git code\nitself is only because there are so many build products in a single\ndirectory that cannot be caught by a glob pattern. In practice, you\nusually have only a hand-full non-glob ignored files per directory; it\ndoesn't hurt to anchor them using \"/frotz\" style.\n\n> But that is a kind of incompatible change whose necessity is unproven and\n> has to cook and wait.\n\nI would be concerned by this change.\n\n-- Hannes\n"},{"id":"126402","messageId":"20091030182431.GA19901@coredump.intra.peff.net","threadId":"21369","inReplyTo":"7vmy3cys0f.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] gitignore: root most patterns at the top-level directory","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-10-30T18:24:32Z","receivedAt":"2009-10-30T18:24:32Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Oct 27, 2009 at 11:03:28PM -0700, Junio C Hamano wrote:\n\n> How does .cvsignore and .svnignore work?  Don't they have the same issue,\n> and perhaps worse as I do not recall seeing a way to anchor a pattern to a\n> particular directory like we do in their .SCMignore files?  And judging\n> from the fact that they can get away with the lack of that \"feature\", this\n> perhaps is not an issue in real life?\n\nHappily, I did not remember how .cvsignore worked and had to go read the\ndocumentation. :) The answer is that no, it does not have the recursive\nfeature in the root .cvsignore list at all. But it does apply the\nrepo-wide CVSROOT/cvsignore, the user's ~/.cvsignore, and the\nenvironment's $CVSIGNORE to all directories. So it is safe from this\nproblem (though now that I think on it, I think I was once bitten by\nsomething similar in the CVSROOT/cvsignore).\n\nSVN implements this with \"properties\" on the directories. They are not\nrecursive at all. However, it also implements \"global-ignores\" which\napplies everywhere.\n\nSo no, they don't have the same issue, because they explicitly split the\n\"everywhere\" and \"this directory\" cases into two locations. We wouldn't\nwant to use .git/info/excludes for this, because we do want to support\nthe project shipping some global excludes itself.\n\n> I am actually a bit reluctant to queue this, even though I most likely\n> will, and then hope that we will think of a better solution later, at\n> which time this file again needs to change.\n\nI am mixed on it, as well. I did see it bite someone, but I think it's\nvery rare, and everyone who reads or touches the file will have to deal\nwith the ugliness every time. If you want to drop the patch, I will not\ncomplain.\n\n> For example, it crossed my mind that perhaps we can change the ignore\n> rules so that a non-globbing pattern is automatically anchored at the\n> current directly but globbing ones are recursive as before.\n\nThat makes some sense to me (and in fact when making the patch, it was\nthe rule of thumb I used). Though I think you might want to make it\n\"starts with glob\" as the trigger for the rule. We have \"git-core-*/?*\",\nwhich I would expect to still be anchored at the root.\n\n> If we do so, there is no need to change the current .gitignore entires.\n> You need to spell a concrete filename as a glob pattern that matches only\n> one path if you want the recursive behaviour.  E.g. if you have a Makefile\n> per subdirectory, each of which generates and includes Makefile.depend\n> file, you would write \"Makefile.depen[d]\" in the toplevel .gitignore file.\n\nWhile clever, that use of '[d]' seems unneccessarily obscure to me. Why\nnot just give a wildcard for \"any subdirectory of me\" and do:\n\n  Makefile.depend\n  **/Makefile.depend\n\nSince \"**\" is in common use in other systems, it's pretty clear (to me,\nanyway, but then I am the one suggesting the syntax ;) ) what that\nmeans.\n\n-Peff\n"},{"id":"126436","messageId":"885649360910301452g7d7311d7w1133f5d4c98072dc@mail.gmail.com","threadId":"21369","inReplyTo":"20091030182431.GA19901@coredump.intra.peff.net","subject":"Re: [PATCH] gitignore: root most patterns at the top-level directory","fromName":"James Pickens","fromEmail":"jepicken@gmail.com","sentAt":"2009-10-30T21:52:07Z","receivedAt":"2009-10-30T21:52:07Z","isPatch":true,"sender":{"key":"jepicken@gmail.com","avatar":null},"body":"On Fri, Oct 30, 2009 at 11:24 AM, Jeff King <peff@peff.net> wrote:\n>> If we do so, there is no need to change the current .gitignore entires.\n>> You need to spell a concrete filename as a glob pattern that matches only\n>> one path if you want the recursive behaviour.  E.g. if you have a Makefile\n>> per subdirectory, each of which generates and includes Makefile.depend\n>> file, you would write \"Makefile.depen[d]\" in the toplevel .gitignore file.\n>\n> While clever, that use of '[d]' seems unneccessarily obscure to me. Why\n> not just give a wildcard for \"any subdirectory of me\" and do:\n>\n>  Makefile.depend\n>  **/Makefile.depend\n>\n> Since \"**\" is in common use in other systems, it's pretty clear (to me,\n> anyway, but then I am the one suggesting the syntax ;) ) what that\n> means.\n\n+1 to that.  I've often wished for Git to support the ** wildcard, not only in\n.gitignore but also in other places like .gitattributes and sparse checkout (if\nthat feature ever gets completed anyways).  It's on my list of \"git features I\nwould work on if I ever had any free time.\"\n\nJames\n"}]}