{"thread":{"id":"22202","subject":"Filenames and prefixes in extended diffs","startedAt":"2010-01-13T16:13:05Z","lastAt":"2010-01-18T23:22:07Z","messageCount":20,"participants":["Andreas Gruenbacher","Junio C Hamano","Nanako Shiraishi","Jeff King","David Aguilar"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"131487","messageId":"201001131713.05505.agruen@suse.de","threadId":"22202","inReplyTo":null,"subject":"Filenames and prefixes in extended diffs","fromName":"Andreas Gruenbacher","fromEmail":"agruen@suse.de","sentAt":"2010-01-13T16:13:05Z","receivedAt":"2010-01-13T16:13:05Z","isPatch":false,"sender":{"key":"agruen@suse.de","avatar":null},"body":"I'm having a problem filename prefixes in git's extended diffs for patches \nwhich rename or copy files: those patches include the old and new filenames in \n\"rename from\", \"rename to\", \"copy from\", and \"copy to\" headers, e.g.,\n\n\t$ git show -M\n\tdiff --git a/f b/g\n\tsimilarity index 87%\n\trename from f\n\trename to g\n\tindex f00c965..3bb459b 100644\n\t--- a/f\n\t+++ b/g\n\t@@ -8,3 +8,4 @@\n\t 8\n\t 9\n\t 10\n\t+11\n\nUnlike the filenames in the \"diff --git\", \"---\", and \"+++\" headers, the \n\"rename from\", \"rename to\", \"copy from\", and \"copy to\" filenames do not \ninclude prefixes.\n\nNow when applying a patch, GNU patch's -p option determines the number of \npathname components to strip off from filenames.  This obviously can't work \nconsistently for the prefixed and prefix-less headers.\n\nCan git be changed to include prefixes in all filenames?\n\nThe only alternative I see is to ignore the filenames in the rename/copy \nheaders and rely only on the \"diff --git\" line.  (The \"---\" and \"+++\" headers \nare not guaranteed to exist.)  What's worse, as already discussed here, the \n\"diff --git\" line uses space as a separator between filenames yet it doesn't \nquote spaces in filenames.  When being forced to ignore rename/copy headers, \nthis defect would make things much worse.\n\n\nAny ideas?\n\n\nThanks,\nAndreas\n"},{"id":"131518","messageId":"7v4ompn5u0.fsf@alter.siamese.dyndns.org","threadId":"22202","inReplyTo":"201001131713.05505.agruen@suse.de","subject":"Re: Filenames and prefixes in extended diffs","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-01-13T19:49:11Z","receivedAt":"2010-01-13T19:49:11Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Andreas Gruenbacher <agruen@suse.de> writes:\n\n> Any ideas?\n\nHow about studying what \"git-apply\" does?\n"},{"id":"131552","messageId":"7vfx69k0bu.fsf@alter.siamese.dyndns.org","threadId":"22202","inReplyTo":"201001131713.05505.agruen@suse.de","subject":"Re: Filenames and prefixes in extended diffs","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-01-14T00:16:21Z","receivedAt":"2010-01-14T00:16:21Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Andreas Gruenbacher <agruen@suse.de> writes:\n\n> Can git be changed to ...\n\nJust to save your time coming up with more ways to *change* git diff...\n\nEven though I wouldn't say _any_ change is too late to bring in, change in\nthe output format from \"git diff\" family _must_ be usable by \"git apply\"\npeople have been using for the last 4 years or so.\n\nSuppose your updated version of \"git diff\" with a certain set of options\nproduces output A, which is different from the output B you would get out\nof today's \"git diff\" that is run with the same set of options.\n\nIf \"git apply\" people have been using understands B (i.e. current output)\nand does something, the format change between A and B must be designed in\nsuch a way that the same \"git apply\" accepts A (i.e. your output) and do\nthe same thing.\n\nTwo examples:\n\n - \"git diff -M\" (or \"git show -M\") is _defined_ to show the filenames\n   without prefix on \"rename from\" line, and deployed \"git apply\" relies\n   on this definition to apply the patch to the file the patch was meant\n   to apply.  If your modified \"git diff -M\" changes it to add the prefix,\n   and existing \"git apply\" changes behaviour (either by rejecting your\n   output, or applying the patch to a wrong file), then such a change has\n   *no chance* of getting in.  It is merely a breakage.\n\n - If you say \"git diff --src-prefix=a/b/c --dst-prefix=x/y\", it _might_\n   produce something \"git apply\" won't grok (I haven't checked this,\n   though).  You can suggest to change the output from such a case to work\n   better.  We didn't work as expected so a change _could_ be a fix.\n\nThe output from \"git diff --no-index\" is an exception to the above rule.\nIt is primarily for people who have unmanaged contents and want to use\nfeatures of the git diff engine that are not found in other people's diff\nimplementations (e.g. wordwise colored diff), and the header part of its\noutput does not currently follow \"git diff\" convention to be grokkable by\n\"git apply\".\n\nFixing _that_ is a welcome change, but I suspect that there are corner\ncases, e.g. \"git diff --no-index frotz-1.2.36/ /tmp/frotz/\" (i.e. you have\na pristine version in frotz-1.2.36 directory, but your modified version is\nin /tmp/frtoz/) that might make fixing it fundamentally impossible (I\nhaven't looked into it for a long time, so it could be easy, but my gut\nfeeling is it isn't).\n"},{"id":"131719","messageId":"20100115223259.6117@nanako3.lavabit.com","threadId":"22202","inReplyTo":"7vfx69k0bu.fsf@alter.siamese.dyndns.org","subject":"Re: Filenames and prefixes in extended diffs","fromName":"Nanako Shiraishi","fromEmail":"nanako3@lavabit.com","sentAt":"2010-01-15T13:32:59Z","receivedAt":"2010-01-15T13:32:59Z","isPatch":false,"sender":{"key":"nanako3@lavabit.com","avatar":"https://gravatar.com/avatar/3777b9e201c5883a62b1a6fdf7c53f2d712d1d80989146063ea861e33aad72a8?d=mp&s=160"},"body":"Quoting Junio C Hamano <gitster@pobox.com>\n\n> The output from \"git diff --no-index\" is an exception to the above rule.\n> It is primarily for people who have unmanaged contents and want to use\n> features of the git diff engine that are not found in other people's diff\n> implementations (e.g. wordwise colored diff),...\n\nIs it possible to give --no-index option to \"git grep\", please?\n\n-- \nNanako Shiraishi\nhttp://ivory.ap.teacup.com/nanako3/\n"},{"id":"131741","messageId":"7vska71br0.fsf@alter.siamese.dyndns.org","threadId":"22202","inReplyTo":"20100115223259.6117@nanako3.lavabit.com","subject":"Re: Filenames and prefixes in extended diffs","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-01-15T18:09:07Z","receivedAt":"2010-01-15T18:09:07Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nanako Shiraishi <nanako3@lavabit.com> writes:\n\n> Quoting Junio C Hamano <gitster@pobox.com>\n>\n>> The output from \"git diff --no-index\" is an exception to the above rule.\n>> It is primarily for people who have unmanaged contents and want to use\n>> features of the git diff engine that are not found in other people's diff\n>> implementations (e.g. wordwise colored diff),...\n>\n> Is it possible to give --no-index option to \"git grep\", please?\n\nSurely.  And \"grep\" is much easier to do than \"diff\".  Will send a patch\nperhaps during my lunch break.\n"},{"id":"131766","messageId":"7v4omnw0r5.fsf_-_@alter.siamese.dyndns.org","threadId":"22202","inReplyTo":"7vska71br0.fsf@alter.siamese.dyndns.org","subject":"[PATCH] grep: prepare to run outside of a work tree","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-01-15T20:50:54Z","receivedAt":"2010-01-15T20:50:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This moves the call to setup_git_directory() for running \"grep\" from\nthe \"git\" wrapper to the implementation of the \"grep\" subcommand.  A\nnew variable \"use_index\" is always true at this stage in the series,\nand when it is on, we require that we are in a directory that is under\ngit control.  To make sure we die the same way, we make a second call\ninto setup_git_directory() when we detect this situation.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n\n Junio C Hamano <gitster@pobox.com> writes:\n\n > Nanako Shiraishi <nanako3@lavabit.com> writes:\n >\n >> Is it possible to give --no-index option to \"git grep\", please?\n >\n > Surely.  And \"grep\" is much easier to do than \"diff\".  Will send a\n > patch perhaps during my lunch break.\n\n This is merely a preparatory step.\n\n builtin-grep.c |    7 +++++++\n git.c          |    2 +-\n 2 files changed, 8 insertions(+), 1 deletions(-)\n\ndiff --git a/builtin-grep.c b/builtin-grep.c\nindex 3d6ebb5..229555d 100644\n--- a/builtin-grep.c\n+++ b/builtin-grep.c\n@@ -414,6 +414,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \tconst char **paths = NULL;\n \tint i;\n \tint dummy;\n+\tint nongit = 0, use_index = 1;\n \tstruct option options[] = {\n \t\tOPT_BOOLEAN(0, \"cached\", &cached,\n \t\t\t\"search in index instead of in the work tree\"),\n@@ -497,6 +498,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \t\tOPT_END()\n \t};\n \n+\tprefix = setup_git_directory_gently(&nongit);\n+\n \t/*\n \t * 'git grep -h', unlike 'git grep -h <pattern>', is a request\n \t * to show usage information and exit.\n@@ -534,6 +537,10 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \t\t\t     PARSE_OPT_STOP_AT_NON_OPTION |\n \t\t\t     PARSE_OPT_NO_INTERNAL_HELP);\n \n+\tif (use_index && nongit)\n+\t\t/* die the same way as if we did it at the beginning */\n+\t\tsetup_git_directory();\n+\n \t/* First unrecognized non-option token */\n \tif (argc > 0 && !opt.pattern_list) {\n \t\tappend_grep_pattern(&opt, argv[0], \"command line\", 0,\ndiff --git a/git.c b/git.c\nindex 11544cd..ad07473 100644\n--- a/git.c\n+++ b/git.c\n@@ -317,7 +317,7 @@ static void handle_internal_command(int argc, const char **argv)\n \t\t{ \"fsck-objects\", cmd_fsck, RUN_SETUP },\n \t\t{ \"gc\", cmd_gc, RUN_SETUP },\n \t\t{ \"get-tar-commit-id\", cmd_get_tar_commit_id },\n-\t\t{ \"grep\", cmd_grep, RUN_SETUP | USE_PAGER },\n+\t\t{ \"grep\", cmd_grep, USE_PAGER },\n \t\t{ \"help\", cmd_help },\n \t\t{ \"init\", cmd_init_db },\n \t\t{ \"init-db\", cmd_init_db },\n-- \n1.6.6.324.g20f8f4.dirty\n"},{"id":"131767","messageId":"7vzl4fum3r.fsf_-_@alter.siamese.dyndns.org","threadId":"22202","inReplyTo":"7vska71br0.fsf@alter.siamese.dyndns.org","subject":"[PATCH] grep --no-index: allow use of \"git grep\" outside a git repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-01-15T20:52:40Z","receivedAt":"2010-01-15T20:52:40Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Just like some people wanted diff features that are not found in\nother people's diff implementations outside of a git repository\nand added --no-index mode to the command, this adds --no-index mode\nto the \"git grep\" command.\n\nAlso, inside a git repository, --no-index mode allows you to grep\nin untracked (but not ignored) files.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n\n * This is much easier than \"git diff --no-index\" because it does not have\n   to worry about corner cases like \"git diff --no-index file1 file2\".\n\n builtin-grep.c  |   26 ++++++++++++++++++++++++++\n t/t7002-grep.sh |   52 ++++++++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 78 insertions(+), 0 deletions(-)\n\ndiff --git a/builtin-grep.c b/builtin-grep.c\nindex 229555d..1283373 100644\n--- a/builtin-grep.c\n+++ b/builtin-grep.c\n@@ -14,6 +14,7 @@\n #include \"userdiff.h\"\n #include \"grep.h\"\n #include \"quote.h\"\n+#include \"dir.h\"\n \n static char const * const grep_usage[] = {\n \t\"git grep [options] [-e] <pattern> [<rev>...] [[--] path...]\",\n@@ -320,6 +321,21 @@ static int grep_object(struct grep_opt *opt, const char **paths,\n \tdie(\"unable to grep from object of type %s\", typename(obj->type));\n }\n \n+static int grep_directory(struct grep_opt *opt, const char **paths)\n+{\n+\tstruct dir_struct dir;\n+\tint i, hit = 0;\n+\n+\tmemset(&dir, 0, sizeof(dir));\n+\tsetup_standard_excludes(&dir);\n+\n+\tfill_directory(&dir, paths);\n+\tfor (i = 0; i < dir.nr; i++)\n+\t\thit |= grep_file(opt, dir.entries[i]->name);\n+\tfree_grep_patterns(opt);\n+\treturn hit;\n+}\n+\n static int context_callback(const struct option *opt, const char *arg,\n \t\t\t    int unset)\n {\n@@ -418,6 +434,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \tstruct option options[] = {\n \t\tOPT_BOOLEAN(0, \"cached\", &cached,\n \t\t\t\"search in index instead of in the work tree\"),\n+\t\tOPT_BOOLEAN(0, \"index\", &use_index,\n+\t\t\t\"--no-index finds in contents not managed by git\"),\n \t\tOPT_GROUP(\"\"),\n \t\tOPT_BOOLEAN('v', \"invert-match\", &opt.invert,\n \t\t\t\"show non-matching lines\"),\n@@ -591,6 +609,14 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \t\tpaths[1] = NULL;\n \t}\n \n+\tif (!use_index) {\n+\t\tif (cached)\n+\t\t\tdie(\"--cached cannot be used with --no-index.\");\n+\t\tif (list.nr)\n+\t\t\tdie(\"--no-index cannot be used with revs.\");\n+\t\treturn !grep_directory(&opt, paths);\n+\t}\n+\n \tif (!list.nr) {\n \t\tif (!cached)\n \t\t\tsetup_work_tree();\ndiff --git a/t/t7002-grep.sh b/t/t7002-grep.sh\nindex c369cdb..7eceb08 100755\n--- a/t/t7002-grep.sh\n+++ b/t/t7002-grep.sh\n@@ -426,4 +426,56 @@ test_expect_success 'grep -Fi' '\n \ttest_cmp expected actual\n '\n \n+test_expect_success 'outside of git repository' '\n+\trm -fr non &&\n+\tmkdir -p non/git/sub &&\n+\techo hello >non/git/file1 &&\n+\techo world >non/git/sub/file2 &&\n+\techo \".*o*\" >non/git/.gitignore &&\n+\t{\n+\t\techo file1:hello &&\n+\t\techo sub/file2:world\n+\t} >non/expect.full &&\n+\techo file2:world >non/expect.sub\n+\t(\n+\t\tGIT_CEILING_DIRECTORIES=\"$(pwd)/non/git\" &&\n+\t\texport GIT_CEILING_DIRECTORIES &&\n+\t\tcd non/git &&\n+\t\ttest_must_fail git grep o &&\n+\t\tgit grep --no-index o >../actual.full &&\n+\t\ttest_cmp ../expect.full ../actual.full\n+\t\tcd sub &&\n+\t\ttest_must_fail git grep o &&\n+\t\tgit grep --no-index o >../../actual.sub &&\n+\t\ttest_cmp ../../expect.sub ../../actual.sub\n+\t)\n+'\n+\n+test_expect_success 'inside git repository but with --no-index' '\n+\trm -fr is &&\n+\tmkdir -p is/git/sub &&\n+\techo hello >is/git/file1 &&\n+\techo world >is/git/sub/file2 &&\n+\techo \".*o*\" >is/git/.gitignore &&\n+\t{\n+\t\techo file1:hello &&\n+\t\techo sub/file2:world\n+\t} >is/expect.full &&\n+\t: >is/expect.empty &&\n+\techo file2:world >is/expect.sub\n+\t(\n+\t\tcd is/git &&\n+\t\tgit init &&\n+\t\ttest_must_fail git grep o >../actual.full &&\n+\t\ttest_cmp ../expect.empty ../actual.full &&\n+\t\tgit grep --no-index o >../actual.full &&\n+\t\ttest_cmp ../expect.full ../actual.full &&\n+\t\tcd sub &&\n+\t\ttest_must_fail git grep o >../../actual.sub &&\n+\t\ttest_cmp ../../expect.empty ../../actual.sub &&\n+\t\tgit grep --no-index o >../../actual.sub &&\n+\t\ttest_cmp ../../expect.sub ../../actual.sub\n+\t)\n+'\n+\n test_done\n-- \n1.6.6.324.g20f8f4\n"},{"id":"131769","messageId":"20100115210854.GA21540@coredump.intra.peff.net","threadId":"22202","inReplyTo":"7vzl4fum3r.fsf_-_@alter.siamese.dyndns.org","subject":"Re: [PATCH] grep --no-index: allow use of \"git grep\" outside a git repository","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2010-01-15T21:08:54Z","receivedAt":"2010-01-15T21:08:54Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Jan 15, 2010 at 12:52:40PM -0800, Junio C Hamano wrote:\n\n> Just like some people wanted diff features that are not found in\n> other people's diff implementations outside of a git repository\n> and added --no-index mode to the command, this adds --no-index mode\n> to the \"git grep\" command.\n\nOut of curiosity, what are the interesting features in git grep versus\nother greps?\n\n-Peff\n"},{"id":"131835","messageId":"7vwrzin9jt.fsf@alter.siamese.dyndns.org","threadId":"22202","inReplyTo":"20100115210854.GA21540@coredump.intra.peff.net","subject":"Re: [PATCH] grep --no-index: allow use of \"git grep\" outside a git repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-01-16T01:05:42Z","receivedAt":"2010-01-16T01:05:42Z","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> On Fri, Jan 15, 2010 at 12:52:40PM -0800, Junio C Hamano wrote:\n>\n>> Just like some people wanted diff features that are not found in\n>> other people's diff implementations outside of a git repository\n>> and added --no-index mode to the command, this adds --no-index mode\n>> to the \"git grep\" command.\n>\n> Out of curiosity, what are the interesting features in git grep versus\n> other greps?\n\nThree examples:\n\n    git grep -e Junio --and -e Dscho --and -e Peff\n\nis different from\n\n    grep \"Junio.*Dscho.*Peff\"\n\nin that the latter wouldn't find a line that has these names in different\norder.  You can of course give permutations explicitly, like\n\n    grep -e \"Junio.*Dscho.*Peff\" \\\n         -e \"Dscho.*Junio.*Peff\" \\\n         ...\n\t -e \"Peff.*Dscho.*Junio\"\n\nI don't know how you would do these with \"grep\":\n\n    git grep -e Junio --and -e Dscho --and --not -e Linus\n\n    git grep --all-match -e Junio -e Dscho\n"},{"id":"131839","messageId":"20100116011512.GA27082@coredump.intra.peff.net","threadId":"22202","inReplyTo":"7vwrzin9jt.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] grep --no-index: allow use of \"git grep\" outside a git repository","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2010-01-16T01:15:12Z","receivedAt":"2010-01-16T01:15:12Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Jan 15, 2010 at 05:05:42PM -0800, Junio C Hamano wrote:\n\n> > Out of curiosity, what are the interesting features in git grep versus\n> > other greps?\n> \n> Three examples:\n> \n>     git grep -e Junio --and -e Dscho --and -e Peff\n> \n> is different from\n> \n>     grep \"Junio.*Dscho.*Peff\"\n\nRight. I would do:\n\n  grep Junio | grep Dscho | grep Peff\n\nNo, it's not quite as accurate, as you are grepping the filenames too.\n\nAnd no, it's not as efficient, but given that the first grep eliminates\nmost of your input anyway, it's generally not a big deal.\n\nSo the short answer to my question seems to be \"git grep has logical\noperators\". I don't find that compelling, but I guess some people do.\nThanks for satisfying my curiosity.\n\n> I don't know how you would do these with \"grep\":\n> \n>     git grep -e Junio --and -e Dscho --and --not -e Linus\n\nI would do \"grep Junio | grep Dscho | grep -v Linus\".\n\n>     git grep --all-match -e Junio -e Dscho\n\nThat one is a little harder (though it is not something I do very often,\nand I had to actually read the docs to find what --all-match does):\n\n  grep Junio `grep -l Dscho *`\n\nwhich of course has problems with exotic filenames.\n\n-Peff\n"},{"id":"131848","messageId":"7vpr5ait1m.fsf@alter.siamese.dyndns.org","threadId":"22202","inReplyTo":"20100116011512.GA27082@coredump.intra.peff.net","subject":"Re: [PATCH] grep --no-index: allow use of \"git grep\" outside a git repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-01-16T04:15:49Z","receivedAt":"2010-01-16T04:15:49Z","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>>     git grep --all-match -e Junio -e Dscho\n>\n> That one is a little harder (though it is not something I do very often,\n> and I had to actually read the docs to find what --all-match does):\n>\n>   grep Junio `grep -l Dscho *`\n>\n> which of course has problems with exotic filenames.\n\nAlso it doesn't find lines that match Dscho in the result ;-)\n\nRealistically, this most often is used when grepping in the log, e.g.\n\n    git log --all-match --author=peff --grep=test\n\nI actually wish \"log\" to somehow default to --all-match mode at least when\nusing the --author option.  \"Change by Jeff, or about test by anybody\" is\nrarely what I would want to look for.\n"},{"id":"131854","messageId":"20100116065135.GA15104@gmail.com","threadId":"22202","inReplyTo":"7vpr5ait1m.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] grep --no-index: allow use of \"git grep\" outside a git repository","fromName":"David Aguilar","fromEmail":"davvid@gmail.com","sentAt":"2010-01-16T06:51:36Z","receivedAt":"2010-01-16T06:51:36Z","isPatch":true,"sender":{"key":"davvid@gmail.com","avatar":"https://avatars.githubusercontent.com/u/13196?v=4"},"body":"On Fri, Jan 15, 2010 at 08:15:49PM -0800, Junio C Hamano wrote:\n> Jeff King <peff@peff.net> writes:\n> \n> >>     git grep --all-match -e Junio -e Dscho\n> >\n> > That one is a little harder (though it is not something I do very often,\n> > and I had to actually read the docs to find what --all-match does):\n> >\n> >   grep Junio `grep -l Dscho *`\n> >\n> > which of course has problems with exotic filenames.\n> \n> Also it doesn't find lines that match Dscho in the result ;-)\n> \n> Realistically, this most often is used when grepping in the log, e.g.\n> \n>     git log --all-match --author=peff --grep=test\n> \n> I actually wish \"log\" to somehow default to --all-match mode at least when\n> using the --author option.  \"Change by Jeff, or about test by anybody\" is\n> rarely what I would want to look for.\n\nKinda like this?\n\nI originally had it set grep_filter.all_match in --author only,\nbut then I thought \"why author and not commiter too\", so changing\nthe default seemed like the natural thing to do.  Or it could be\na cat brained idea, I dunno ;)\n\n-- -- -- 8< -- -- -- 8< -- -- --\nFrom 2277a6e512c2f597c6240f06c9e7d5ff83e2fe3f Mon Sep 17 00:00:00 2001\nFrom: David Aguilar <davvid@gmail.com>\nDate: Fri, 15 Jan 2010 21:18:36 -0800\nSubject: [PATCH] Make --all-match the default in \"log\" family\n\n'git log --author=peff --grep=test' means \"search for commits by Jeff,\nor about test by anybody,\" which is rarely what what we want to do.\nThe original behavior can by achieved by specifying --no-all-match.\n\nReference: http://article.gmane.org/gmane.comp.version-control.git/137197\nSigned-off-by: David Aguilar <davvid@gmail.com>\n---\n Documentation/rev-list-options.txt |    1 +\n revision.c                         |    3 +++\n t/t7002-grep.sh                    |    2 +-\n 3 files changed, 5 insertions(+), 1 deletions(-)\n\ndiff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt\nindex 1f57aed..0ce1008 100644\n--- a/Documentation/rev-list-options.txt\n+++ b/Documentation/rev-list-options.txt\n@@ -179,6 +179,7 @@ endif::git-rev-list[]\n --all-match::\n \tLimit the commits output to ones that match all given --grep,\n \t--author and --committer instead of ones that match at least one.\n+\t--all-match is the defaullt and can be disabled with --no-all-match.\n \n -i::\n --regexp-ignore-case::\ndiff --git a/revision.c b/revision.c\nindex 25fa14d..64ebdc5 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -804,6 +804,7 @@ void init_revisions(struct rev_info *revs, const char *prefix)\n \n \trevs->commit_format = CMIT_FMT_DEFAULT;\n \n+\trevs->grep_filter.all_match = 1;\n \trevs->grep_filter.status_only = 1;\n \trevs->grep_filter.pattern_tail = &(revs->grep_filter.pattern_list);\n \trevs->grep_filter.regflags = REG_NEWLINE;\n@@ -1222,6 +1223,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\trevs->grep_filter.fixed = 1;\n \t} else if (!strcmp(arg, \"--all-match\")) {\n \t\trevs->grep_filter.all_match = 1;\n+\t} else if (!strcmp(arg, \"--no-all-match\")) {\n+\t\trevs->grep_filter.all_match = 0;\n \t} else if (!prefixcmp(arg, \"--encoding=\")) {\n \t\targ += 11;\n \t\tif (strcmp(arg, \"none\"))\ndiff --git a/t/t7002-grep.sh b/t/t7002-grep.sh\nindex 76c5e09..92ef534 100755\n--- a/t/t7002-grep.sh\n+++ b/t/t7002-grep.sh\n@@ -358,7 +358,7 @@ test_expect_success 'log grep (4)' '\n \n test_expect_success 'log grep (5)' '\n \tgit log --author=Thor -F --grep=Thu --pretty=tformat:%s >actual &&\n-\t( echo third ; echo initial ) >expect &&\n+\t: >expect &&\n \ttest_cmp expect actual\n '\n \n-- \n1.6.6.197.g2277\n"},{"id":"131855","messageId":"7v1vhqfrai.fsf@alter.siamese.dyndns.org","threadId":"22202","inReplyTo":"20100116065135.GA15104@gmail.com","subject":"Re: [PATCH] grep --no-index: allow use of \"git grep\" outside a git repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-01-16T07:21:57Z","receivedAt":"2010-01-16T07:21:57Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"David Aguilar <davvid@gmail.com> writes:\n\n> On Fri, Jan 15, 2010 at 08:15:49PM -0800, Junio C Hamano wrote:\n>\n>> Realistically, this most often is used when grepping in the log, e.g.\n>> \n>>     git log --all-match --author=peff --grep=test\n>> \n>> I actually wish \"log\" to somehow default to --all-match mode at least when\n>> using the --author option.  \"Change by Jeff, or about test by anybody\" is\n>> rarely what I would want to look for.\n>\n> Kinda like this?\n\nNot quite.  What I really want is\n\n    git log --author=davvid --grep=difftool --grep=mergetool\n\nto find all commits by you that is about (either diff or mergetool).  I\nthink your patch will limit the search only to your patch that talks about\nboth of these two tools (not necessarily on the same line, but in the same\ncommit).\n\nThe extended \"grep\" expression parser by default creates a list of OR'ed\nterms.  What --all-match does is to make this top-level chain to mean \"all\nof these must trigger somewhere in the whole _document_ (not an individual\nline), for the document to be considered a hit\" for the purpose of \"grep -l\",\nand when used with \"log\" family, --author/--committer/--grep are used to\nlimit the output to commits \"grep -l\" would say \"yes, this document has\nmatched\".\n\nCurrently,\n\n    git log --author=davvid --grep=difftool --grep=mergetool\n\nwill parse to a list of three terms:\n\n    GREP_PATTERN_HEAD(\"^author .*davvid\")\n    GREP_PATTERN_BODY(\"difftool\")\n    GREP_PATTERN_BODY(\"mergetool\")\n\nAnd giving --all-match will require all of these OR'ed terms to appear in\nthe commit object.\n\nMy dream one will probably has to make a list of two terms as its parse\ntree instead, like this:\n\n    GREP_PATTERN_HEAD(\"^author .*davvid\")\n    GREP_NODE_OR(\n        GREP_PATTERN_BODY(\"difftool\")\n        GREP_PATTERN_BODY(\"mergetool\")\n    )           \n\nand then run it with --all-match semantics.  The top-level consists of two\nterms, and they both must hit, but the second term is an OR'ed one.\n\nIt is unclear how we would want to throw the committer in the mix.  If we\nmake this parse tree:\n\n    GREP_PATTERN_HEAD(\"^author .*davvid\")\n    GREP_PATTERN_HEAD(\"^committer .*gitster\")\n    GREP_NODE_OR(\n        GREP_PATTERN_BODY(\"difftool\")\n        GREP_PATTERN_BODY(\"mergetool\")\n    )           \n\nwe would be looking for your patch about either diff or mergetool _and_\nit has to be committed by me.  On the other hand, if we do this:\n\n    GREP_NODE_OR(\n        GREP_PATTERN_HEAD(\"^author .*davvid\")\n        GREP_PATTERN_HEAD(\"^committer .*gitster\")\n    )\n    GREP_NODE_OR(\n        GREP_PATTERN_BODY(\"difftool\")\n        GREP_PATTERN_BODY(\"mergetool\")\n    )           \n\nwe would be looking for a patch about (either diff or mergetool) _and_\n(either committed by me or written by you).\n\nI think the former makes more sense in _our_ project (because there are\nvery few committers), but in the context of other projects, e.g. the Linux\nkernel, you may want to give \"Linus\" to both --author and --committer to\ntrack what he did (either as an author to some other subsystem, or as the\ntop-level integrator for the entire system), and for such a use case, the\nlatter would make more sense.\n\nUnfortunately, the parsing of --grep/--author/--committer options to the\nlog family is quite limited (you cannot give --and, --or and --not, for\nexample), and it would be hard to express these distinction.\n"},{"id":"132002","messageId":"20100118015140.GB6831@coredump.intra.peff.net","threadId":"22202","inReplyTo":"7vpr5ait1m.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] grep --no-index: allow use of \"git grep\" outside a git repository","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2010-01-18T01:51:40Z","receivedAt":"2010-01-18T01:51:40Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Jan 15, 2010 at 08:15:49PM -0800, Junio C Hamano wrote:\n\n> Realistically, this most often is used when grepping in the log, e.g.\n> \n>     git log --all-match --author=peff --grep=test\n> \n> I actually wish \"log\" to somehow default to --all-match mode at least when\n> using the --author option.  \"Change by Jeff, or about test by anybody\" is\n> rarely what I would want to look for.\n\nAgreed. That is the most common log grep pattern for me (author + grep),\nand I always want all-match. I see from later in the thread, though,\nthat implementing it is not as straightforward as we might hope.\n\nI would personally be fine with \"--all-match\" being the default, but\nthat may be too big a change in behavior for some people to swallow (I\nwould also be fine with log.allmatch in the config, but every time I\nsuggest something like that people's heads explode and I get told to\nmake an alias).\n\n-Peff\n"},{"id":"132011","messageId":"7v8wbwultw.fsf@alter.siamese.dyndns.org","threadId":"22202","inReplyTo":"20100118015140.GB6831@coredump.intra.peff.net","subject":"Re: [PATCH] grep --no-index: allow use of \"git grep\" outside a git repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-01-18T03:35:23Z","receivedAt":"2010-01-18T03:35:23Z","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> Agreed. That is the most common log grep pattern for me (author + grep),\n> and I always want all-match. I see from later in the thread, though,\n> that implementing it is not as straightforward as we might hope.\n\nI haven't looked at the codepath for quite some time but I have a feeling\nthat it probably won't be too bad.\n\nIt just won't be as simple as flipping the all_match bit with a one-liner.\n\nBefore calling compile_grep_patterns() in revision.c::setup_revisions(),\nwe probably would want to massage revs->grep_filter to result in the\ndesired grep expression parse tree, i.e. from\n\n    GREP_PATTERN_HEAD(\"^author .*davvid\")\n    GREP_PATTERN_HEAD(\"^committer .*gitster\")\n    GREP_PATTERN_BODY(\"difftool\")\n    GREP_PATTERN_BODY(\"mergetool\")\n\nto\n\n    GREP_PATTERN_HEAD(\"^author .*davvid\")\n    GREP_PATTERN_HEAD(\"^committer .*gitster\")\n    GREP_NODE_OR(\n        GREP_PATTERN_BODY(\"difftool\")\n        GREP_PATTERN_BODY(\"mergetool\")\n    )           \n"},{"id":"132013","messageId":"7v3a24ukku.fsf@alter.siamese.dyndns.org","threadId":"22202","inReplyTo":"7v8wbwultw.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] grep --no-index: allow use of \"git grep\" outside a git repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-01-18T04:02:25Z","receivedAt":"2010-01-18T04:02:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Jeff King <peff@peff.net> writes:\n>\n>> Agreed. That is the most common log grep pattern for me (author + grep),\n>> and I always want all-match. I see from later in the thread, though,\n>> that implementing it is not as straightforward as we might hope.\n>\n> I haven't looked at the codepath for quite some time but I have a feeling\n> that it probably won't be too bad.\n>\n> It just won't be as simple as flipping the all_match bit with a one-liner.\n\nPerhaps something like this.\n\n-- >8 --\nSubject: \"log --author=me --grep=it\" should find intersection, not union\n\nHistorically, any grep filter in \"git log\" family of commands were taken\nas restricting to commits with any of the words in the commit log message.\nHowever, the user almost always want to find commits \"done by this person\non that topic\".  With \"--all-match\" option, a series of grep patterns can\nbe turned into a requirement that all of them must produce a match, but\nthat makes it impossible to ask for \"done by me, on either this or that\"\nwith:\n\n\tlog --author=me --grep=this --grep=that\n\nbecause it will require both \"this\" and \"that\" to appear.\n\nChange the \"header\" parser of grep library to treat the headers specially.\nWhen parsing the above, behave as if it was specified like this on the\ncommand line:\n\n\t--all-match --author=me '(' --grep=this --grep=that ')'\n\nEven though the \"log\" command line parser doesn't give direct access to\nthe extended grep syntax to group terms with parentheses, this change will\ncover the majority of the case the users would want.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin-grep.c |    1 +\n grep.c         |   20 ++++++++++++++++++--\n grep.h         |    2 ++\n revision.c     |    1 +\n 4 files changed, 22 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin-grep.c b/builtin-grep.c\nindex 529461f..d57c4d9 100644\n--- a/builtin-grep.c\n+++ b/builtin-grep.c\n@@ -820,6 +820,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \topt.relative = 1;\n \topt.pathname = 1;\n \topt.pattern_tail = &opt.pattern_list;\n+\topt.header_tail = &opt.header_list;\n \topt.regflags = REG_NEWLINE;\n \topt.max_depth = -1;\n \ndiff --git a/grep.c b/grep.c\nindex bdadf2c..f51fa4a 100644\n--- a/grep.c\n+++ b/grep.c\n@@ -11,8 +11,8 @@ void append_header_grep_pattern(struct grep_opt *opt, enum grep_header_field fie\n \tp->no = 0;\n \tp->token = GREP_PATTERN_HEAD;\n \tp->field = field;\n-\t*opt->pattern_tail = p;\n-\topt->pattern_tail = &p->next;\n+\t*opt->header_tail = p;\n+\topt->header_tail = &p->next;\n \tp->next = NULL;\n }\n \n@@ -173,6 +173,22 @@ void compile_grep_patterns(struct grep_opt *opt)\n {\n \tstruct grep_pat *p;\n \n+\tif (opt->header_list && !opt->all_match) {\n+\t\tstruct grep_pat *p = opt->pattern_list;\n+\t\topt->pattern_list = opt->header_list;\n+\t\topt->pattern_tail = opt->header_tail;\n+\t\topt->header_list = NULL;\n+\t\topt->header_tail = NULL;\n+\n+\t\tappend_grep_pattern(opt, \"(\", \"internal\", 0, GREP_OPEN_PAREN);\n+\t\twhile (p) {\n+\t\t\t*opt->pattern_tail = p;\n+\t\t\topt->pattern_tail = &p->next;\n+\t\t\tp = p->next;\n+\t\t}\n+\t\tappend_grep_pattern(opt, \")\", \"internal\", 0, GREP_CLOSE_PAREN);\n+\t\topt->all_match = 1;\n+\t}\n \tif (opt->all_match)\n \t\topt->extended = 1;\n \ndiff --git a/grep.h b/grep.h\nindex 75370f6..e39e514 100644\n--- a/grep.h\n+++ b/grep.h\n@@ -59,6 +59,8 @@ struct grep_expr {\n struct grep_opt {\n \tstruct grep_pat *pattern_list;\n \tstruct grep_pat **pattern_tail;\n+\tstruct grep_pat *header_list;\n+\tstruct grep_pat **header_tail;\n \tstruct grep_expr *pattern_expression;\n \tconst char *prefix;\n \tint prefix_length;\ndiff --git a/revision.c b/revision.c\nindex 25fa14d..18a3658 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -806,6 +806,7 @@ void init_revisions(struct rev_info *revs, const char *prefix)\n \n \trevs->grep_filter.status_only = 1;\n \trevs->grep_filter.pattern_tail = &(revs->grep_filter.pattern_list);\n+\trevs->grep_filter.header_tail = &(revs->grep_filter.header_list);\n \trevs->grep_filter.regflags = REG_NEWLINE;\n \n \tdiff_setup(&revs->diffopt);\n"},{"id":"132015","messageId":"20100118055703.GA17879@coredump.intra.peff.net","threadId":"22202","inReplyTo":"7v3a24ukku.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] grep --no-index: allow use of \"git grep\" outside a git repository","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2010-01-18T05:57:03Z","receivedAt":"2010-01-18T05:57:03Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Jan 17, 2010 at 08:02:25PM -0800, Junio C Hamano wrote:\n\n> Subject: \"log --author=me --grep=it\" should find intersection, not union\n> \n> Historically, any grep filter in \"git log\" family of commands were taken\n> as restricting to commits with any of the words in the commit log message.\n> However, the user almost always want to find commits \"done by this person\n> on that topic\".  With \"--all-match\" option, a series of grep patterns can\n> be turned into a requirement that all of them must produce a match, but\n> that makes it impossible to ask for \"done by me, on either this or that\"\n> with:\n> \n> \tlog --author=me --grep=this --grep=that\n> \n> because it will require both \"this\" and \"that\" to appear.\n> \n> Change the \"header\" parser of grep library to treat the headers specially.\n> When parsing the above, behave as if it was specified like this on the\n> command line:\n> \n> \t--all-match --author=me '(' --grep=this --grep=that ')'\n> \n> Even though the \"log\" command line parser doesn't give direct access to\n> the extended grep syntax to group terms with parentheses, this change will\n> cover the majority of the case the users would want.\n\nHmm. I like the new behavior. The implementation feels a little\nhack-ish, like we should really be supporting full-on:\n\n  git log --author=me --and --grep=foo\n\nThat gets a little weird, though. We already have \"--not\" for ref\nlimiting, so clearly there is some conflict over exactly what logical\noperators would be operating on. I guess we could use context to see\nthat the adjacent arguments were grep-related.\n\nSo perhaps, as you say, this is enough as it covers the usual case.\n\n-Peff\n"},{"id":"132017","messageId":"7vk4vgsz5w.fsf@alter.siamese.dyndns.org","threadId":"22202","inReplyTo":"20100118055703.GA17879@coredump.intra.peff.net","subject":"Re: [PATCH] grep --no-index: allow use of \"git grep\" outside a git repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-01-18T06:30:19Z","receivedAt":"2010-01-18T06:30:19Z","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> Hmm. I like the new behavior. The implementation feels a little\n> hack-ish, like we should really be supporting full-on:\n>\n>   git log --author=me --and --grep=foo\n>\n> That gets a little weird, though. We already have \"--not\" for ref\n> limiting, so clearly there is some conflict ...\n\nThat is fundamentally wrong.\n\nRemember, \"grep\" works on two levels: a line matches or does not match the\ngiven set of patterns (rather, the expression given), and matched lines\nare shown.  A file as a whole is considered to have matched if one or more\nlines produced a match, or under the --all-match option, only when all of\nthe top-level ORed terms in the expression have fired for some lines in\nit.\n\nAnd --not and --and are both elements of grep expression that determines\nif the expression matches \"a single line\".  --author=me --and --grep=foo\nwould ask: does the \"^author \" line in the header have \"me\" _and_ also\nstring \"foo\" on it at the same time?\n\nIOW, most of the \"logical\" stuff (including the precedence binding\nparentheses) works at a line level.  --all-match is currently the only\nthing that affects \"grep -l\" (and \"will the commit get shown\") behaviour\nby collecting hits from the whole buffer.\n"},{"id":"132018","messageId":"20100118065018.GA18074@coredump.intra.peff.net","threadId":"22202","inReplyTo":"7vk4vgsz5w.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] grep --no-index: allow use of \"git grep\" outside a git repository","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2010-01-18T06:50:18Z","receivedAt":"2010-01-18T06:50:18Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Jan 17, 2010 at 10:30:19PM -0800, Junio C Hamano wrote:\n\n> Jeff King <peff@peff.net> writes:\n> \n> > Hmm. I like the new behavior. The implementation feels a little\n> > hack-ish, like we should really be supporting full-on:\n> >\n> >   git log --author=me --and --grep=foo\n> >\n> > That gets a little weird, though. We already have \"--not\" for ref\n> > limiting, so clearly there is some conflict ...\n> \n> That is fundamentally wrong.\n> \n> Remember, \"grep\" works on two levels: a line matches or does not match the\n> given set of patterns (rather, the expression given), and matched lines\n> are shown.  A file as a whole is considered to have matched if one or more\n> lines produced a match, or under the --all-match option, only when all of\n> the top-level ORed terms in the expression have fired for some lines in\n> it.\n\nFundamentally wrong for the way \"log --grep\" is currently implemented\nperhaps, but I don't see anything wrong with considering each commit as\na single \"record\", just as regular grep considers each line to be a\nrecord. That is a much more useful distinction for log traversal than\nlines, which are useless from the user's perspective. If searching for\ntwo terms, I care about whether they are in the same commit message, but\nI don't care at all about line breaks.\n\nYes, I know that internally --author is really about line-matching the\ncommit headers, but that is an implementation detail. The mental model\nwe should present to the user is record-matching based on specific\nfields like author, committer, or body text.\n\n-Peff\n"},{"id":"132057","messageId":"201001190022.07580.agruen@suse.de","threadId":"22202","inReplyTo":"7vfx69k0bu.fsf@alter.siamese.dyndns.org","subject":"Re: Filenames and prefixes in extended diffs","fromName":"Andreas Gruenbacher","fromEmail":"agruen@suse.de","sentAt":"2010-01-18T23:22:07Z","receivedAt":"2010-01-18T23:22:07Z","isPatch":false,"sender":{"key":"agruen@suse.de","avatar":null},"body":"On Thursday 14 January 2010 01:16:21 am Junio C Hamano wrote:\n> Andreas Gruenbacher <agruen@suse.de> writes:\n> > Can git be changed to ...\n> \n> Just to save your time coming up with more ways to *change* git diff...\n> \n> Even though I wouldn't say _any_ change is too late to bring in, change in\n> the output format from \"git diff\" family _must_ be usable by \"git apply\"\n> people have been using for the last 4 years or so.\n> \n> Suppose your updated version of \"git diff\" with a certain set of options\n> produces output A, which is different from the output B you would get out\n> of today's \"git diff\" that is run with the same set of options.\n> \n> If \"git apply\" people have been using understands B (i.e. current output)\n> and does something, the format change between A and B must be designed in\n> such a way that the same \"git apply\" accepts A (i.e. your output) and do\n> the same thing.\n> \n> Two examples:\n> \n>  - \"git diff -M\" (or \"git show -M\") is _defined_ to show the filenames\n>    without prefix on \"rename from\" line, and deployed \"git apply\" relies\n>    on this definition to apply the patch to the file the patch was meant\n>    to apply.  If your modified \"git diff -M\" changes it to add the prefix,\n>    and existing \"git apply\" changes behaviour (either by rejecting your\n>    output, or applying the patch to a wrong file), then such a change has\n>    *no chance* of getting in.  It is merely a breakage.\n\nGit apply is currently broken in some (uncommon) cases.  Consider the \nfollowing two patches:\n\n\t$ cat add.diff\n\tdiff --git a/d/f b/d/f\n\tnew file mode 100644\n\tindex 0000000..6a69f92\n\t--- /dev/null\n\t+++ b/d/f\n\t@@ -0,0 +1 @@\n\t+f\n\n\t$ cat rename.diff\n\tdiff --git a/d/f b/d/g\n\tsimilarity index 100%\n\trename from d/f\n\trename to d/g\n\nThey apply fine after each other with plain \"git apply\".  When you try to \napply them to a different location, things break though:\n\n\t$ git apply --directory e -p2 add.diff\n\t$ git apply --directory e -p2 rename.diff\n\terror: e/d/f: No such file or directory\n\nHad the second patch not been generated with \"git diff -M\", things would just \nhave worked; in other words, the -M format is broken.\n\nI think the easiest way to fix this in \"git apply\" would be to figure out what \nthe missing prefixes are in the rename and copy lines (in this case, just \"a/\" \nand \"b/\"), and to prepend those prefixes to the decoded filenames before \nstripping off pathname components.  This is the same as just taking the \nfilenames from the \"diff --git\" line, and ignoring the filenames in the \"copy \nfrom\", \"copy to\", \"rename from\", and \"rename to\" headers.\n\nI don't see a way how to fix this in the existing headers in a backwards \ncompatible way.  Do you?\n\nIndependent of whether and how this is addressed, can I please at least have \nthe \"diff --git\" line parsing problem fixed so that filenames which contain \nspaces are put in double quotes there?  Then I can at least ignore all the \nprefix-less filenames in GNU patch and still make it understand git's output.\n\n>  - If you say \"git diff --src-prefix=a/b/c --dst-prefix=x/y\", it _might_\n>    produce something \"git apply\" won't grok (I haven't checked this,\n>    though).  You can suggest to change the output from such a case to work\n>    better.  We didn't work as expected so a change _could_ be a fix.\n\nThe output format for that is fine.\n\n> The output from \"git diff --no-index\" is an exception to the above rule.\n> It is primarily for people who have unmanaged contents and want to use\n> features of the git diff engine that are not found in other people's diff\n> implementations (e.g. wordwise colored diff), and the header part of its\n> output does not currently follow \"git diff\" convention to be grokkable by\n> \"git apply\".\n> \n> Fixing _that_ is a welcome change, but I suspect that there are corner\n> cases, e.g. \"git diff --no-index frotz-1.2.36/ /tmp/frotz/\" (i.e. you have\n> a pristine version in frotz-1.2.36 directory, but your modified version is\n> in /tmp/frtoz/) that might make fixing it fundamentally impossible (I\n> haven't looked into it for a long time, so it could be easy, but my gut\n> feeling is it isn't).\n\nPatches with a different number of components in the from and to prefixes are \na really bad idea.  (GNU patch will prefer the pathname with the fewer \ncomponents, but this yould just as well be the wrong one.)\n\nThanks,\nAndreas\n"}]}