{"thread":{"id":"9529","subject":"merge-recursive: do not rudely die on binary merge","startedAt":"2007-08-14T22:33:07Z","lastAt":"2007-08-22T00:14:10Z","messageCount":22,"participants":["Junio C Hamano","Chris Shoemaker","Chris Larson","Nikodemus Siivola","Steven Grimm","Jeff King","Shawn O. Pearce","Florian Weimer","Johannes Sixt","Jan Hudec","Jakub Narebski"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"50731","messageId":"7v1we5bvbw.fsf@assigned-by-dhcp.cox.net","threadId":"9529","inReplyTo":null,"subject":"merge-recursive: do not rudely die on binary merge","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-08-14T22:33:07Z","receivedAt":"2007-08-14T22:33:07Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"When you try to merge a path that involves binary file-level\nmerge, merge-recursive died rudely without cleaning up its own\nmess.  A files added by the merge were left in the working tree,\nbut the index was not written out (because it just punted and\ndied), so it was cumbersome for the user to retry it by first\nrunning \"git reset --hard\".\n\nThis changes merge-recursive to still warn but do the \"binary\"\nmerge for such a path; leave the \"our\" version in the working\ntree, but still keep the path unmerged so that the user can sort\nit out.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n merge-recursive.c       |   51 +++++++++++++++++++----------------\n t/t6027-merge-binary.sh |   67 +++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 95 insertions(+), 23 deletions(-)\n\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex f7d1b84..5326d7c 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -677,6 +677,26 @@ struct ll_merge_driver {\n /*\n  * Built-in low-levels\n  */\n+static int ll_binary_merge(const struct ll_merge_driver *drv_unused,\n+\t\t\t   const char *path_unused,\n+\t\t\t   mmfile_t *orig,\n+\t\t\t   mmfile_t *src1, const char *name1,\n+\t\t\t   mmfile_t *src2, const char *name2,\n+\t\t\t   mmbuffer_t *result)\n+{\n+\t/*\n+\t * The tentative merge result is \"ours\" for the final round,\n+\t * or common ancestor for an internal merge.  Still return\n+\t * \"conflicted merge\" status.\n+\t */\n+\tmmfile_t *stolen = index_only ? orig : src1;\n+\n+\tresult->ptr = stolen->ptr;\n+\tresult->size = stolen->size;\n+\tstolen->ptr = NULL;\n+\treturn 1;\n+}\n+\n static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,\n \t\t\tconst char *path_unused,\n \t\t\tmmfile_t *orig,\n@@ -687,10 +707,15 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,\n \txpparam_t xpp;\n \n \tif (buffer_is_binary(orig->ptr, orig->size) ||\n-\t\t\tbuffer_is_binary(src1->ptr, src1->size) ||\n-\t\t\tbuffer_is_binary(src2->ptr, src2->size))\n-\t\treturn error(\"Cannot merge binary files: %s vs. %s\\n\",\n+\t    buffer_is_binary(src1->ptr, src1->size) ||\n+\t    buffer_is_binary(src2->ptr, src2->size)) {\n+\t\twarning(\"Cannot merge binary files: %s vs. %s\\n\",\n \t\t\tname1, name2);\n+\t\treturn ll_binary_merge(drv_unused, path_unused,\n+\t\t\t\t       orig, src1, name1,\n+\t\t\t\t       src2, name2,\n+\t\t\t\t       result);\n+\t}\n \n \tmemset(&xpp, 0, sizeof(xpp));\n \treturn xdl_merge(orig,\n@@ -743,26 +768,6 @@ static int ll_union_merge(const struct ll_merge_driver *drv_unused,\n \treturn 0;\n }\n \n-static int ll_binary_merge(const struct ll_merge_driver *drv_unused,\n-\t\t\t   const char *path_unused,\n-\t\t\t   mmfile_t *orig,\n-\t\t\t   mmfile_t *src1, const char *name1,\n-\t\t\t   mmfile_t *src2, const char *name2,\n-\t\t\t   mmbuffer_t *result)\n-{\n-\t/*\n-\t * The tentative merge result is \"ours\" for the final round,\n-\t * or common ancestor for an internal merge.  Still return\n-\t * \"conflicted merge\" status.\n-\t */\n-\tmmfile_t *stolen = index_only ? orig : src1;\n-\n-\tresult->ptr = stolen->ptr;\n-\tresult->size = stolen->size;\n-\tstolen->ptr = NULL;\n-\treturn 1;\n-}\n-\n #define LL_BINARY_MERGE 0\n #define LL_TEXT_MERGE 1\n #define LL_UNION_MERGE 2\ndiff --git a/t/t6027-merge-binary.sh b/t/t6027-merge-binary.sh\nnew file mode 100755\nindex 0000000..a7358f7\n--- /dev/null\n+++ b/t/t6027-merge-binary.sh\n@@ -0,0 +1,67 @@\n+#!/bin/sh\n+\n+test_description='ask merge-recursive to merge binary files'\n+\n+. ./test-lib.sh\n+\n+test_expect_success setup '\n+\n+\tcat ../test4012.png >m &&\n+\tgit add m &&\n+\tgit ls-files -s | sed -e \"s/ 0\t/ 1\t/\" >E1 &&\n+\ttest_tick &&\n+\tgit commit -m \"initial\" &&\n+\n+\tgit branch side &&\n+\techo frotz >a &&\n+\tgit add a &&\n+\techo nitfol >>m &&\n+\tgit add a m &&\n+\tgit ls-files -s a >E0 &&\n+\tgit ls-files -s m | sed -e \"s/ 0\t/ 3\t/\" >E3 &&\n+\ttest_tick &&\n+\tgit commit -m \"master adds some\" &&\n+\n+\tgit checkout side &&\n+\techo rezrov >>m &&\n+\tgit add m &&\n+\tgit ls-files -s m | sed -e \"s/ 0\t/ 2\t/\" >E2 &&\n+\ttest_tick &&\n+\tgit commit -m \"side modifies\" &&\n+\n+\tgit tag anchor &&\n+\n+\tcat E0 E1 E2 E3 >expect\n+'\n+\n+test_expect_success resolve '\n+\n+\trm -f a* m* &&\n+\tgit reset --hard anchor &&\n+\n+\tif git merge -s resolve master\n+\tthen\n+\t\techo Oops, should not have succeeded\n+\t\tfalse\n+\telse\n+\t\tgit ls-files -s >current\n+\t\tdiff -u current expect\n+\tfi\n+'\n+\n+test_expect_success recursive '\n+\n+\trm -f a* m* &&\n+\tgit reset --hard anchor &&\n+\n+\tif git merge -s recursive master\n+\tthen\n+\t\techo Oops, should not have succeeded\n+\t\tfalse\n+\telse\n+\t\tgit ls-files -s >current\n+\t\tdiff -u current expect\n+\tfi\n+'\n+\n+test_done\n"},{"id":"50733","messageId":"20070814231422.GA10662@pe.Belkin","threadId":"9529","inReplyTo":"7v1we5bvbw.fsf@assigned-by-dhcp.cox.net","subject":"Re: merge-recursive: do not rudely die on binary merge","fromName":"Chris Shoemaker","fromEmail":"c.shoemaker@cox.net","sentAt":"2007-08-14T23:14:22Z","receivedAt":"2007-08-14T23:14:22Z","isPatch":false,"sender":{"key":"c.shoemaker@cox.net","avatar":null},"body":"On Tue, Aug 14, 2007 at 03:33:07PM -0700, Junio C Hamano wrote:\n> When you try to merge a path that involves binary file-level\n> merge, merge-recursive died rudely without cleaning up its own\n> mess.  A files added by the merge were left in the working tree,\n> but the index was not written out (because it just punted and\n> died), so it was cumbersome for the user to retry it by first\n> running \"git reset --hard\".\n> \n> This changes merge-recursive to still warn but do the \"binary\"\n> merge for such a path; leave the \"our\" version in the working\n> tree, but still keep the path unmerged so that the user can sort\n> it out.\n\nVery nice. Thanks, Junio.  As an additional convenience, it would be\nnice to make the \"theirs\" version easily accessible.  Perhaps, by\nleaving an untracked file in the working tree, with the original\nfilename, suffixed with a hash-prefix.  Or alternatively,\ncut-n-pastable instuctions on stdout for replacing the file with the\n\"theirs\" version.\n\nOn the other hand, I tend to think that \"theirs\" would be a better\ndefault than \"ours\" anyway - still leaving the path unmerged, of\ncourse.\n\n-chris\n"},{"id":"50737","messageId":"7vps1paceh.fsf@assigned-by-dhcp.cox.net","threadId":"9529","inReplyTo":"20070814231422.GA10662@pe.Belkin","subject":"Re: merge-recursive: do not rudely die on binary merge","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-08-15T00:07:18Z","receivedAt":"2007-08-15T00:07:18Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Chris Shoemaker <c.shoemaker@cox.net> writes:\n\n> Very nice. Thanks, Junio.  As an additional convenience, it would be\n> nice to make the \"theirs\" version easily accessible.\n\nPeople should learn this command.  Really.\n\n\t$ git cat-file -p :$n:path\n\nwhere $n == 2 is ours, $n == 1 is common ancestor, and $n == 3\nis theirs.\n"},{"id":"50738","messageId":"7vlkcdacbi.fsf@assigned-by-dhcp.cox.net","threadId":"9529","inReplyTo":"20070814231422.GA10662@pe.Belkin","subject":"Re: merge-recursive: do not rudely die on binary merge","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-08-15T00:09:05Z","receivedAt":"2007-08-15T00:09:05Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Chris Shoemaker <c.shoemaker@cox.net> writes:\n\n>> This changes merge-recursive to still warn but do the \"binary\"\n>> merge for such a path; leave the \"our\" version in the working\n>> tree, but still keep the path unmerged so that the user can sort\n>> it out.\n>\n> Very nice.\n\nForgot to ask.  I did this because you had trouble on #git\nyesterday and then at around the same time today somebody else\nhad the same issue.  Did this patch solve your problem?  I do\nnot think this has big risk of regression, but if it does not\nhelp anything there is no reason to put it in 1.5.3, so I am\nasking for a success report.\n"},{"id":"50739","messageId":"b6ebd0a50708141718w15ad2bbbrfa1d3c97ca7d4397@mail.gmail.com","threadId":"9529","inReplyTo":"7vlkcdacbi.fsf@assigned-by-dhcp.cox.net","subject":"Re: merge-recursive: do not rudely die on binary merge","fromName":"Chris Larson","fromEmail":"clarson@kergoth.com","sentAt":"2007-08-15T00:18:10Z","receivedAt":"2007-08-15T00:18:10Z","isPatch":false,"sender":{"key":"clarson@kergoth.com","avatar":"https://gravatar.com/avatar/8929179d0d33b0477876eaae4d5ca20dc4207c2eb573360adec7d91f63a3bd71?d=mp&s=160"},"body":"On 8/14/07, Junio C Hamano <gitster@pobox.com> wrote:\n> Chris Shoemaker <c.shoemaker@cox.net> writes:\n>\n> >> This changes merge-recursive to still warn but do the \"binary\"\n> >> merge for such a path; leave the \"our\" version in the working\n> >> tree, but still keep the path unmerged so that the user can sort\n> >> it out.\n> >\n> > Very nice.\n>\n> Forgot to ask.  I did this because you had trouble on #git\n> yesterday and then at around the same time today somebody else\n> had the same issue.  Did this patch solve your problem?  I do\n> not think this has big risk of regression, but if it does not\n> help anything there is no reason to put it in 1.5.3, so I am\n> asking for a success report.\n\nI got bit by this one earlier, and the patch fixed it here.\n-- \nChris Larson - clarson at kergoth dot com\nDedicated Engineer - MontaVista - clarson at mvista dot com\nCore Developer/Architect - TSLib, BitBake, OpenEmbedded, OpenZaurus\n"},{"id":"50740","messageId":"20070815011629.GA11266@pe.Belkin","threadId":"9529","inReplyTo":"7vlkcdacbi.fsf@assigned-by-dhcp.cox.net","subject":"Re: merge-recursive: do not rudely die on binary merge","fromName":"Chris Shoemaker","fromEmail":"c.shoemaker@cox.net","sentAt":"2007-08-15T01:16:29Z","receivedAt":"2007-08-15T01:16:29Z","isPatch":false,"sender":{"key":"c.shoemaker@cox.net","avatar":null},"body":"On Tue, Aug 14, 2007 at 05:09:05PM -0700, Junio C Hamano wrote:\n> Chris Shoemaker <c.shoemaker@cox.net> writes:\n> \n> >> This changes merge-recursive to still warn but do the \"binary\"\n> >> merge for such a path; leave the \"our\" version in the working\n> >> tree, but still keep the path unmerged so that the user can sort\n> >> it out.\n> >\n> > Very nice.\n> \n> Forgot to ask.  I did this because you had trouble on #git\n> yesterday and then at around the same time today somebody else\n> had the same issue.  Did this patch solve your problem?  I do\n> not think this has big risk of regression, but if it does not\n> help anything there is no reason to put it in 1.5.3, so I am\n> asking for a success report.\n\nYes, with this patch, the merge completes, and leaves the index and\nworking tree in a sane state.  Thanks again.\n\n-chris\n"},{"id":"50763","messageId":"6bcc356f0708150419h51546814x62ceb7c900293d58@mail.gmail.com","threadId":"9529","inReplyTo":"7vps1paceh.fsf@assigned-by-dhcp.cox.net","subject":"Re: merge-recursive: do not rudely die on binary merge","fromName":"Nikodemus Siivola","fromEmail":"nikodemus@random-state.net","sentAt":"2007-08-15T11:19:16Z","receivedAt":"2007-08-15T11:19:16Z","isPatch":false,"sender":{"key":"nikodemus@random-state.net","avatar":null},"body":"On 8/15/07, Junio C Hamano <gitster@pobox.com> wrote:\n\n> People should learn this command.  Really.\n>\n>         $ git cat-file -p :$n:path\n>\n> where $n == 2 is ours, $n == 1 is common ancestor, and $n == 3\n> is theirs.\n\nA question related to this: as a user, how can I tell if a command\nis something I'm expected to use, or if thinking I need it is a\nsign that I'm doing something wrong?\n\nGit has many commands, and telling the business-as-usual apart from\nthe deviant ones is not always easy. It may be that it's just a question\nof knowing what is plumbing and what is a porcelain, but I'm not sure.\n\nCheers,\n\n -- Nikodemus\n"},{"id":"50765","messageId":"7vbqd9rp7t.fsf@gitster.siamese.dyndns.org","threadId":"9529","inReplyTo":"6bcc356f0708150419h51546814x62ceb7c900293d58@mail.gmail.com","subject":"Re: merge-recursive: do not rudely die on binary merge","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-08-15T11:50:46Z","receivedAt":"2007-08-15T11:50:46Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Nikodemus Siivola\" <nikodemus@random-state.net> writes:\n\n> On 8/15/07, Junio C Hamano <gitster@pobox.com> wrote:\n>\n>> People should learn this command.  Really.\n>>\n>>         $ git cat-file -p :$n:path\n>>\n>> where $n == 2 is ours, $n == 1 is common ancestor, and $n == 3\n>> is theirs.\n>\n> A question related to this: as a user, how can I tell if a command\n> is something I'm expected to use, or if thinking I need it is a\n> sign that I'm doing something wrong?\n\nGood question.\n\nI guess \"git show\" instead of \"git cat-file -p\" is probably the\nrecommended way these days.  Mostly sticking to what the user\nmanual demonstrates would be a safe thing to do, as J. Bruce\nFields has really did a great job carefully picking the order of\nthe commands to be presented in the manual.\n"},{"id":"51040","messageId":"46C90C46.1030000@midwinter.com","threadId":"9529","inReplyTo":"7vps1paceh.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH] Document what the stage numbers in the :$n:path syntax mean.","fromName":"Steven Grimm","fromEmail":"koreth@midwinter.com","sentAt":"2007-08-20T03:36:38Z","receivedAt":"2007-08-20T03:36:38Z","isPatch":true,"sender":{"key":"koreth@midwinter.com","avatar":"https://gravatar.com/avatar/71b4d2e8b62f168bdc9e9205341159e3567003b4f9e2127c617c5fa0a1f5bad2?d=mp&s=160"},"body":"Junio C Hamano wrote:\n > People should learn this command.  Really.\n >\n >       $ git cat-file -p :$n:path\n >\n > where $n == 2 is ours, $n == 1 is common ancestor, and $n == 3\n > is theirs.\n\nThe git-rev-parse manpage talks about the :$n:path notation (buried deep in\na list of other syntax) but it just says $n is a \"stage number\" -- someone\nwho is not familiar with the internals of git's merge implementation is\nnever going to be able to figure out that \"1\", \"2\", and \"3\" mean what Junio\nsaid.\n---\n\n    Not sure if this is correct for octopus merges -- corrections welcome.\n\n Documentation/git-rev-parse.txt |    5 ++++-\n 1 files changed, 4 insertions(+), 1 deletions(-)\n\ndiff --git a/Documentation/git-rev-parse.txt \nb/Documentation/git-rev-parse.txt\nindex 4b4d229..4758c33 100644\n--- a/Documentation/git-rev-parse.txt\n+++ b/Documentation/git-rev-parse.txt\n@@ -215,7 +215,10 @@ blobs contained in a commit.\n * A colon, optionally followed by a stage number (0 to 3) and a\n   colon, followed by a path; this names a blob object in the\n   index at the given path.  Missing stage number (and the colon\n-  that follows it) names an stage 0 entry.\n+  that follows it) names an stage 0 entry. During a merge, stage\n+  1 is the common ancestor, stage 2 is the target branch's version\n+  (typically the current branch), and stage 3 is the version from\n+  the branch being merged.\n \n Here is an illustration, by Jon Loeliger.  Both node B and C are\n a commit parents of commit node A.  Parent commits are ordered\n-- \n1.5.3.rc2.4.g726f9\n"},{"id":"51042","messageId":"20070820055221.GA22993@coredump.intra.peff.net","threadId":"9529","inReplyTo":"46C90C46.1030000@midwinter.com","subject":"Re: [PATCH] Document what the stage numbers in the :$n:path syntax mean.","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2007-08-20T05:52:21Z","receivedAt":"2007-08-20T05:52:21Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Aug 20, 2007 at 11:36:38AM +0800, Steven Grimm wrote:\n\n> The git-rev-parse manpage talks about the :$n:path notation (buried deep in\n> a list of other syntax) but it just says $n is a \"stage number\" -- someone\n> who is not familiar with the internals of git's merge implementation is\n> never going to be able to figure out that \"1\", \"2\", and \"3\" mean what Junio\n> said.\n\nI often forget which number corresponds to which source. I seem to\nrecall somebody proposing :ours:$path a while ago, but I couldn't find\nany reference in the archive, so perhaps I just dreamed it.\n\nAm I the only one who messes this up? If not, patch is below.\n\n-- >8 --\nsha1_name: allow human-readable stage aliases\n\nThis adds the alias \":ours:$path\" to mean the same thing as \":2:$path\",\nas well as \"base\" (for 1) and \"theirs\" (for 2), for those of us who\nmerge infrequently and forget which is which.\n\nThe parsing is as strict as possible in order to minimize impact on\nfilenames with colons. However, for some (presumably unlikely)\nfilenames, the behavior is changed. Previously, you could look at stage\n0 of any file beginning with the string \"ours:\" as simply \"git-show\n:ours:foo\". Now, because of the parsing conflict, you must use \"git-show\n:0:ours:foo\".\n\n---\n\n sha1_name.c |   35 +++++++++++++++++++++++++++++------\n 1 files changed, 29 insertions(+), 6 deletions(-)\n\ndiff --git a/sha1_name.c b/sha1_name.c\nindex 2d727d5..eaa6bd7 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -664,6 +664,7 @@ int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)\n \t/* sha1:path --> object name of path in ent sha1\n \t * :path -> object name of path in index\n \t * :[0-3]:path -> object name of path in index at stage\n+\t * :base|ours|theirs:path -> same as :[1-3]:path\n \t */\n \tif (name[0] == ':') {\n \t\tint stage = 0;\n@@ -671,14 +672,36 @@ int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)\n \t\tint pos;\n \t\tif (namelen > 2 && name[1] == '/')\n \t\t\treturn get_sha1_oneline(name + 2, sha1);\n-\t\tif (namelen < 3 ||\n-\t\t    name[2] != ':' ||\n-\t\t    name[1] < '0' || '3' < name[1])\n-\t\t\tcp = name + 1;\n-\t\telse {\n-\t\t\tstage = name[1] - '0';\n+\t\tif (!strncmp(name+1, \"0:\", 2)) {\n+\t\t\tstage = 0;\n+\t\t\tcp = name + 3;\n+\t\t}\n+\t\telse if (!strncmp(name+1, \"1:\", 2)) {\n+\t\t\tstage = 1;\n+\t\t\tcp = name + 3;\n+\t\t}\n+\t\telse if (!strncmp(name+1, \"base:\", 5)) {\n+\t\t\tstage = 1;\n+\t\t\tcp = name + 6;\n+\t\t}\n+\t\telse if (!strncmp(name+1, \"2:\", 2)) {\n+\t\t\tstage = 2;\n \t\t\tcp = name + 3;\n \t\t}\n+\t\telse if (!strncmp(name+1, \"ours:\", 5)) {\n+\t\t\tstage = 2;\n+\t\t\tcp = name + 6;\n+\t\t}\n+\t\telse if (!strncmp(name+1, \"3:\", 2)) {\n+\t\t\tstage = 3;\n+\t\t\tcp = name + 3;\n+\t\t}\n+\t\telse if (!strncmp(name+1, \"theirs:\", 7)) {\n+\t\t\tstage = 3;\n+\t\t\tcp = name + 8;\n+\t\t}\n+\t\telse\n+\t\t\tcp = name + 1;\n \t\tnamelen = namelen - (cp - name);\n \t\tif (!active_cache)\n \t\t\tread_cache();\n"},{"id":"51044","messageId":"20070820060522.GA27913@spearce.org","threadId":"9529","inReplyTo":"20070820055221.GA22993@coredump.intra.peff.net","subject":"Re: [PATCH] Document what the stage numbers in the :$n:path syntax mean.","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-08-20T06:05:22Z","receivedAt":"2007-08-20T06:05:22Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Jeff King <peff@peff.net> wrote:\n> On Mon, Aug 20, 2007 at 11:36:38AM +0800, Steven Grimm wrote:\n> \n> > The git-rev-parse manpage talks about the :$n:path notation (buried deep in\n> > a list of other syntax) but it just says $n is a \"stage number\" -- someone\n> > who is not familiar with the internals of git's merge implementation is\n> > never going to be able to figure out that \"1\", \"2\", and \"3\" mean what Junio\n> > said.\n> \n> I often forget which number corresponds to which source. I seem to\n> recall somebody proposing :ours:$path a while ago, but I couldn't find\n> any reference in the archive, so perhaps I just dreamed it.\n> \n> Am I the only one who messes this up? If not, patch is below.\n\nMaybe.  ;-)\n\nI've memorized it long long ago.  But my coworkers haven't and always\nget it wrong, and look at me funny when I tell them \"trust me, your\ndata is in stage 2 and theirs is in stage 3...  because that's the\nconvention all of the tools you are using follows\".\n\nKeywords in that last part: \"convention\" and \"tools you are using\".\nSomeone could redefine what the stages mean and load content into\nthem using `update index --index-info`.  You might even be able to\nload the stages in odd ways yourself from Porcelain.\n\nOh, like say git-rebase.  During a rebase \"theirs\" (stage 3) is\nyour file and \"ours\" (stage 2) is the upstream.  Confusing now,\nain't it?  Mine is theirs and ours is theirs?  Huh?  Yeeaaaah.\n\nThis is why I've never liked most merge tools.  They get hung up on\nwhat is theirs and what is mine and then at some point they wind up\nconfusing the stages and getting them inverted.  And this is exactly\nwhy git-merge.sh/git-rebase.sh/git-am.sh try to setup GITHEAD_* for\ngit-merge-recursive, and why they set it up using branch names and\npatch subject lines, because it makes the conflict markers easier\nto understand.\n \n>  \t/* sha1:path --> object name of path in ent sha1\n>  \t * :path -> object name of path in index\n>  \t * :[0-3]:path -> object name of path in index at stage\n> +\t * :base|ours|theirs:path -> same as :[1-3]:path\n>  \t */\n\nAt least document the new syntax in git-rev-parse documentation?\n\n-- \nShawn.\n"},{"id":"51045","messageId":"20070820061330.GB27913@spearce.org","threadId":"9529","inReplyTo":"20070820060522.GA27913@spearce.org","subject":"Re: [PATCH] Document what the stage numbers in the :$n:path syntax mean.","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-08-20T06:13:30Z","receivedAt":"2007-08-20T06:13:30Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"\"Shawn O. Pearce\" <spearce@spearce.org> wrote:\n> Jeff King <peff@peff.net> wrote:\n> > On Mon, Aug 20, 2007 at 11:36:38AM +0800, Steven Grimm wrote:\n> > \n> > > The git-rev-parse manpage talks about the :$n:path notation (buried deep in\n> > > a list of other syntax) but it just says $n is a \"stage number\" -- someone\n> > > who is not familiar with the internals of git's merge implementation is\n> > > never going to be able to figure out that \"1\", \"2\", and \"3\" mean what Junio\n> > > said.\n> > \n> > I often forget which number corresponds to which source. I seem to\n> > recall somebody proposing :ours:$path a while ago, but I couldn't find\n> > any reference in the archive, so perhaps I just dreamed it.\n> > \n> > Am I the only one who messes this up? If not, patch is below.\n> \n> Maybe.  ;-)\n> \n> I've memorized it long long ago.  But my coworkers haven't and always\n> get it wrong, and look at me funny when I tell them \"trust me, your\n> data is in stage 2 and theirs is in stage 3...  because that's the\n> convention all of the tools you are using follows\".\n\nActually, what's wrong with the following:\n\n\tgit show HEAD:foo.c\n\tgit show MERGE_HEAD:foo.c\n\n?\n\nThat gives you yours (HEAD) and theirs (MERGE_HEAD).  And it doesn't\nabuse sha1_file.c.  Granted it only works during a true merge and\ndoesn't work during a rebase, but remember I just pointed out life\nis backwards anyway during a rebase, so uh, yea...\n\n-- \nShawn.\n"},{"id":"51046","messageId":"7v4piuafqy.fsf@gitster.siamese.dyndns.org","threadId":"9529","inReplyTo":"46C90C46.1030000@midwinter.com","subject":"Re: [PATCH] Document what the stage numbers in the :$n:path syntax mean.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-08-20T06:20:53Z","receivedAt":"2007-08-20T06:20:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Steven Grimm <koreth@midwinter.com> writes:\n\n> Junio C Hamano wrote:\n>> People should learn this command.  Really.\n>>\n>>       $ git cat-file -p :$n:path\n>>\n>> where $n == 2 is ours, $n == 1 is common ancestor, and $n == 3\n>> is theirs.\n>\n> The git-rev-parse manpage talks about the :$n:path notation (buried deep in\n> a list of other syntax) but it just says $n is a \"stage number\" -- someone\n> who is not familiar with the internals of git's merge implementation is\n> never going to be able to figure out that \"1\", \"2\", and \"3\" mean what Junio\n> said.\n\nThe patch makes sense.  Thanks.\n\nJust to give historical background to new readers, this is\nprimarily because the really core level of the plumbing started\nas not caring between stages 2 and 3 (iow, as far as the merge\nis concerned, both heads are equal), and the description in the\nmanual was written back then.\n\nThese days, all the merge strategies and other non-merge\nprograms such as \"git am\" that can record conflicts as\nmulti-stage index entries consistently use stage #2 as our\nversion, and stages #2 and #3 are not equals anymore.\n"},{"id":"51048","messageId":"7vveba90qs.fsf@gitster.siamese.dyndns.org","threadId":"9529","inReplyTo":"20070820060522.GA27913@spearce.org","subject":"Re: [PATCH] Document what the stage numbers in the :$n:path syntax mean.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-08-20T06:30:19Z","receivedAt":"2007-08-20T06:30:19Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Shawn O. Pearce\" <spearce@spearce.org> writes:\n\n>> Am I the only one who messes this up? If not, patch is below.\n>\n> Maybe.  ;-)\n>\n> I've memorized it long long ago.  But my coworkers haven't and always\n> get it wrong, and look at me funny when I tell them \"trust me, your\n> data is in stage 2 and theirs is in stage 3...  because that's the\n> convention all of the tools you are using follows\".\n\nI am not _opposed_ to :ours:$path syntax, but I suspect there is\nsomething else that is wrong if you need to use :$n:$path syntax\nthat often.\n\nI have never been in a situation I had to say :base:$path,\nunless I am debugging the merge driver.  So it is between :ours:$path\nand :theirs:$path.\n\nBut aren't they by definition HEAD:$path and MERGE_HEAD:$path,\nwhich are far more descriptive?\n"},{"id":"51050","messageId":"20070820063733.GA31201@coredump.intra.peff.net","threadId":"9529","inReplyTo":"20070820060522.GA27913@spearce.org","subject":"Re: [PATCH] Document what the stage numbers in the :$n:path syntax mean.","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2007-08-20T06:37:33Z","receivedAt":"2007-08-20T06:37:33Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Aug 20, 2007 at 02:05:22AM -0400, Shawn O. Pearce wrote:\n\n> Oh, like say git-rebase.  During a rebase \"theirs\" (stage 3) is\n> your file and \"ours\" (stage 2) is the upstream.  Confusing now,\n> ain't it?  Mine is theirs and ours is theirs?  Huh?  Yeeaaaah.\n\nUgh, I hadn't even thought of that. git-diff _does_ respect \"--base\",\n\"--ours\", and \"--theirs\" to mean the same thing, but I am now wondering\nif that is a bit of a mistake.\n\nHowever, as the intent of my patch was to _increase_ usability, I think\na gotcha like that is probably counterproductive. OTOH, users of\ngit-rebase already have to make the switch mentally.\n\n> confusing the stages and getting them inverted.  And this is exactly\n> why git-merge.sh/git-rebase.sh/git-am.sh try to setup GITHEAD_* for\n\nYes, I agree that the GITHEAD markers are much more sensible.\nUnfortunately, I'm not sure of the best way to translate them into\nstage names. The MERGE_HEAD/HEAD suggestion you made is a nice way of\navoiding the whole issue, though it doesn't easily provide the \"base\"\nversion.\n\n> At least document the new syntax in git-rev-parse documentation?\n\nI was about to, but your message has convinced me that this is perhaps\nnot a very good idea.\n\n-Peff\n"},{"id":"51051","messageId":"20070820064401.GB31201@coredump.intra.peff.net","threadId":"9529","inReplyTo":"7vveba90qs.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Document what the stage numbers in the :$n:path syntax mean.","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2007-08-20T06:44:01Z","receivedAt":"2007-08-20T06:44:01Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Aug 19, 2007 at 11:30:19PM -0700, Junio C Hamano wrote:\n\n> I am not _opposed_ to :ours:$path syntax, but I suspect there is\n> something else that is wrong if you need to use :$n:$path syntax\n> that often.\n\nThat's the problem: I don't use it that often, so when I do, the numbers\nseem nonsensical.\n\n> I have never been in a situation I had to say :base:$path,\n> unless I am debugging the merge driver.  So it is between :ours:$path\n> and :theirs:$path.\n\nI used to need it to look at the 3-way merge, but git-mergetool now does\na nice job of hiding these details from me.\n\nThinking about it more, I really _haven't_ used the stages at all since\ngit-mergetool came around. This thread just reminded me of all the prior\ntimes when I had had trouble with it.\n\nSo Junio, please consider my patch retracted. What _would_ be useful is\nGITHEAD_* support for git-mergetool, which has been on my 'todo' list\nfor some time. I'll see if I can work up a patch for that.\n\n-Peff\n"},{"id":"51053","messageId":"828x86ad8q.fsf@mid.bfk.de","threadId":"9529","inReplyTo":"20070820061330.GB27913@spearce.org","subject":"Re: [PATCH] Document what the stage numbers in the :$n:path syntax mean.","fromName":"Florian Weimer","fromEmail":"fweimer@bfk.de","sentAt":"2007-08-20T07:15:01Z","receivedAt":"2007-08-20T07:15:01Z","isPatch":true,"sender":{"key":"fweimer@bfk.de","avatar":null},"body":"* Shawn O. Pearce:\n\n>> I've memorized it long long ago.  But my coworkers haven't and always\n>> get it wrong, and look at me funny when I tell them \"trust me, your\n>> data is in stage 2 and theirs is in stage 3...  because that's the\n>> convention all of the tools you are using follows\".\n>\n> Actually, what's wrong with the following:\n>\n> \tgit show HEAD:foo.c\n> \tgit show MERGE_HEAD:foo.c\n>\n> ?\n\nI think that in the staged versions, the non-conflicting parts of the\nmerge are in fact merged.  For the HEAD/MERGE_HEAD versions, this\nisn't the case, obviously.\n\n-- \nFlorian Weimer                <fweimer@bfk.de>\nBFK edv-consulting GmbH       http://www.bfk.de/\nKriegsstraße 100              tel: +49-721-96201-1\nD-76133 Karlsruhe             fax: +49-721-96201-99\n"},{"id":"51059","messageId":"20070820080453.GA13233@coredump.intra.peff.net","threadId":"9529","inReplyTo":"828x86ad8q.fsf@mid.bfk.de","subject":"Re: [PATCH] Document what the stage numbers in the :$n:path syntax mean.","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2007-08-20T08:04:53Z","receivedAt":"2007-08-20T08:04:53Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Aug 20, 2007 at 09:15:01AM +0200, Florian Weimer wrote:\n\n> > Actually, what's wrong with the following:\n> >\n> > \tgit show HEAD:foo.c\n> > \tgit show MERGE_HEAD:foo.c\n> \n> I think that in the staged versions, the non-conflicting parts of the\n> merge are in fact merged.  For the HEAD/MERGE_HEAD versions, this\n> isn't the case, obviously.\n\nNo, the stage versions are not merged at all (but the working tree copy\nhas all non-conflicting parts merged).\n\nHere's a script that creates a conflicted file with one easily resolved\npart and one conflict. You can see the staged hashes at the end (and\ncheck the working tree copy to see that only the one conflict is\nmarked).\n\n-Peff\n\n-- >8 --\nmkdir repo && cd repo && git-init\n\nhead -n 100 </usr/share/dict/words >words\ngit-add words\ngit-commit -m words\n\nsed '10d' <words >words.tmp\nmv words.tmp words\ngit-commit -a -m 'remove 10'\n\ngit-checkout -b other HEAD^\nsed '9d\n     90d' <words >words.tmp\nmv words.tmp words\ngit-commit -a -m 'remove 9 and 90'\n\ngit-merge master\n\necho \"stage 2 `git-rev-parse :2:words`\"\necho \"HEAD    `git-rev-parse HEAD:words`\"\necho \"stage 3    `git-rev-parse :3:words`\"\necho \"MERGE_HEAD `git-rev-parse MERGE_HEAD:words`\"\n"},{"id":"51076","messageId":"46C96528.67A3FDAE@eudaptics.com","threadId":"9529","inReplyTo":"20070820055221.GA22993@coredump.intra.peff.net","subject":"Re: [PATCH] Document what the stage numbers in the :$n:path syntaxmean.","fromName":"Johannes Sixt","fromEmail":"j.sixt@eudaptics.com","sentAt":"2007-08-20T09:55:52Z","receivedAt":"2007-08-20T09:55:52Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Jeff King wrote:\n> +               else if (!strncmp(name+1, \"1:\", 2)) {\n> [etc.]\n\nprefixcmp()?\n\n-- Hannes\n"},{"id":"51103","messageId":"20070820180809.GA8542@efreet.light.src","threadId":"9529","inReplyTo":"7v4piuafqy.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Document what the stage numbers in the :$n:path syntax mean.","fromName":"Jan Hudec","fromEmail":"bulb@ucw.cz","sentAt":"2007-08-20T18:08:09Z","receivedAt":"2007-08-20T18:08:09Z","isPatch":true,"sender":{"key":"bulb@ucw.cz","avatar":null},"body":"On Sun, Aug 19, 2007 at 23:20:53 -0700, Junio C Hamano wrote:\n> Steven Grimm <koreth@midwinter.com> writes:\n> \n> > Junio C Hamano wrote:\n> >> People should learn this command.  Really.\n> >>\n> >>       $ git cat-file -p :$n:path\n> >>\n> >> where $n == 2 is ours, $n == 1 is common ancestor, and $n == 3\n> >> is theirs.\n> >\n> > The git-rev-parse manpage talks about the :$n:path notation (buried deep in\n> > a list of other syntax) but it just says $n is a \"stage number\" -- someone\n> > who is not familiar with the internals of git's merge implementation is\n> > never going to be able to figure out that \"1\", \"2\", and \"3\" mean what Junio\n> > said.\n> \n> The patch makes sense.  Thanks.\n> \n> Just to give historical background to new readers, this is\n> primarily because the really core level of the plumbing started\n> as not caring between stages 2 and 3 (iow, as far as the merge\n> is concerned, both heads are equal), and the description in the\n> manual was written back then.\n> \n> These days, all the merge strategies and other non-merge\n> programs such as \"git am\" that can record conflicts as\n> multi-stage index entries consistently use stage #2 as our\n> version, and stages #2 and #3 are not equals anymore.\n\nPardon me? In what are they not equal?\n\nIn merge, the parents *are* equall. They are just recorded in the resulting\ncommit in particular order and the stages are in that order.\n\nBesides if I prepare a merge locally to push out to a shared repo, I will\nprobably switch to the mainline and merge my branch in, so it will actually\nbe my changes in stage #3. That is to say 'ours' and 'theirs' don't really\nexpress what is going on IMHO.\n\n-- \n\t\t\t\t\t\t Jan 'Bulb' Hudec <bulb@ucw.cz>\n"},{"id":"51117","messageId":"7vy7g6rnev.fsf@gitster.siamese.dyndns.org","threadId":"9529","inReplyTo":"20070820180809.GA8542@efreet.light.src","subject":"Re: [PATCH] Document what the stage numbers in the :$n:path syntax mean.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-08-20T19:55:36Z","receivedAt":"2007-08-20T19:55:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jan Hudec <bulb@ucw.cz> writes:\n\n>> These days, all the merge strategies and other non-merge\n>> programs such as \"git am\" that can record conflicts as\n>> multi-stage index entries consistently use stage #2 as our\n>> version, and stages #2 and #3 are not equals anymore.\n>\n> Pardon me? In what are they not equal?\n\nThe version left in the worktree always corresponds to stage #2.\nThere is no way to say \"please use stage #2 for their version\nand use stage #3 for our version\" (that is not necessary, so\ndon't take this as if I am complaining about a lack of feature).\n\"git-read-tree -m\" knows that stage #2 corresopnds to the index\nand the worktree and performs up-to-date check on them to make\nsure you do not lose local changes.\n\nMerge parent order does not matter --- they are more equal than\nstages between #2 and #3.  But that's not what we are discussing\nhere.\n\nIn some minor corners merge parents are not exactly equal --\nhistory simplification and other places that wants to pick one\nparent iterates from the first to the last parent and pick the\nfirst one, so strictly speaking earlier parents have a slight\nedge over later ones.\n"},{"id":"51212","messageId":"fafv4j$fb4$2@sea.gmane.org","threadId":"9529","inReplyTo":"7vveba90qs.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Document what the stage numbers in the :$n:path syntax mean.","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-08-22T00:14:10Z","receivedAt":"2007-08-22T00:14:10Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano wrote:\n\n> \"Shawn O. Pearce\" <spearce@spearce.org> writes:\n> \n>>> Am I the only one who messes this up? If not, patch is below.\n>>\n>> Maybe.  ;-)\n>>\n>> I've memorized it long long ago.  But my coworkers haven't and always\n>> get it wrong, and look at me funny when I tell them \"trust me, your\n>> data is in stage 2 and theirs is in stage 3...  because that's the\n>> convention all of the tools you are using follows\".\n> \n> I am not _opposed_ to :ours:$path syntax, but I suspect there is\n> something else that is wrong if you need to use :$n:$path syntax\n> that often.\n> \n> I have never been in a situation I had to say :base:$path,\n> unless I am debugging the merge driver.  So it is between :ours:$path\n> and :theirs:$path.\n> \n> But aren't they by definition HEAD:$path and MERGE_HEAD:$path,\n> which are far more descriptive?\n\nNice idea, if only this was mentioned in the documentation...\n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"}]}