{"thread":{"id":"20675","subject":"[PATCH] Make 'diff C^!' show the same diff as 'show C'","startedAt":"2009-08-20T22:10:07Z","lastAt":"2009-08-20T23:35:36Z","messageCount":8,"participants":["Thomas Rast","Junio C Hamano","Jeff King"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"121357","messageId":"86d1201d8adf53c1f48c0f3526d8e81475b18244.1250806019.git.trast@student.ethz.ch","threadId":"20675","inReplyTo":null,"subject":"[PATCH] Make 'diff C^!' show the same diff as 'show C'","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2009-08-20T22:10:07Z","receivedAt":"2009-08-20T22:10:07Z","isPatch":true,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Ideally, we'd like 'git diff C^!' to show the same diff that 'git show C'\ndoes (with log.showroot enabled).  This gives easy access to a readable\ndiff for the commit, irrespective of how many parents it has and without\nany trickery to remove the commit message from the git-show output.\n\ncmd_diff relied on telling the various diff invocations apart from\nonly the number of revisions parsed by setup_revision() (with a twist\nfor A...B).  In the case of C^! this failed on two counts:\n\n* If C has no parents, setup_revision() turns C^! into simply C.  This\n  meant that 'git diff C^!' compared the current worktree to C, which\n  is certainly not what the user asked for.\n\n* Otherwise setup_revision puts C itself last, i.e., the rev.pending\n  are ^C^1 ... ^C^N C.  So the first revision is uninteresting and in\n  the case of exactly two parents, the symmetric difference revspec\n  (diff A...B) case fired, and compared C only to C^1 (instead of\n  showing a combined diff).\n\nDetect the presence of A...B or C^! style arguments before running\nsetup_revisions(), so that we know in which case we are in.  We can\nthen dispatch to the right case without peeking at UNINTERESTING\nflags.\n\nThere's still some complication in builtin_diff_combined() because\n0fe7c1d (built-in diff: assorted updates., 2006-04-29) advertises that\n'git diff T0 T1 ... Tn' does a combined diff of arbitrary trees where T0\nis the merge result, so we have to handle both this case and C^!.\n\nNote that UNINTERESTING is not a good criterion at all, as it is\ntacked onto *trees*; if any of the involved revisions share the same\ntrees, the flags will overwrite each other.\n\nThanks to Abhijit \"crab\" Menon-Sen for noticing that 'diff C^!' didn't\nwork as expected on root commits, and Björn \"doener\" Steinbrink for\nhelpful discussions.\n---\n\nError checking is still iffy, but I'm not sure that can be fixed\nwithout throwing out the whole \"argument parsing through\nsetup_revisions\" code and handrolling it.\n\n\n Documentation/git-diff.txt  |   10 +++++++-\n builtin-diff.c              |   54 +++++++++++++++++++++++++++++++++++-------\n t/t4013-diff-various.sh     |    3 ++\n t/t4013/diff.diff_initial^! |   28 ++++++++++++++++++++++\n t/t4013/diff.diff_master^!  |   29 +++++++++++++++++++++++\n t/t4013/diff.diff_side^!    |   32 +++++++++++++++++++++++++\n 6 files changed, 146 insertions(+), 10 deletions(-)\n create mode 100644 t/t4013/diff.diff_initial^!\n create mode 100644 t/t4013/diff.diff_master^!\n create mode 100644 t/t4013/diff.diff_side^!\n\ndiff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt\nindex 0ac7112..5d0f2a6 100644\n--- a/Documentation/git-diff.txt\n+++ b/Documentation/git-diff.txt\n@@ -62,9 +62,17 @@ forced by --no-index.\n \t\"git diff $(git-merge-base A B) B\".  You can omit any one\n \tof <commit>, which has the same effect as using HEAD instead.\n \n+'git diff' [--options] <commit>^{caret}! [--] [<path>...]::\n+\n+\tThis shows the changes that <commit> made relative to its\n+\tparents.  For an ordinary commit it is the same as `git diff\n+\t<commit>{caret} <commit>`.  For a root commit it shows a\n+\tcreation patch and for a merge commit it shows a combined\n+\tdiff.\n+\n Just in case if you are doing something exotic, it should be\n noted that all of the <commit> in the above description, except\n-for the last two forms that use \"..\" notations, can be any\n+for the two forms that use \"..\" notations, can be any\n <tree-ish>.\n \n For a more complete list of ways to spell <commit>, see\ndiff --git a/builtin-diff.c b/builtin-diff.c\nindex ffcdd05..285bf29 100644\n--- a/builtin-diff.c\n+++ b/builtin-diff.c\n@@ -163,10 +163,17 @@ static int builtin_diff_tree(struct rev_info *revs,\n \treturn 0;\n }\n \n+enum diff_mode {\n+\tDIFF_MODE_NORMAL,\n+\tDIFF_MODE_SYMMETRIC,\n+\tDIFF_MODE_SHOW\n+};\n+\n static int builtin_diff_combined(struct rev_info *revs,\n \t\t\t\t int argc, const char **argv,\n \t\t\t\t struct object_array_entry *ent,\n-\t\t\t\t int ents)\n+\t\t\t\t int ents,\n+\t\t\t\t enum diff_mode mode)\n {\n \tconst unsigned char (*parent)[20];\n \tint i;\n@@ -177,8 +184,18 @@ static int builtin_diff_combined(struct rev_info *revs,\n \tif (!revs->dense_combined_merges && !revs->combine_merges)\n \t\trevs->dense_combined_merges = revs->combine_merges = 1;\n \tparent = xmalloc(ents * sizeof(*parent));\n-\tfor (i = 0; i < ents; i++)\n-\t\thashcpy((unsigned char *)(parent + i), ent[i].item->sha1);\n+\n+\tif (mode == DIFF_MODE_SHOW) {\n+\t\t/* diff C^!, we exploit knowledge that C is last */\n+\t\tfor (i = 1; i < ents; i++)\n+\t\t\thashcpy((unsigned char *)(parent + i),\n+\t\t\t\tent[i-1].item->sha1);\n+\t\thashcpy((unsigned char *)(parent),\n+\t\t\tent[ents-1].item->sha1);\n+\t} else {\n+\t\tfor (i = 0; i < ents; i++)\n+\t\t\thashcpy((unsigned char *)(parent + i), ent[i].item->sha1);\n+\t}\n \tdiff_tree_combined(parent[0], parent + 1, ents - 1,\n \t\t\t   revs->dense_combined_merges, revs);\n \treturn 0;\n@@ -254,6 +271,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)\n \tstruct blobinfo blob[2];\n \tint nongit;\n \tint result = 0;\n+\tenum diff_mode mode = DIFF_MODE_NORMAL;\n \n \t/*\n \t * We could get N tree-ish in the rev.pending_objects list.\n@@ -292,6 +310,17 @@ int cmd_diff(int argc, const char **argv, const char *prefix)\n \t/* Otherwise, we are doing the usual \"git\" diff */\n \trev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;\n \n+\tfor (i = 1; i < argc; i++) {\n+\t\tif (prefixcmp(argv[i], \"--\")) {\n+\t\t\tif (strstr(argv[i], \"...\"))\n+\t\t\t\tmode = DIFF_MODE_SYMMETRIC;\n+\t\t\telse if (strstr(argv[i], \"^!\"))\n+\t\t\t\tmode = DIFF_MODE_SHOW;\n+\t\t} else if (!strcmp(argv[i], \"--\")) {\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n \t/* Default to let external and textconv be used */\n \tDIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL);\n \tDIFF_OPT_SET(&rev.diffopt, ALLOW_TEXTCONV);\n@@ -403,11 +432,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)\n \t}\n \telse if (blobs)\n \t\tusage(builtin_diff_usage);\n-\telse if (ents == 1)\n-\t\tresult = builtin_diff_index(&rev, argc, argv);\n-\telse if (ents == 2)\n-\t\tresult = builtin_diff_tree(&rev, argc, argv, ent);\n-\telse if ((ents == 3) && (ent[0].item->flags & UNINTERESTING)) {\n+\telse if (mode == DIFF_MODE_SYMMETRIC) {\n \t\t/* diff A...B where there is one sane merge base between\n \t\t * A and B.  We have ent[0] == merge-base, ent[1] == A,\n \t\t * and ent[2] == B.  Show diff between the base and B.\n@@ -415,9 +440,20 @@ int cmd_diff(int argc, const char **argv, const char *prefix)\n \t\tent[1] = ent[2];\n \t\tresult = builtin_diff_tree(&rev, argc, argv, ent);\n \t}\n+\telse if (ents == 1 && mode == DIFF_MODE_SHOW) {\n+\t\t/* diff R^! where R is a root commit: creation patch */\n+\t\tdiff_tree_sha1((const unsigned char *) EMPTY_TREE_SHA1_BIN,\n+\t\t\t       ent[0].item->sha1, \"\", &rev.diffopt);\n+\t\tlog_tree_diff_flush(&rev);\n+\t\tresult = 0;\n+\t}\n+\telse if (ents == 1)\n+\t\tresult = builtin_diff_index(&rev, argc, argv);\n+\telse if (ents == 2)\n+\t\tresult = builtin_diff_tree(&rev, argc, argv, ent);\n \telse\n \t\tresult = builtin_diff_combined(&rev, argc, argv,\n-\t\t\t\t\t     ent, ents);\n+\t\t\t\t\t       ent, ents, mode);\n \tresult = diff_result_code(&rev.diffopt, result);\n \tif (1 < rev.diffopt.skip_stat_unmatch)\n \t\trefresh_index_quietly();\ndiff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh\nindex 8b33321..2ce7204 100755\n--- a/t/t4013-diff-various.sh\n+++ b/t/t4013-diff-various.sh\n@@ -273,6 +273,9 @@ diff --no-index --name-status -- dir2 dir\n diff --no-index dir dir3\n diff master master^ side\n diff --dirstat master~1 master~2\n+diff initial^!\n+diff side^!\n+diff master^!\n EOF\n \n test_done\ndiff --git a/t/t4013/diff.diff_initial^! b/t/t4013/diff.diff_initial^!\nnew file mode 100644\nindex 0000000..22f6bb7\n--- /dev/null\n+++ b/t/t4013/diff.diff_initial^!\n@@ -0,0 +1,28 @@\n+$ git diff initial^!\n+diff --git a/dir/sub b/dir/sub\n+new file mode 100644\n+index 0000000..35d242b\n+--- /dev/null\n++++ b/dir/sub\n+@@ -0,0 +1,2 @@\n++A\n++B\n+diff --git a/file0 b/file0\n+new file mode 100644\n+index 0000000..01e79c3\n+--- /dev/null\n++++ b/file0\n+@@ -0,0 +1,3 @@\n++1\n++2\n++3\n+diff --git a/file2 b/file2\n+new file mode 100644\n+index 0000000..01e79c3\n+--- /dev/null\n++++ b/file2\n+@@ -0,0 +1,3 @@\n++1\n++2\n++3\n+$\ndiff --git a/t/t4013/diff.diff_master^! b/t/t4013/diff.diff_master^!\nnew file mode 100644\nindex 0000000..ca2eaa1\n--- /dev/null\n+++ b/t/t4013/diff.diff_master^!\n@@ -0,0 +1,29 @@\n+$ git diff master^!\n+diff --cc dir/sub\n+index cead32e,7289e35..992913c\n+--- a/dir/sub\n++++ b/dir/sub\n+@@@ -1,6 -1,4 +1,8 @@@\n+  A\n+  B\n+ +C\n+ +D\n+ +E\n+ +F\n++ 1\n++ 2\n+diff --cc file0\n+index b414108,f4615da..10a8a9f\n+--- a/file0\n++++ b/file0\n+@@@ -1,6 -1,6 +1,9 @@@\n+  1\n+  2\n+  3\n+ +4\n+ +5\n+ +6\n++ A\n++ B\n++ C\n+$\ndiff --git a/t/t4013/diff.diff_side^! b/t/t4013/diff.diff_side^!\nnew file mode 100644\nindex 0000000..6d4378a\n--- /dev/null\n+++ b/t/t4013/diff.diff_side^!\n@@ -0,0 +1,32 @@\n+$ git diff side^!\n+diff --git a/dir/sub b/dir/sub\n+index 35d242b..7289e35 100644\n+--- a/dir/sub\n++++ b/dir/sub\n+@@ -1,2 +1,4 @@\n+ A\n+ B\n++1\n++2\n+diff --git a/file0 b/file0\n+index 01e79c3..f4615da 100644\n+--- a/file0\n++++ b/file0\n+@@ -1,3 +1,6 @@\n+ 1\n+ 2\n+ 3\n++A\n++B\n++C\n+diff --git a/file3 b/file3\n+new file mode 100644\n+index 0000000..7289e35\n+--- /dev/null\n++++ b/file3\n+@@ -0,0 +1,4 @@\n++A\n++B\n++1\n++2\n+$\n-- \n1.6.4.363.g2183a\n"},{"id":"121358","messageId":"7vab1up1gz.fsf@alter.siamese.dyndns.org","threadId":"20675","inReplyTo":"86d1201d8adf53c1f48c0f3526d8e81475b18244.1250806019.git.trast@student.ethz.ch","subject":"Re: [PATCH] Make 'diff C^!' show the same diff as 'show C'","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-08-20T22:25:16Z","receivedAt":"2009-08-20T22:25:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thomas Rast <trast@student.ethz.ch> writes:\n\n> Ideally, we'd like 'git diff C^!' to show the same diff that 'git show C'\n> does (with log.showroot enabled).  This gives easy access to a readable\n> diff for the commit, irrespective of how many parents it has and without\n> any trickery to remove the commit message from the git-show output.\n\nNot interested yet, as the \"git show\" discussion is not convincing at all.\n\nIs the message annoying enough to warrant this change?\n\nIf that is indeed the case and if it is a common thing to ask, isn't it\nmore productive to teach \"show\" a way to do so in a simpler way than\ndoing, say,\n\n\t$ git show --pretty=format: HEAD\n"},{"id":"121359","messageId":"20090820223424.GA5843@coredump.intra.peff.net","threadId":"20675","inReplyTo":"7vab1up1gz.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] Make 'diff C^!' show the same diff as 'show C'","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-08-20T22:34:24Z","receivedAt":"2009-08-20T22:34:24Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Aug 20, 2009 at 03:25:16PM -0700, Junio C Hamano wrote:\n\n> Thomas Rast <trast@student.ethz.ch> writes:\n> \n> > Ideally, we'd like 'git diff C^!' to show the same diff that 'git show C'\n> > does (with log.showroot enabled).  This gives easy access to a readable\n> > diff for the commit, irrespective of how many parents it has and without\n> > any trickery to remove the commit message from the git-show output.\n> \n> Not interested yet, as the \"git show\" discussion is not convincing at all.\n> \n> Is the message annoying enough to warrant this change?\n\nI thought the same thing when I saw his message, but reading further,\nthe current output is nonsensical. So if not this patch, we should\nprobably at least complain about bogus input and die (though if it is\neasy to make it work, why not...).\n\n-Peff\n"},{"id":"121361","messageId":"200908210042.05802.trast@student.ethz.ch","threadId":"20675","inReplyTo":"7vab1up1gz.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] Make 'diff C^!' show the same diff as 'show C'","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2009-08-20T22:42:03Z","receivedAt":"2009-08-20T22:42:03Z","isPatch":true,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Junio C Hamano wrote:\n> Thomas Rast <trast@student.ethz.ch> writes:\n> \n> > Ideally, we'd like 'git diff C^!' to show the same diff that 'git show C'\n> > does (with log.showroot enabled).  This gives easy access to a readable\n> > diff for the commit, irrespective of how many parents it has and without\n> > any trickery to remove the commit message from the git-show output.\n> \n> Not interested yet, as the \"git show\" discussion is not convincing at all.\n\nWell, it is currently half-supported, diff doesn't complain about it,\nyet it does something wildly different from what people expect in the\nzero- and two-parent cases.\n\nAnd yes, people expect this to work; searching the #git logs (I won't\nlink here as it takes a fair while even for one request) shows that\npeople such as Dscho, Thiago, Jakub and Björn have recommended this\nsyntax in the context of diff.\n\n> Is the message annoying enough to warrant this change?\n> \n> If that is indeed the case and if it is a common thing to ask, isn't it\n> more productive to teach \"show\" a way to do so in a simpler way than\n> doing, say,\n> \n> \t$ git show --pretty=format: HEAD\n\nThat still doesn't get rid of the stray newline.\n\n-- \nThomas Rast\ntrast@{inf,student}.ethz.ch\n"},{"id":"121363","messageId":"7v1vn6ozso.fsf@alter.siamese.dyndns.org","threadId":"20675","inReplyTo":"20090820223424.GA5843@coredump.intra.peff.net","subject":"Re: [PATCH] Make 'diff C^!' show the same diff as 'show C'","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-08-20T23:01:27Z","receivedAt":"2009-08-20T23:01:27Z","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 Thu, Aug 20, 2009 at 03:25:16PM -0700, Junio C Hamano wrote:\n>\n>> Thomas Rast <trast@student.ethz.ch> writes:\n>> \n>> > Ideally, we'd like 'git diff C^!' to show the same diff that 'git show C'\n>> > does (with log.showroot enabled).  This gives easy access to a readable\n>> > diff for the commit, irrespective of how many parents it has and without\n>> > any trickery to remove the commit message from the git-show output.\n>> \n>> Not interested yet, as the \"git show\" discussion is not convincing at all.\n>> \n>> Is the message annoying enough to warrant this change?\n>\n> I thought the same thing when I saw his message, but reading further,\n> the current output is nonsensical. So if not this patch, we should\n> probably at least complain about bogus input and die (though if it is\n> easy to make it work, why not...).\n\nOk.\n"},{"id":"121364","messageId":"7vws4ynl5e.fsf@alter.siamese.dyndns.org","threadId":"20675","inReplyTo":"200908210042.05802.trast@student.ethz.ch","subject":"Re: [PATCH] Make 'diff C^!' show the same diff as 'show C'","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-08-20T23:03:09Z","receivedAt":"2009-08-20T23:03:09Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thomas Rast <trast@student.ethz.ch> writes:\n\n>> If that is indeed the case and if it is a common thing to ask, isn't it\n>> more productive to teach \"show\" a way to do so in a simpler way than\n>> doing, say,\n>> \n>> \t$ git show --pretty=format: HEAD\n>\n> That still doesn't get rid of the stray newline.\n\nAnd the reason you don't want that newline, especially when you know there\nalways is one so if you really wanted to you could easily sed it out,\nis...?\n"},{"id":"121367","messageId":"7vocqanjua.fsf@alter.siamese.dyndns.org","threadId":"20675","inReplyTo":"86d1201d8adf53c1f48c0f3526d8e81475b18244.1250806019.git.trast@student.ethz.ch","subject":"Re: [PATCH] Make 'diff C^!' show the same diff as 'show C'","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-08-20T23:31:25Z","receivedAt":"2009-08-20T23:31:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thomas Rast <trast@student.ethz.ch> writes:\n\n> * If C has no parents, setup_revision() turns C^! into simply C.  This\n>   meant that 'git diff C^!' compared the current worktree to C, which\n>   is certainly not what the user asked for.\n>\n> * Otherwise setup_revision puts C itself last, i.e., the rev.pending\n>   are ^C^1 ... ^C^N C.  So the first revision is uninteresting and in\n>   the case of exactly two parents, the symmetric difference revspec\n>   (diff A...B) case fired, and compared C only to C^1 (instead of\n>   showing a combined diff).\n\nI actually have a vague recollection that this ugly syntax C^! (and I am\nentitled to call it ugly as it was my invention) was advertised as a way\nto get \"diff C^..C\", not the combined diff, iow, this could be deliberate\nand people may depend on it.\n\nIn that light, I would say the first one (showing the root commit as root)\nmay be a good change, but the latter one is moderately iffy.\n\n> @@ -292,6 +310,17 @@ int cmd_diff(int argc, const char **argv, const char *prefix)\n>  \t/* Otherwise, we are doing the usual \"git\" diff */\n>  \trev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;\n>  \n> +\tfor (i = 1; i < argc; i++) {\n> +\t\tif (prefixcmp(argv[i], \"--\")) {\n> +\t\t\tif (strstr(argv[i], \"...\"))\n> +\t\t\t\tmode = DIFF_MODE_SYMMETRIC;\n> +\t\t\telse if (strstr(argv[i], \"^!\"))\n> +\t\t\t\tmode = DIFF_MODE_SHOW;\n> +\t\t} else if (!strcmp(argv[i], \"--\")) {\n> +\t\t\tbreak;\n> +\t\t}\n> +\t}\n> +\n\nThis is too ugly beyond words.  \n\nWe already mark the left side commit \"...\" with SYMMETRIC_LEFT bit, so you\nshould be able to detect it from the setup_revisions() result.  If we were\nto formerly add some special meaning (other than being a short-hand of\n^C^n C) to the ugly C^! syntax, I would suggest marking the result of in a\nsimilar way to allow you to detect it from the result.\n\nBut I do mean moderately strong negativeness when I say \"if we _were_\"\nabove.\n\nAs far as I recall, there were only two reasons C^! was invented for\n(actually, one that was invented for, and another that was found to be\nuseful).\n\nOne was so that you can say \"The traversal should stop around this commit,\nbut I want the commit itself to be included in the result\".\n\n\t$ git log v1.6.3^! v1.6.3.1\n\nThis is much less useful than it used to be back when C^! was invented, as\nwe can ask for --boundary these days.\n\nThe other utility later found was \"to view diff with its first parent\".  I\nthink it is a useful mode of operation, and we should add a simpler way to\nask for it to \"git show\", as people often ask to view a merge not in the\ncombined way, but a simple diff relative to the merged-to commit, to get\nan overview of the work done by the side branch.\n\nSo if anything, I'm actually for deprecating C^! syntax and removing it\nbefore we hit 1.7.0.\n"},{"id":"121369","messageId":"7vk50ynjnb.fsf@alter.siamese.dyndns.org","threadId":"20675","inReplyTo":"7vocqanjua.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] Make 'diff C^!' show the same diff as 'show C'","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-08-20T23:35:36Z","receivedAt":"2009-08-20T23:35:36Z","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> We already mark the left side commit \"...\" with SYMMETRIC_LEFT bit, so you\n> should be able to detect it from the setup_revisions() result.  If we were\n> to formerly add some special meaning (other than being a short-hand of\n\nblush.  I meant \"formally\".\n\n> ^C^n C) to the ugly C^! syntax, I would suggest marking the result of in a\n> similar way to allow you to detect it from the result.\n>\n> But I do mean moderately strong negativeness when I say \"if we _were_\"\n> above.\n"}]}