{"thread":{"id":"41779","subject":"git-apply does not work in a sub-directory of a Git repository","startedAt":"2016-03-22T12:10:17Z","lastAt":"2016-03-30T17:13:56Z","messageCount":18,"participants":["Mehul Jain","Stefan Beller","Duy Nguyen","Junio C Hamano","Nguyễn Thái Ngọc Duy"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"281428","messageId":"CA+DCAeQQQH59Lb43Y4Bi1xktPNoODV11KkUBbKNG1OZ7mDb-UQ@mail.gmail.com","threadId":"41779","inReplyTo":null,"subject":"git-apply does not work in a sub-directory of a Git repository","fromName":"Mehul Jain","fromEmail":"mehul.jain2029@gmail.com","sentAt":"2016-03-22T12:10:17Z","receivedAt":"2016-03-22T12:10:17Z","isPatch":false,"sender":{"key":"mehul.jain2029@gmail.com","avatar":"https://avatars.githubusercontent.com/u/14936539?v=4"},"body":"Hello everyone,\n\nRecently while using git-apply, I observed that if git-apply is used in a\nsub-directory of a Git repository then it silently dies without doing\nanything.\n\nHere's what I did\n\n~ $mkdir example\n~ $cd example\nexample $git init\nInitialized empty Git repository in /home/mj/example/.git/\nexample $echo main >main\nexample $git add main\nexample $git commit -m 'main'\n[master (root-commit) 97aeda3] main\n 1 file changed, 1 insertion(+)\n create mode 100644 main\nexample $git checkout -b feature\nSwitched to a new branch 'feature'\nexample $echo modified >main\nexample $git add main\nexample $git commit -m 'modified'\n[feature 2551fa2] modified\n 1 file changed, 1 insertion(+), 1 deletion(-)\nexample $mkdir outgoing\nexample $git diff master >outgoing/feature.patch\nexample $git checkout master\nSwitched to branch 'master'\nexample $cd outgoing/\noutgoing $git apply feature.patch\noutgoing $cd ..\nexample $cat main\nmain\n\nAs you observed, patch wasn't applied. Is it intended behaviour of\ngit-apply? Usually to apply the patch I have to copy it to top directory\nand then use git-apply.\n\nI tried out git-am to apply the patch (\"git format-patch\" was used to\nmake patch) while being in the \"outgoing\" sub-directory and it worked\nfine. So why does git-apply show this kind of behaviour?\n\nThanks,\nMehul\n"},{"id":"281501","messageId":"CAGZ79kYmoKX1w5X8jE5_yGb3VKricHEwxAianTyt4VUd71qH-A@mail.gmail.com","threadId":"41779","inReplyTo":"CA+DCAeQQQH59Lb43Y4Bi1xktPNoODV11KkUBbKNG1OZ7mDb-UQ@mail.gmail.com","subject":"Re: git-apply does not work in a sub-directory of a Git repository","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2016-03-22T22:14:56Z","receivedAt":"2016-03-22T22:14:56Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Tue, Mar 22, 2016 at 5:10 AM, Mehul Jain <mehul.jain2029@gmail.com> wrote:\n> Hello everyone,\n>\n> Recently while using git-apply, I observed that if git-apply is used in a\n> sub-directory of a Git repository then it silently dies without doing\n> anything.\n>\n> Here's what I did\n>\n> ~ $mkdir example\n> ~ $cd example\n> example $git init\n> Initialized empty Git repository in /home/mj/example/.git/\n> example $echo main >main\n> example $git add main\n> example $git commit -m 'main'\n> [master (root-commit) 97aeda3] main\n>  1 file changed, 1 insertion(+)\n>  create mode 100644 main\n> example $git checkout -b feature\n> Switched to a new branch 'feature'\n> example $echo modified >main\n> example $git add main\n> example $git commit -m 'modified'\n> [feature 2551fa2] modified\n>  1 file changed, 1 insertion(+), 1 deletion(-)\n> example $mkdir outgoing\n> example $git diff master >outgoing/feature.patch\n> example $git checkout master\n> Switched to branch 'master'\n> example $cd outgoing/\n> outgoing $git apply feature.patch\n> outgoing $cd ..\n> example $cat main\n> main\n>\n> As you observed, patch wasn't applied. Is it intended behaviour of\n> git-apply? Usually to apply the patch I have to copy it to top directory\n> and then use git-apply.\n>\n> I tried out git-am to apply the patch (\"git format-patch\" was used to\n> make patch) while being in the \"outgoing\" sub-directory and it worked\n> fine. So why does git-apply show this kind of behaviour?\n>\n> Thanks,\n> Mehul\n\n\nThink of git-apply as a specialized version of 'patch', which would also\nerror out if there are path issues. (Inside outgoing/ there is no file found at\n./main)\n\ngit-am is the porcelain command which is what is recommended to users\nwho interact with Git and patches.\n"},{"id":"281560","messageId":"CACsJy8DCk5YintK3PoO1BWdNmsiSLpAcGL4pU7QgNEG6S41CsQ@mail.gmail.com","threadId":"41779","inReplyTo":"CAGZ79kYmoKX1w5X8jE5_yGb3VKricHEwxAianTyt4VUd71qH-A@mail.gmail.com","subject":"Re: git-apply does not work in a sub-directory of a Git repository","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2016-03-23T10:15:28Z","receivedAt":"2016-03-23T10:15:28Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, Mar 23, 2016 at 5:14 AM, Stefan Beller <sbeller@google.com> wrote:\n>> Hello everyone,\n>> As you observed, patch wasn't applied. Is it intended behaviour of\n>> git-apply? Usually to apply the patch I have to copy it to top directory\n>> and then use git-apply.\n>>\n>> I tried out git-am to apply the patch (\"git format-patch\" was used to\n>> make patch) while being in the \"outgoing\" sub-directory and it worked\n>> fine. So why does git-apply show this kind of behaviour?\n>\n>\n> Think of git-apply as a specialized version of 'patch', which would also\n> error out if there are path issues. (Inside outgoing/ there is no file found at\n> ./main)\n>\n> git-am is the porcelain command which is what is recommended to users\n> who interact with Git and patches.\n\ngit-am is about patches in mailbox form, not plain patches, isn't it?\nIn that view, it's not a replacement for git-apply.\n\nHow about we start deprecating the old behavior?\n\n1) add --no-index to force git-apply ignore .git, --git (or some other\nname) to apply patches as if running from topdir, add a config key to\nchoose default behavior\n2) when git-apply is run without --git, --index or --cached from a\nsubdir and the said config key is not set, start warning and\nrecommending --no-index\n3) wait X years\n4)switch default behavior to --git (if run inside a git repo)\n-- \nDuy\n"},{"id":"281582","messageId":"xmqqbn65dxtl.fsf@gitster.mtv.corp.google.com","threadId":"41779","inReplyTo":"CACsJy8DCk5YintK3PoO1BWdNmsiSLpAcGL4pU7QgNEG6S41CsQ@mail.gmail.com","subject":"Re: git-apply does not work in a sub-directory of a Git repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-23T15:21:42Z","receivedAt":"2016-03-23T15:21:42Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Duy Nguyen <pclouds@gmail.com> writes:\n\n> 1) add --no-index to force git-apply ignore .git, --git (or some other\n> name) to apply patches as if running from topdir, add a config key to\n> choose default behavior\n\nI think we do have --no-index (which is why I am largely ignoring\nthe rest of your message as uninformed speculation for now).\n\nSee\n\n  http://thread.gmane.org/gmane.comp.version-control.git/288316/focus=288321\n\nI agree it is bad that it silently ignores the path outside the\ndirectory.  When run with --verbose, we should say \"Skipped X that\nis outside the directory.\" or something like that, just like we\nissue notices when we applied with offset, etc.\n"},{"id":"281592","messageId":"xmqqlh59cexj.fsf@gitster.mtv.corp.google.com","threadId":"41779","inReplyTo":"xmqqbn65dxtl.fsf@gitster.mtv.corp.google.com","subject":"Re: git-apply does not work in a sub-directory of a Git repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-23T16:55:04Z","receivedAt":"2016-03-23T16:55:04Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> See\n>\n>   http://thread.gmane.org/gmane.comp.version-control.git/288316/focus=288321\n>\n> I agree it is bad that it silently ignores the path outside the\n> directory.  When run with --verbose, we should say \"Skipped X that\n> is outside the directory.\" or something like that, just like we\n> issue notices when we applied with offset, etc.\n\nAnother thing we may want to do is to loosen (or redo) the logic\nin builtin/apply.c::use_patch()\n\n        static int use_patch(struct patch *p)\n        {\n                const char *pathname = p->new_name ? p->new_name : p->old_name;\n                int i;\n\n                /* Paths outside are not touched regardless of \"--include\" */\n                if (0 < prefix_length) {\n                        int pathlen = strlen(pathname);\n                        if (pathlen <= prefix_length ||\n                            memcmp(prefix, pathname, prefix_length))\n                                return 0;\n                }\n\nThe include/exclude mechanism does use wildmatch() but does not use\nthe pathspec mechanism (it predates the pathspec machinery that was\nmade reusable in places like this).  We should be able to\n\n    $ cd d/e/e/p/d/i/r\n    $ git apply --include=:/ ../../../../../../../patch\n\nto lift this limitation.  IOW, we can think of the use_patch() to\ninclude only the paths in the subdirectory we are in by default, but\nwe can make it allow --include/--exclude command line option to\noverride that default.\n\nThat way, the plain-vanilla use would still retain the \"when working\nin subdirectory, we only touch that subdirectory\" behaviour, which\nexisting scripts may depend on, but users can loosen the default as\nnecessary.\n"},{"id":"281594","messageId":"CA+DCAeSE4CS8zg1tHP5kYOs-CbGk0uAzWX9Zh9Fk3O7mYwYTMQ@mail.gmail.com","threadId":"41779","inReplyTo":"xmqqbn65dxtl.fsf@gitster.mtv.corp.google.com","subject":"Re: git-apply does not work in a sub-directory of a Git repository","fromName":"Mehul Jain","fromEmail":"mehul.jain2029@gmail.com","sentAt":"2016-03-23T17:24:19Z","receivedAt":"2016-03-23T17:24:19Z","isPatch":false,"sender":{"key":"mehul.jain2029@gmail.com","avatar":"https://avatars.githubusercontent.com/u/14936539?v=4"},"body":"On Wed, Mar 23, 2016 at 8:51 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> I think we do have --no-index (which is why I am largely ignoring\n> the rest of your message as uninformed speculation for now).\n\n--no-index command line flag is there for git-apply but unfortunately not\ndocumented.\n\nAlso *auto-completion* for \"git apply --no-index\" doesn't work.\n\nThat is\n\n    git apply --no-i<tab><tab>\n\nshould be auto completed and give\n\n   git apply --no-index.\n\nProbably following change will remove this problem.\n\ndiff --git a/contrib/completion/git-completion.bash\nb/contrib/completion/git-completion.bash\nindex 45ec47f..860dae0 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -886,7 +886,7 @@ _git_apply ()\n                ;;\n        --*)\n                __gitcomp \"\n-                       --stat --numstat --summary --check --index\n+                       --stat --numstat --summary --check --index --no-index\n                        --cached --index-info --reverse --reject --unidiff-zero\n                        --apply --no-add --exclude=\n                        --ignore-whitespace --ignore-space-change\n"},{"id":"281659","messageId":"CACsJy8CTix-ZwN04MwYTB+JEtDCV27QVf7_0vWmhUSVCwU29Jg@mail.gmail.com","threadId":"41779","inReplyTo":"xmqqlh59cexj.fsf@gitster.mtv.corp.google.com","subject":"Re: git-apply does not work in a sub-directory of a Git repository","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2016-03-24T10:49:05Z","receivedAt":"2016-03-24T10:49:05Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, Mar 23, 2016 at 11:55 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n>> See\n>>\n>>   http://thread.gmane.org/gmane.comp.version-control.git/288316/focus=288321\n>>\n>> I agree it is bad that it silently ignores the path outside the\n>> directory.  When run with --verbose, we should say \"Skipped X that\n>> is outside the directory.\" or something like that, just like we\n>> issue notices when we applied with offset, etc.\n>\n> Another thing we may want to do is to loosen (or redo) the logic\n> in builtin/apply.c::use_patch()\n>\n>         static int use_patch(struct patch *p)\n>         {\n>                 const char *pathname = p->new_name ? p->new_name : p->old_name;\n>                 int i;\n>\n>                 /* Paths outside are not touched regardless of \"--include\" */\n>                 if (0 < prefix_length) {\n>                         int pathlen = strlen(pathname);\n>                         if (pathlen <= prefix_length ||\n>                             memcmp(prefix, pathname, prefix_length))\n>                                 return 0;\n>                 }\n>\n> The include/exclude mechanism does use wildmatch() but does not use\n> the pathspec mechanism (it predates the pathspec machinery that was\n> made reusable in places like this).  We should be able to\n>\n>     $ cd d/e/e/p/d/i/r\n>     $ git apply --include=:/ ../../../../../../../patch\n>\n> to lift this limitation.  IOW, we can think of the use_patch() to\n> include only the paths in the subdirectory we are in by default, but\n> we can make it allow --include/--exclude command line option to\n> override that default.\n\nInteresting. Disabling that comment block seems to work ok. So\ngit-apply works more like git-grep, automatically narrowing to current\nsubdir, rather than full-tree like git-status. git-apply.txt should\nprobably mention about this because (at least to me) it sounds more\nnaturally that if I give a patch, git-apply should apply the whole\npatch.\n\nWe probably should show a warning if everything file is filtered out\ntoo because silence usually means \"good\" from a typical unix command.\nIt could be guarded with advice config key, and should only show if it\nlooks like there are matching paths on worktree, but filtered out.\nHmm?\n\n> That way, the plain-vanilla use would still retain the \"when working\n> in subdirectory, we only touch that subdirectory\" behaviour, which\n> existing scripts may depend on, but users can loosen the default as\n> necessary.\n-- \nDuy\n"},{"id":"281661","messageId":"1458820579-31621-1-git-send-email-pclouds@gmail.com","threadId":"41779","inReplyTo":"CACsJy8CTix-ZwN04MwYTB+JEtDCV27QVf7_0vWmhUSVCwU29Jg@mail.gmail.com","subject":"Re: git-apply does not work in a sub-directory of a Git repository","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2016-03-24T11:56:15Z","receivedAt":"2016-03-24T11:56:15Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"+Brian who also had issues with git-apply.\n\nOn Thu, Mar 24, 2016 at 5:49 PM, Duy Nguyen <pclouds@gmail.com> wrote:\n> On Wed, Mar 23, 2016 at 11:55 PM, Junio C Hamano <gitster@pobox.com> wrote:\n>> Junio C Hamano <gitster@pobox.com> writes:\n>>\n>>> See\n>>>\n>>>   http://thread.gmane.org/gmane.comp.version-control.git/288316/focus=288321\n>>>\n>>> I agree it is bad that it silently ignores the path outside the\n>>> directory.  When run with --verbose, we should say \"Skipped X that\n>>> is outside the directory.\" or something like that, just like we\n>>> issue notices when we applied with offset, etc.\n\nImplemented in [04/04] apply: report patch skipping in verbose mode.\n\n>> Another thing we may want to do is to loosen (or redo) the logic\n>> in builtin/apply.c::use_patch()\n>>\n>>         static int use_patch(struct patch *p)\n>>         {\n>>                 const char *pathname = p->new_name ? p->new_name : p->old_name;\n>>                 int i;\n>>\n>>                 /* Paths outside are not touched regardless of \"--include\" */\n>>                 if (0 < prefix_length) {\n>>                         int pathlen = strlen(pathname);\n>>                         if (pathlen <= prefix_length ||\n>>                             memcmp(prefix, pathname, prefix_length))\n>>                                 return 0;\n>>                 }\n>>\n>> The include/exclude mechanism does use wildmatch() but does not use\n>> the pathspec mechanism (it predates the pathspec machinery that was\n>> made reusable in places like this).  We should be able to\n>>\n>>     $ cd d/e/e/p/d/i/r\n>>     $ git apply --include=:/ ../../../../../../../patch\n>>\n>> to lift this limitation.  IOW, we can think of the use_patch() to\n>> include only the paths in the subdirectory we are in by default, but\n>> we can make it allow --include/--exclude command line option to\n>> override that default.\n\nI went with a new option instead of changing --include. Making it\npathspec can still bite people. And pathspec is not exactly compatible\nwith wildmatch either. This is in\n\n  [03/04] apply: add --whole to apply git patch without prefix filtering\n\n> git-apply.txt should\n> probably mention about this because (at least to me) it sounds more\n> naturally that if I give a patch, git-apply should apply the whole\n> patch.\n\n  [02/04] git-apply.txt: mention the behavior inside a subdir\n\n> We probably should show a warning if everything file is filtered out\n> too because silence usually means \"good\" from a typical unix command.\n> It could be guarded with advice config key, and should only show if it\n> looks like there are matching paths on worktree, but filtered out.\n\nI'm holding this back. Too much heuristics.\n--\nDuy\n"},{"id":"281662","messageId":"1458820579-31621-2-git-send-email-pclouds@gmail.com","threadId":"41779","inReplyTo":"1458820579-31621-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 1/4] git-apply.txt: remove a space","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2016-03-24T11:56:16Z","receivedAt":"2016-03-24T11:56:16Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/git-apply.txt | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt\nindex d9ed6a1..5444d2f 100644\n--- a/Documentation/git-apply.txt\n+++ b/Documentation/git-apply.txt\n@@ -13,7 +13,7 @@ SYNOPSIS\n \t  [--apply] [--no-add] [--build-fake-ancestor=<file>] [-R | --reverse]\n \t  [--allow-binary-replacement | --binary] [--reject] [-z]\n \t  [-p<n>] [-C<n>] [--inaccurate-eof] [--recount] [--cached]\n-\t  [--ignore-space-change | --ignore-whitespace ]\n+\t  [--ignore-space-change | --ignore-whitespace]\n \t  [--whitespace=(nowarn|warn|fix|error|error-all)]\n \t  [--exclude=<path>] [--include=<path>] [--directory=<root>]\n \t  [--verbose] [--unsafe-paths] [<patch>...]\n-- \n2.8.0.rc0.210.gd302cd2\n"},{"id":"281663","messageId":"1458820579-31621-3-git-send-email-pclouds@gmail.com","threadId":"41779","inReplyTo":"1458820579-31621-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 2/4] git-apply.txt: mention the behavior inside a subdir","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2016-03-24T11:56:17Z","receivedAt":"2016-03-24T11:56:17Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/git-apply.txt | 2 ++\n 1 file changed, 2 insertions(+)\n\ndiff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt\nindex 5444d2f..8ddb207 100644\n--- a/Documentation/git-apply.txt\n+++ b/Documentation/git-apply.txt\n@@ -21,6 +21,8 @@ SYNOPSIS\n DESCRIPTION\n -----------\n Reads the supplied diff output (i.e. \"a patch\") and applies it to files.\n+When running from a subdirectory in a repository, patched paths\n+outside the directory are ignored.\n With the `--index` option the patch is also applied to the index, and\n with the `--cached` option the patch is only applied to the index.\n Without these options, the command applies the patch only to files,\n-- \n2.8.0.rc0.210.gd302cd2\n"},{"id":"281664","messageId":"1458820579-31621-4-git-send-email-pclouds@gmail.com","threadId":"41779","inReplyTo":"1458820579-31621-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 3/4] apply: add --whole to apply git patch without prefix filtering","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2016-03-24T11:56:18Z","receivedAt":"2016-03-24T11:56:18Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Back in edf2e37 (git-apply: work from subdirectory. - 2005-11-25),\ngit-apply is made to work from a subdir of a worktree. When applying a\ngit patch this way, only paths in the subdir are patched, the rest is\nfiltered out. To apply without filtering, the user has to move back to\ntoplevel. Add --whole to make it more convenient to do so without moving\ncwd around.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/git-apply.txt |  8 +++++++-\n builtin/apply.c             |  4 +++-\n t/t4111-apply-subdir.sh     | 32 ++++++++++++++++++++++++++++++++\n 3 files changed, 42 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt\nindex 8ddb207..47cea57 100644\n--- a/Documentation/git-apply.txt\n+++ b/Documentation/git-apply.txt\n@@ -13,7 +13,7 @@ SYNOPSIS\n \t  [--apply] [--no-add] [--build-fake-ancestor=<file>] [-R | --reverse]\n \t  [--allow-binary-replacement | --binary] [--reject] [-z]\n \t  [-p<n>] [-C<n>] [--inaccurate-eof] [--recount] [--cached]\n-\t  [--ignore-space-change | --ignore-whitespace]\n+\t  [--ignore-space-change | --ignore-whitespace] [--whole]\n \t  [--whitespace=(nowarn|warn|fix|error|error-all)]\n \t  [--exclude=<path>] [--include=<path>] [--directory=<root>]\n \t  [--verbose] [--unsafe-paths] [<patch>...]\n@@ -154,6 +154,12 @@ discouraged.\n \tflag was the way to do so.  Currently we always allow binary\n \tpatch application, so this is a no-op.\n \n+--whole::\n+\tNormally when running inside a subdirectory of a working area,\n+\tpatched files outside current directory is filtered out. This option\n+\tmakes `git apply` to apply them all. All paths are still subject\n+\tto `--exclude` and `--include` fitlering if present.\n+\n --exclude=<path-pattern>::\n \tDon't apply changes to files matching the given path pattern. This can\n \tbe useful when importing patchsets, where you want to exclude certain\ndiff --git a/builtin/apply.c b/builtin/apply.c\nindex 42c610e..01e1d5e 100644\n--- a/builtin/apply.c\n+++ b/builtin/apply.c\n@@ -80,6 +80,7 @@ static const char *patch_input_file;\n static struct strbuf root = STRBUF_INIT;\n static int read_stdin = 1;\n static int options;\n+static int apply_whole;\n \n static void parse_whitespace_option(const char *option)\n {\n@@ -1956,7 +1957,7 @@ static int use_patch(struct patch *p)\n \tint i;\n \n \t/* Paths outside are not touched regardless of \"--include\" */\n-\tif (0 < prefix_length) {\n+\tif (!apply_whole && 0 < prefix_length) {\n \t\tint pathlen = strlen(pathname);\n \t\tif (pathlen <= prefix_length ||\n \t\t    memcmp(prefix, pathname, prefix_length))\n@@ -4565,6 +4566,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix_)\n \t\tOPT_BIT(0, \"recount\", &options,\n \t\t\tN_(\"do not trust the line counts in the hunk headers\"),\n \t\t\tRECOUNT),\n+\t\tOPT_BOOL(0, \"whole\", &apply_whole, N_(\"apply whole patch\")),\n \t\t{ OPTION_CALLBACK, 0, \"directory\", NULL, N_(\"root\"),\n \t\t\tN_(\"prepend <root> to all filenames\"),\n \t\t\t0, option_parse_directory },\ndiff --git a/t/t4111-apply-subdir.sh b/t/t4111-apply-subdir.sh\nindex 1618a6d..e5cd019 100755\n--- a/t/t4111-apply-subdir.sh\n+++ b/t/t4111-apply-subdir.sh\n@@ -153,4 +153,36 @@ test_expect_success 'apply --cached from subdir of .git dir' '\n \ttest_cmp expected.subdir actual.subdir\n '\n \n+test_expect_success 'setup a git patch' '\n+\tcat >gitpatch <<-\\EOF &&\n+\tdiff --git a/file b/file\n+\t--- a/file\n+\t+++ b/file\n+\t@@ -1 +1,2 @@\n+\t 1\n+\t+2\n+\tEOF\n+\tgitpatch=\"$(pwd)/gitpatch\"\n+'\n+\n+test_expect_success 'apply a git patch from subdir of toplevel' '\n+\treset_subdir other preimage &&\n+\t(\n+\t\tcd sub/dir &&\n+\t\tgit apply \"$gitpatch\"\n+\t) &&\n+\ttest_cmp preimage sub/dir/file &&\n+\ttest_cmp preimage file\n+'\n+\n+test_expect_success 'apply the whole git patch from subdir of toplevel' '\n+\treset_subdir other preimage &&\n+\t(\n+\t\tcd sub/dir &&\n+\t\tgit apply --whole \"$gitpatch\"\n+\t) &&\n+\ttest_cmp preimage sub/dir/file &&\n+\ttest_cmp postimage file\n+'\n+\n test_done\n-- \n2.8.0.rc0.210.gd302cd2\n"},{"id":"281665","messageId":"1458820579-31621-5-git-send-email-pclouds@gmail.com","threadId":"41779","inReplyTo":"1458820579-31621-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 4/4] apply: report patch skipping in verbose mode","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2016-03-24T11:56:19Z","receivedAt":"2016-03-24T11:56:19Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/apply.c | 2 ++\n 1 file changed, 2 insertions(+)\n\ndiff --git a/builtin/apply.c b/builtin/apply.c\nindex 01e1d5e..9cbb186 100644\n--- a/builtin/apply.c\n+++ b/builtin/apply.c\n@@ -4384,6 +4384,8 @@ static int apply_patch(int fd, const char *filename, int options)\n \t\t\tlistp = &patch->next;\n \t\t}\n \t\telse {\n+\t\t\tif (apply_verbosely)\n+\t\t\t\tsay_patch_name(stderr, _(\"Skipped patch '%s'.\"), patch);\n \t\t\tfree_patch(patch);\n \t\t\tskipped_patch++;\n \t\t}\n-- \n2.8.0.rc0.210.gd302cd2\n"},{"id":"281683","messageId":"xmqqd1qjalfh.fsf@gitster.mtv.corp.google.com","threadId":"41779","inReplyTo":"CACsJy8CTix-ZwN04MwYTB+JEtDCV27QVf7_0vWmhUSVCwU29Jg@mail.gmail.com","subject":"Re: git-apply does not work in a sub-directory of a Git repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-24T16:29:54Z","receivedAt":"2016-03-24T16:29:54Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Duy Nguyen <pclouds@gmail.com> writes:\n\n>> The include/exclude mechanism does use wildmatch() but does not use\n>> the pathspec mechanism (it predates the pathspec machinery that was\n>> made reusable in places like this).  We should be able to\n>>\n>>     $ cd d/e/e/p/d/i/r\n>>     $ git apply --include=:/ ../../../../../../../patch\n>>\n>> to lift this limitation.  IOW, we can think of the use_patch() to\n>> include only the paths in the subdirectory we are in by default, but\n>> we can make it allow --include/--exclude command line option to\n>> override that default.\n>\n> Interesting. Disabling that comment block seems to work ok. So\n> git-apply works more like git-grep, automatically narrowing to current\n> subdir, rather than full-tree like git-status.\n\nWe used to have one argument when choosing between \"limit to cwd\" vs\n\"work on full-tree\" defaults, i.e. \"a full-tree thing can easily be\nlimited to cwd by passing '.' as a pathspec, but limited-to-cwd thing\ncannot be widened\" before we introduced the magic \"full-tree\" pathspec.\n\nThis \"limit to cwd\" behaviour of \"git apply\" predates that by\nseveral years.\n\n> git-apply.txt should\n> probably mention about this because (at least to me) it sounds more\n> naturally that if I give a patch, git-apply should apply the whole\n> patch.\n\nYes, documentation update is necessary.\n\n> We probably should show a warning if everything file is filtered out\n> too because silence usually means \"good\" from a typical unix command.\n\nWe should give an informational message if _anything_ is filtered\nout, I would say.\n"},{"id":"281684","messageId":"xmqq8u17akgn.fsf@gitster.mtv.corp.google.com","threadId":"41779","inReplyTo":"1458820579-31621-1-git-send-email-pclouds@gmail.com","subject":"Re: git-apply does not work in a sub-directory of a Git repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-24T16:50:48Z","receivedAt":"2016-03-24T16:50:48Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n>> On Wed, Mar 23, 2016 at 11:55 PM, Junio C Hamano <gitster@pobox.com> wrote:\n>>> The include/exclude mechanism does use wildmatch() but does not use\n>>> the pathspec mechanism (it predates the pathspec machinery that was\n>>> made reusable in places like this).  We should be able to\n>>>\n>>>     $ cd d/e/e/p/d/i/r\n>>>     $ git apply --include=:/ ../../../../../../../patch\n>>>\n>>> to lift this limitation.  IOW, we can think of the use_patch() to\n>>> include only the paths in the subdirectory we are in by default, but\n>>> we can make it allow --include/--exclude command line option to\n>>> override that default.\n>\n> I went with a new option instead of changing --include.\n\nIt might be a \"workable\" band-aid, but would be an unsatisfying UI\nif it were the endgame state.  You do not say \"git grep --whole\" (by\nthe way, \"whole\" is a bad option name, as you cannot tell \"100% of\n*what*\" you are referring to--what you are widening is the limit\nbased on the location in the directory structure, so the option name\nshould have some hint about it, e.g. \"full-tree\" or something) and\nthis command will become an odd-man-out.\n\nI haven't thought things through, but thinking out aloud a few\npoints...\n\n  An existing user/script may be working in a subdirectory of a huge\n  working tree and relies on the current behaviour that outside world\n  is excluded by default, and may be passing --exclude to further\n  limit the extent of damage by applying the patch to a subset of\n  paths in the current directory that itself is also huge.  And that\n  use case would not be harmed by such a change.\n\n  On the other hand, an existing user/script would not be passing an\n  \"--include\" that names outside the current subdirectory to force\n  them to be included, because it is known for the past 10 years not\n  to have any effect at all.\n\nSo a better alternative may be to conditionally disable the \"Paths\noutside are not touched regardless of --include\" logic, i.e. we\nexclude paths outside by default just as before, but if there is at\nleast one explicit \"--include\" given, we skip this \"return 0\".\n\nThat way, we do not have to commit to turning --include/--exclude to\npathspec (which I agree is a huge change in behaviour that may not\nbe a good idea) and we do not have to add \"--full-tree\" that is only\nunderstood by \"apply\" but not other commands that operate on the\ncurrent directory by default.\n\nI agree that the \"excluded because the path is outside cwd\" should\nbe reported just like we show notices when applying a hunk with\noffset, and that the \"excluded because the path is outside cwd\"\nshould be documented.\n"},{"id":"281691","messageId":"xmqqtwjv93yk.fsf@gitster.mtv.corp.google.com","threadId":"41779","inReplyTo":"xmqq8u17akgn.fsf@gitster.mtv.corp.google.com","subject":"Re: git-apply does not work in a sub-directory of a Git repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-24T17:32:35Z","receivedAt":"2016-03-24T17:32:35Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> So a better alternative may be to conditionally disable the \"Paths\n> outside are not touched regardless of --include\" logic, i.e. we\n> exclude paths outside by default just as before, but if there is at\n> least one explicit \"--include\" given, we skip this \"return 0\".\n>\n> That way, we do not have to commit to turning --include/--exclude to\n> pathspec (which I agree is a huge change in behaviour that may not\n> be a good idea) and we do not have to add \"--full-tree\" that is only\n> understood by \"apply\" but not other commands that operate on the\n> current directory by default.\n\nAnd the necessary change to do so may look like this.  With this:\n\n    $ git show >P\n    $ git reset --hard HEAD^\n    $ cd t\n    $ git apply -v ../P\n    $ git apply -v --include=\\* ../P\n\nseem to work as expected.\n\ndiff --git a/builtin/apply.c b/builtin/apply.c\nindex c993333..1af3f7e 100644\n--- a/builtin/apply.c\n+++ b/builtin/apply.c\n@@ -1955,8 +1955,8 @@ static int use_patch(struct patch *p)\n \tconst char *pathname = p->new_name ? p->new_name : p->old_name;\n \tint i;\n \n-\t/* Paths outside are not touched regardless of \"--include\" */\n-\tif (0 < prefix_length) {\n+\t/* Paths outside are not touched when there is no explicit \"--include\" */\n+\tif (!has_include && 0 < prefix_length) {\n \t\tint pathlen = strlen(pathname);\n \t\tif (pathlen <= prefix_length ||\n \t\t    memcmp(prefix, pathname, prefix_length))\n"},{"id":"282167","messageId":"CACsJy8BtOR-0FNSP5cggAz=X3Vm-do_N4V-z7=tvW28p14FMkw@mail.gmail.com","threadId":"41779","inReplyTo":"xmqq8u17akgn.fsf@gitster.mtv.corp.google.com","subject":"Re: git-apply does not work in a sub-directory of a Git repository","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2016-03-30T01:05:45Z","receivedAt":"2016-03-30T01:05:45Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, Mar 24, 2016 at 11:50 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n>\n>>> On Wed, Mar 23, 2016 at 11:55 PM, Junio C Hamano <gitster@pobox.com> wrote:\n>>>> The include/exclude mechanism does use wildmatch() but does not use\n>>>> the pathspec mechanism (it predates the pathspec machinery that was\n>>>> made reusable in places like this).  We should be able to\n>>>>\n>>>>     $ cd d/e/e/p/d/i/r\n>>>>     $ git apply --include=:/ ../../../../../../../patch\n>>>>\n>>>> to lift this limitation.  IOW, we can think of the use_patch() to\n>>>> include only the paths in the subdirectory we are in by default, but\n>>>> we can make it allow --include/--exclude command line option to\n>>>> override that default.\n>>\n>> I went with a new option instead of changing --include.\n>\n> It might be a \"workable\" band-aid, but would be an unsatisfying UI\n> if it were the endgame state.  You do not say \"git grep --whole\" (by\n> the way, \"whole\" is a bad option name, as you cannot tell \"100% of\n> *what*\" you are referring to--what you are widening is the limit\n> based on the location in the directory structure, so the option name\n> should have some hint about it, e.g. \"full-tree\" or something) and\n> this command will become an odd-man-out.\n>\n> I haven't thought things through, but thinking out aloud a few\n> points...\n>\n>   An existing user/script may be working in a subdirectory of a huge\n>   working tree and relies on the current behaviour that outside world\n>   is excluded by default, and may be passing --exclude to further\n>   limit the extent of damage by applying the patch to a subset of\n>   paths in the current directory that itself is also huge.  And that\n>   use case would not be harmed by such a change.\n>\n>   On the other hand, an existing user/script would not be passing an\n>   \"--include\" that names outside the current subdirectory to force\n>   them to be included, because it is known for the past 10 years not\n>   to have any effect at all.\n\nReal-world .gitignore patterns have taught me that even if it does not\nhave any effect, it might still be present in some scripts, waiting\nfor a chance to bite me.\n\n> So a better alternative may be to conditionally disable the \"Paths\n> outside are not touched regardless of --include\" logic, i.e. we\n> exclude paths outside by default just as before, but if there is at\n> least one explicit \"--include\" given, we skip this \"return 0\".\n>\n> That way, we do not have to commit to turning --include/--exclude to\n> pathspec (which I agree is a huge change in behaviour that may not\n> be a good idea) and we do not have to add \"--full-tree\" that is only\n> understood by \"apply\" but not other commands that operate on the\n> current directory by default.\n\nBut your suggestion is good and I can't think of any better. We could\nintroduce pathspec as ftiler after \"--\", but it does not look elegant,\nand it overlaps with --include/--exclude.\n\nPerhaps we can start to warn people if --include is specified but has\nno effect for a cycle or two, then we can do as you suggested?\n-- \nDuy\n"},{"id":"282205","messageId":"CACsJy8C3QtVmqS_HPHjdWhBssJkZ197yz9uA3XAb-TDiOhEUmg@mail.gmail.com","threadId":"41779","inReplyTo":"xmqq8u17akgn.fsf@gitster.mtv.corp.google.com","subject":"Re: git-apply does not work in a sub-directory of a Git repository","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2016-03-30T09:33:48Z","receivedAt":"2016-03-30T09:33:48Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, Mar 24, 2016 at 11:50 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> So a better alternative may be to conditionally disable the \"Paths\n> outside are not touched regardless of --include\" logic, i.e. we\n> exclude paths outside by default just as before, but if there is at\n> least one explicit \"--include\" given, we skip this \"return 0\".\n>\n> That way, we do not have to commit to turning --include/--exclude to\n> pathspec (which I agree is a huge change in behaviour that may not\n> be a good idea) and we do not have to add \"--full-tree\" that is only\n> understood by \"apply\" but not other commands that operate on the\n> current directory by default.\n\nSuppose I don't like git-apply's default behavior, I make an alias.ap\n= \"apply --include=*\". So far so good, but when I want to limit paths\nback to \"subdir\" (it does not have to be the same as cwd), how do I do\nit without typing resorting to typing \"git apply\" explicitly ? I don't\nsee an option to cancel out --include=*. For \"git ap --exclude=*\n--include=subdir\" to have that effect, we need to change\n\nfor (i = 0; i < limit_by_name.nr; i++) {\n\nin use_patch() to\n\nfor (i = limit_by_name.nr - 1; i >= 0; i--) {\n\nSimple change, but not exactly harmless.\n\nOff topic, but --include/--exclude should be able to deal with\nrelative path like --include=../*.c or --include=./*. I guess nobody\nhas complained about it, so it's not needed.\n-- \nDuy\n"},{"id":"282242","messageId":"xmqqvb43ubvv.fsf@gitster.mtv.corp.google.com","threadId":"41779","inReplyTo":"CACsJy8BtOR-0FNSP5cggAz=X3Vm-do_N4V-z7=tvW28p14FMkw@mail.gmail.com","subject":"Re: git-apply does not work in a sub-directory of a Git repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-30T17:13:56Z","receivedAt":"2016-03-30T17:13:56Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Duy Nguyen <pclouds@gmail.com> writes:\n\n> But your suggestion is good and I can't think of any better. We could\n> introduce pathspec as ftiler after \"--\", but it does not look elegant,\n> and it overlaps with --include/--exclude.\n\nI was imagining that we would allow the magic pathspec syntax used\nin --include/--exclude command line option parameter.  Nobody sane\nuses glob special characters in their pathnames and those that do\ndeserve whatever breakage that comes to them.\n\n> Perhaps we can start to warn people if --include is specified but has\n> no effect for a cycle or two, then we can do as you suggested?\n\nI do not think I'd be against going in that direction.\n"}]}