{"thread":{"id":"43118","subject":"Re: [PATCH 1/3] diff_tree_sha1(): avoid rereading trees if possible","startedAt":"2006-12-07T10:17:07Z","lastAt":"2006-12-19T19:39:25Z","messageCount":37,"participants":["Johannes Schindelin","Linus Torvalds","Petr Baudis","Junio C Hamano","Jakub Narebski","Catalin Marinas","Shawn Pearce","Robin Rosenberg","Shawn O. Pearce"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"298570","messageId":"20061207101707.GA19139@spearce.org","threadId":"43118","inReplyTo":null,"subject":"[PATCH 1/1] Make sure the empty tree exists when needed in merge-recursive.","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2006-12-07T10:17:07Z","receivedAt":"2006-12-07T10:17:07Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"There are some baseless merge cases where git-merge-recursive will\ntry to compare one of the branches against the empty tree.  However\nmost projects won't have the empty tree object in their object database\nas Git does not normally create empty tree objects.  If the empty tree\nobject is missing then the merge process will die, as it cannot load the\nobject from the database.  The error message may make the user think that\ntheir database is corrupt when its actually not.\n\nSo instead we should just create the empty tree object whenever it is\nneeded.  If the object already exists as a loose object then no harm\ndone.  Otherwise that loose object will be pruned away later by either\ngit-prune or git-prune-packed.\n\nThanks goes to Junio for suggesting this fix.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n merge-recursive.c |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex cd2cc77..32e186c 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -1238,7 +1238,7 @@ static int merge(struct commit *h1,\n \n \t\ttree->object.parsed = 1;\n \t\ttree->object.type = OBJ_TREE;\n-\t\thash_sha1_file(NULL, 0, tree_type, tree->object.sha1);\n+\t\twrite_sha1_file(NULL, 0, tree_type, tree->object.sha1);\n \t\tmerged_common_ancestors = make_virtual_commit(tree, \"ancestor\");\n \t}\n \n-- \n"},{"id":"297013","messageId":"Pine.LNX.4.63.0612100055160.28348@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43118","inReplyTo":"20061207101707.GA19139@spearce.org","subject":"[PATCH 1/3] diff_tree_sha1(): avoid rereading trees if possible","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-09T23:55:34Z","receivedAt":"2006-12-09T23:55:34Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nIf the tree has already been read, no need to read it into memory\nagain.\n\nThis also helps when this function is called on temporary trees;\nthese no longer have to be written to disk.\n\nSigned-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n---\n tree-diff.c |   33 ++++++++++++++++++++++-----------\n 1 files changed, 22 insertions(+), 11 deletions(-)\n\ndiff --git a/tree-diff.c b/tree-diff.c\nindex 9d80dfb..54a6b44 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -195,23 +195,34 @@ int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, stru\n \treturn 0;\n }\n \n+static int get_tree_desc_from_sha1(const unsigned char *sha1,\n+\t\tstruct tree_desc *t)\n+{\n+\tstruct object *o;\n+\n+\to = lookup_object(sha1);\n+\tif (o && o->type == OBJ_TREE && o->parsed) {\n+\t\tstruct tree *tree = (struct tree *)o;\n+\t\tt->size = tree->size;\n+\t\tt->buf = xmalloc(t->size);\n+\t\tmemcpy(t->buf, tree->buffer, t->size);\n+\t} else {\n+\t\tt->buf = read_object_with_reference(sha1,\n+\t\t\t\ttree_type, &t->size, NULL);\n+\t\tif (!t->buf)\n+\t\t\tdie(\"unable to read source tree (%s)\",\n+\t\t\t\t\tsha1_to_hex(sha1));\n+\t}\n+}\n+\n int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const char *base, struct diff_options *opt)\n {\n-\tvoid *tree1, *tree2;\n \tstruct tree_desc t1, t2;\n \tint retval;\n \n-\ttree1 = read_object_with_reference(old, tree_type, &t1.size, NULL);\n-\tif (!tree1)\n-\t\tdie(\"unable to read source tree (%s)\", sha1_to_hex(old));\n-\ttree2 = read_object_with_reference(new, tree_type, &t2.size, NULL);\n-\tif (!tree2)\n-\t\tdie(\"unable to read destination tree (%s)\", sha1_to_hex(new));\n-\tt1.buf = tree1;\n-\tt2.buf = tree2;\n+\tget_tree_desc_from_sha1(old, &t1);\n+\tget_tree_desc_from_sha1(new, &t2);\n \tretval = diff_tree(&t1, &t2, base, opt);\n-\tfree(tree1);\n-\tfree(tree2);\n \treturn retval;\n }\n \n-- \n1.4.4.2.g0f32-dirty\n\n"},{"id":"295295","messageId":"Pine.LNX.4.63.0612100055390.28348@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43118","inReplyTo":"20061207101707.GA19139@spearce.org","subject":"[PATCH 2/3] merge-recursive: make empty tree a known object","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-09T23:56:05Z","receivedAt":"2006-12-09T23:56:05Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nTo use it in diff_tree_sha1(), a tree has to be hashed in the\nglobal object collection. This actually moves the empty tree (if\nit is needed) into the global object hash.\n\nSigned-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n---\n merge-recursive.c |    3 ++-\n 1 files changed, 2 insertions(+), 1 deletions(-)\n\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex 6e13b8e..280f23c 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -1220,9 +1220,10 @@ static int merge(struct commit *h1,\n \t\t/* if there is no common ancestor, make an empty tree */\n \t\tstruct tree *tree = xcalloc(1, sizeof(struct tree));\n \n+\t\thash_sha1_file(NULL, 0, tree_type, tree->object.sha1);\n+\t\tcreated_object(tree->object.sha1, &tree->object);\n \t\ttree->object.parsed = 1;\n \t\ttree->object.type = OBJ_TREE;\n-\t\thash_sha1_file(NULL, 0, tree_type, tree->object.sha1);\n \t\tmerged_common_ancestors = make_virtual_commit(tree, \"ancestor\");\n \t}\n \n-- \n1.4.4.2.g0f32-dirty\n\n"},{"id":"296905","messageId":"Pine.LNX.4.63.0612100056090.28348@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43118","inReplyTo":"20061207101707.GA19139@spearce.org","subject":"[PATCH 3/3] add test case for recursive merge","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-09T23:56:33Z","receivedAt":"2006-12-09T23:56:33Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThis test case is based on the bug report by Shawn Pearce.\n\nSigned-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n---\n t/t6024-recursive-merge.sh |   68 ++++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 68 insertions(+), 0 deletions(-)\n\ndiff --git a/t/t6024-recursive-merge.sh b/t/t6024-recursive-merge.sh\nnew file mode 100644\nindex 0000000..5f821fb\n--- /dev/null\n+++ b/t/t6024-recursive-merge.sh\n@@ -0,0 +1,68 @@\n+#!/bin/sh\n+\n+test_description='Test merge without common ancestors'\n+. ./test-lib.sh\n+\n+# This scenario is based on a real-world repository of Shawn Pearce.\n+\n+# 1 - A - D - F\n+#   \\   X   /\n+#     B   X\n+#       X   \\\n+# 2 - C - E - G\n+\n+echo 1 > a1\n+git add a1\n+git commit -m 1 a1\n+\n+git checkout -b A master\n+echo A > a1\n+git commit -m A a1\n+\n+git checkout -b B master\n+echo B > a1\n+git commit -m B a1\n+\n+git checkout -b D A\n+git-rev-parse B > .git/MERGE_HEAD\n+echo D > a1\n+git update-index a1\n+git commit -m D\n+\n+git symbolic-ref HEAD refs/heads/other\n+echo 2 > a1\n+git commit -m 2 a1\n+\n+git checkout -b C\n+echo C > a1\n+git commit -m C a1\n+\n+git checkout -b E C\n+git-rev-parse B > .git/MERGE_HEAD\n+echo E > a1\n+git update-index a1\n+git commit -m E\n+\n+git checkout -b G E\n+git-rev-parse A > .git/MERGE_HEAD\n+echo G > a1\n+git update-index a1\n+git commit -m G\n+\n+git checkout -b F D\n+git-rev-parse C > .git/MERGE_HEAD\n+echo F > a1\n+git update-index a1\n+git commit -m F\n+\n+test_expect_failure \"combined merge conflicts\" \"git merge -m final G\"\n+\n+git ls-files --stage > out\n+cat > expect << EOF\n+100644 cf84443e49e1b366fac938711ddf4be2d4d1d9e9 2\ta1\n+100644 fd7923529855d0b274795ae3349c5e0438333979 3\ta1\n+EOF\n+\n+test_expect_success \"virtual trees were processed\" \"diff -u expect out\"\n+\n+test_done\n-- \n1.4.4.2.g0f32-dirty\n\n"},{"id":"295810","messageId":"Pine.LNX.4.63.0612100114440.28348@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43118","inReplyTo":"Pine.LNX.4.63.0612100056090.28348@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH 3/3] add test case for recursive merge","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-10T00:18:03Z","receivedAt":"2006-12-10T00:18:03Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nthis test succeeds consistently on the machine where I tested it \noriginally, but fails on another of my machines, but only when run without \n\"-v\". Very annoying. I will not have time to investigate until Monday, \nthough.\n\nCiao,\nDscho\n\n"},{"id":"294885","messageId":"7vvekk5xpc.fsf@assigned-by-dhcp.cox.net","threadId":"43118","inReplyTo":"Pine.LNX.4.63.0612100055160.28348@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH 1/3] diff_tree_sha1(): avoid rereading trees if possible","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-12-10T01:47:11Z","receivedAt":"2006-12-10T01:47:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> If the tree has already been read, no need to read it into memory\n> again.\n\nHmm...\n\n> This also helps when this function is called on temporary trees;\n> these no longer have to be written to disk.\n\nTo generate tree-diff, probably yes, but I am not sure that\nallows you to use hash_sha1_file() everywhere in merge_recursive\ninstead of write_sha1_file(), if that is what you are getting\nat.\n\n> +static int get_tree_desc_from_sha1(const unsigned char *sha1,\n> +\t\tstruct tree_desc *t)\n> +{\n> +\tstruct object *o;\n> +\n> +\to = lookup_object(sha1);\n> +\tif (o && o->type == OBJ_TREE && o->parsed) {\n> +\t\tstruct tree *tree = (struct tree *)o;\n> +\t\tt->size = tree->size;\n> +\t\tt->buf = xmalloc(t->size);\n> +\t\tmemcpy(t->buf, tree->buffer, t->size);\n> +\t} else {\n> +\t\tt->buf = read_object_with_reference(sha1,\n> +\t\t\t\ttree_type, &t->size, NULL);\n> +\t\tif (!t->buf)\n> +\t\t\tdie(\"unable to read source tree (%s)\",\n> +\t\t\t\t\tsha1_to_hex(sha1));\n> +\t}\n> +}\n\nAre you absolutely sure that all users of \"struct tree\" retains\nthe tree->buffer for a parsed tree?  If nobody does\n\"free(tree->buffer)\" without \"tree->buffer = NULL\", then the\nsituation is still salvageable (you need a bit more code above),\nthough.\n\nI think this is overkill that only helps a very narrow \"empty\ntree\" special case that [PATCH 2/3] addresses, and can be easily\nand incorrectly abused.  We do not want people to expect that\nreading many trees from different revisions as \"struct tree\"\nobjects and keeping all of them in memory would magically speed\nup diff-tree, for example.\n\nI'd prefer write_sha1_file() approach in Shawn's patch for its\nsimplicity at least for now.\n\nI suspect gitlink/subproject people might want to modify in-core\nrepresentation of a tree to graft in subproject directory\nsomewhere in the superproject, just like the history traversal\ncode modifies in-core representation of a commit to simplify\nparents.  Your approach might turn out to be the right thing to\nfor that application --- populate tree objects in the in-core\nobj_hash[], muck with its entries and then have everybody else\ngo through get_tree_desc_from_sha1() interface to pretend as if\nthe superproject has everything contained in the subproject\ntree.  I dunno.\n"},{"id":"296536","messageId":"7vmz5w5tuw.fsf@assigned-by-dhcp.cox.net","threadId":"43118","inReplyTo":"Pine.LNX.4.63.0612100114440.28348@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH 3/3] add test case for recursive merge","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-12-10T03:10:15Z","receivedAt":"2006-12-10T03:10:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> this test succeeds consistently on the machine where I tested it \n> originally, but fails on another of my machines, but only when run without \n> \"-v\". Very annoying. I will not have time to investigate until Monday, \n> though.\n\nThere seem to be cases where stage #1 contains blob 'B' or 'A'\nor nothing depending on something totally random.  Ring a bell?\n\n"},{"id":"296388","messageId":"Pine.LNX.4.64.0612101030390.12500@woody.osdl.org","threadId":"43118","inReplyTo":"Pine.LNX.4.63.0612100055390.28348@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH 2/3] merge-recursive: make empty tree a known object","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-12-10T18:37:57Z","receivedAt":"2006-12-10T18:37:57Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 10 Dec 2006, Johannes Schindelin wrote:\n> \n> To use it in diff_tree_sha1(), a tree has to be hashed in the\n> global object collection. This actually moves the empty tree (if\n> it is needed) into the global object hash.\n\nI think you should do this more generically.\n\nIf we create this kind of \"default fake object\" that we know about whether \nthe object _really_ exists or not (and I agree it makes sense for the \nempty tree), we should probably use it for \"diff_root_tree_sha1()\" too, \nrather than the special case we have now.\n\nIn other words, right now we have that very special \n\"diff_root_tree_sha1()\" function, but if you create a generic fake \"empty \ntree\" SHA1 that git knows about implicitly, we could entirely replace it \nwith just using\n\n\tdiff_tree_sha1(EMPTY_TREE_SHA1, tree, base, opt);\n\ninstead, and get rid of that special case code (which is efficient, but we \ndon't really _need_ the efficiency).\n\nSo you could make \"read_sha1_file()\" just have a special case for known \nobjects at the end. If the pack entry fails, the loose file case fails, \nthen rather than returning NULL at the end, you could have a list of known \nfixed objects..\n\nHmm?\n\n"},{"id":"298152","messageId":"7vpsar4fcu.fsf@assigned-by-dhcp.cox.net","threadId":"43118","inReplyTo":"Pine.LNX.4.64.0612101030390.12500@woody.osdl.org","subject":"Re: [PATCH 2/3] merge-recursive: make empty tree a known object","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-12-10T21:21:05Z","receivedAt":"2006-12-10T21:21:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> So you could make \"read_sha1_file()\" just have a special case for known \n> objects at the end. If the pack entry fails, the loose file case fails, \n> then rather than returning NULL at the end, you could have a list of known \n> fixed objects..\n\nThat is fine by me.  We would benefit from an empty blob and an\nempty tree.\n"},{"id":"296886","messageId":"Pine.LNX.4.64.0612101326420.12500@woody.osdl.org","threadId":"43118","inReplyTo":"7vpsar4fcu.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 2/3] merge-recursive: make empty tree a known object","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-12-10T21:31:56Z","receivedAt":"2006-12-10T21:31:56Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 10 Dec 2006, Junio C Hamano wrote:\n> \n> That is fine by me.  We would benefit from an empty blob and an\n> empty tree.\n\nI was wondering if we ever had any special case where we wanted the empty \nblob, and couldn't come up with any. Unlike the \"tree diff\" case, a \"blob \ndiff\" will not actually do a \"real diff\" with a non-existing object, it \nspecial-cases it (and, for performance reasons, I think it really should). \n\nAnd all the blob-diff routines generally want to be able to take explicit \ndata anyway, not just diffing two SHA1's (since we often don't have a SHA1 \nanyway - the working tree case).\n\nSo while I think it would make sense to have both the \"empty tree\" and the \n\"empty blob\" as special cases, off-hand I can't actually see where we'd \never use the empty blob SHA1.\n\nIn contrast, the empty tree clearly ends up being an interesting special \ncase that actually gets used occasionally, ie here we had two independent \nuses for the same thing..\n\nBut maybe somebody can point to a case where we actually would want to \ninternally have an easy representation of \"empty blob\".\n\n"},{"id":"297066","messageId":"7vpsar2xom.fsf@assigned-by-dhcp.cox.net","threadId":"43118","inReplyTo":"7vpsar4fcu.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 2/3] merge-recursive: make empty tree a known object","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-12-10T22:28:09Z","receivedAt":"2006-12-10T22:28:09Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <junkio@cox.net> writes:\n\n> Linus Torvalds <torvalds@osdl.org> writes:\n>\n>> So you could make \"read_sha1_file()\" just have a special case for known \n>> objects at the end. If the pack entry fails, the loose file case fails, \n>> then rather than returning NULL at the end, you could have a list of known \n>> fixed objects..\n>\n> That is fine by me.  We would benefit from an empty blob and an\n> empty tree.\n\nI think this might be fragile in the presense of older\nimplementation of git.\n\nA new git may operate fine without having \"well known\" objects\nin the repository, and would happily write result that points at\nthem; an older git would find the resulting repository corrupt.\n\nWe somehow need to force \"well known\" objects to be instantiated\nin the object database when something else points at them.  I am\nnot absolutely sure if keeping has_sha1_file() unaware of this\nmagic is enough.\n\n-- >8 --\nImplement \"well known\" built-in objects.\n\nMake read_sha1_file() aware of a handful \"well known\" objects\nand use built-in copy when they are not found in the object\ndatabase.\n\nNote that we do not hook this into has_sha1_file(), so it is\npossible that has_sha1_file() says you do not have an empty tree\nobject in your repository but read_sha1_file() successfully\ngives you an empty tree object back.\n\nOtherwise write_sha1_file() would not create \"well known\"\nobjects in the repository, leaving the repository corrupt for\nolder implementations of git.\n\n---\n\ndiff --git a/cache.h b/cache.h\nindex f2ec5c8..7ee40e8 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -241,6 +241,10 @@ int adjust_shared_perm(const char *path);\n int safe_create_leading_directories(char *path);\n char *enter_repo(char *path, int strict);\n \n+/* Well known object names */\n+extern unsigned const char EMPTY_TREE_NAME[];\n+extern unsigned const char EMPTY_BLOB_NAME[];\n+\n /* Read and unpack a sha1 file into memory, write memory to a sha1 file */\n extern int sha1_object_info(const unsigned char *, char *, unsigned long *);\n extern void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned long *size);\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex 32e186c..1c56fd3 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -1234,11 +1234,8 @@ static int merge(struct commit *h1,\n \tmerged_common_ancestors = pop_commit(&ca);\n \tif (merged_common_ancestors == NULL) {\n \t\t/* if there is no common ancestor, make an empty tree */\n-\t\tstruct tree *tree = xcalloc(1, sizeof(struct tree));\n-\n-\t\ttree->object.parsed = 1;\n-\t\ttree->object.type = OBJ_TREE;\n-\t\twrite_sha1_file(NULL, 0, tree_type, tree->object.sha1);\n+\t\tstruct tree *tree = lookup_tree(EMPTY_TREE_NAME);\n+\t\tparse_tree(tree);\n \t\tmerged_common_ancestors = make_virtual_commit(tree, \"ancestor\");\n \t}\n \ndiff --git a/sha1_file.c b/sha1_file.c\nindex 63f416b..c6efe88 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -1315,11 +1315,32 @@ static void *read_packed_sha1(const unsigned char *sha1, char *type, unsigned lo\n \treturn unpack_entry(&e, type, size);\n }\n \n-void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size)\n+unsigned const char EMPTY_TREE_NAME[20] = {\n+\t0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9,\t0xa0, 0x60,\n+\t0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04,\n+};\n+\n+unsigned const char EMPTY_BLOB_NAME[20] = {\n+\t0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, 0xd6, 0x43, 0x4b, 0x8b,\n+\t0x29, 0xae, 0x77, 0x5a, 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91,\n+};\n+\n+static struct well_known_objects {\n+\tchar *type;\n+\tunsigned const char *sha1;\n+\tunsigned long size;\n+\tconst char *data;\n+} well_known_objects[] = {\n+\t{ \"tree\", EMPTY_TREE_NAME, 0UL, \"\" },\n+\t{ \"blob\", EMPTY_BLOB_NAME, 0UL, \"\" },\n+};\n+\n+void *read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size)\n {\n \tunsigned long mapsize;\n \tvoid *map, *buf;\n \tstruct pack_entry e;\n+\tint i;\n \n \tif (find_pack_entry(sha1, &e, NULL))\n \t\treturn read_packed_sha1(sha1, type, size);\n@@ -1332,6 +1353,17 @@ void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size\n \treprepare_packed_git();\n \tif (find_pack_entry(sha1, &e, NULL))\n \t\treturn read_packed_sha1(sha1, type, size);\n+\n+\t/* \"well known\" objects */\n+\tfor (i = 0; i < ARRAY_SIZE(well_known_objects); i++) {\n+\t\tif (!hashcmp(well_known_objects[i].sha1, sha1)) {\n+\t\t\t*size = well_known_objects[i].size;\n+\t\t\tbuf = xmalloc(*size);\n+\t\t\tstrcpy(type, well_known_objects[i].type);\n+\t\t\tmemcpy(buf, well_known_objects[i].data, *size);\n+\t\t\treturn buf;\n+\t\t}\n+\t}\n \treturn NULL;\n }\n \n"},{"id":"297976","messageId":"7vlklf2xgd.fsf@assigned-by-dhcp.cox.net","threadId":"43118","inReplyTo":"Pine.LNX.4.64.0612101326420.12500@woody.osdl.org","subject":"Re: [PATCH 2/3] merge-recursive: make empty tree a known object","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-12-10T22:33:06Z","receivedAt":"2006-12-10T22:33:06Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> On Sun, 10 Dec 2006, Junio C Hamano wrote:\n>> \n>> That is fine by me.  We would benefit from an empty blob and an\n>> empty tree.\n>\n> I was wondering if we ever had any special case where we wanted the empty \n> blob, and couldn't come up with any.\n\nAfter saying that I was thinking about the same.  Empty blob is\nnot all that useful (and let's not bring up the \"empty commit\"\nin this discussion pretty please).\n\n> In contrast, the empty tree clearly ends up being an interesting special \n> case that actually gets used occasionally, ie here we had two independent \n> uses for the same thing..\n\nTwo?\n\nI sent out a patch with comment about an issue I worry about.\n\nI do not think the empty-tree case matters in practice because\nwe do not allow an empty tree to be committed, but if we add\nempty blob to the set of \"well known objects\", the backward\ncompatibility issue becomes real.\n"},{"id":"293869","messageId":"Pine.LNX.4.63.0612102347480.28348@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43118","inReplyTo":"7vvekk5xpc.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 1/3] diff_tree_sha1(): avoid rereading trees if possible","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-10T22:49:57Z","receivedAt":"2006-12-10T22:49:57Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 9 Dec 2006, Junio C Hamano wrote:\n\n> I think this is overkill that only helps a very narrow \"empty tree\" \n> special case that [PATCH 2/3] addresses, and can be easily and \n> incorrectly abused.  We do not want people to expect that reading many \n> trees from different revisions as \"struct tree\" objects and keeping all \n> of them in memory would magically speed up diff-tree, for example.\n> \n> I'd prefer write_sha1_file() approach in Shawn's patch for its \n> simplicity at least for now.\n\nOkay, after thinking about it, I agree. merge-recursive is really the only \nuser for such a diff. So, I do not think EMPTY_TREE would be useful.\n\nCiao,\nDscho\n"},{"id":"296187","messageId":"Pine.LNX.4.63.0612102350050.28348@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43118","inReplyTo":"7vmz5w5tuw.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 3/3] add test case for recursive merge","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-10T22:51:38Z","receivedAt":"2006-12-10T22:51:38Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 9 Dec 2006, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > this test succeeds consistently on the machine where I tested it \n> > originally, but fails on another of my machines, but only when run without \n> > \"-v\". Very annoying. I will not have time to investigate until Monday, \n> > though.\n> \n> There seem to be cases where stage #1 contains blob 'B' or 'A'\n> or nothing depending on something totally random.  Ring a bell?\n\nNot at all.\n\nIt seems that one merge is conflicting on \"a1\", and not storing _anything_ \nin the resulting (unclean) tree. So, there is no stage 1.\n\nHowever, I also saw that something is left in stage 1 on the box where the \nproblem arises. Tomorrow.\n\nCiao,\nDscho\n"},{"id":"294217","messageId":"Pine.LNX.4.64.0612101454000.12500@woody.osdl.org","threadId":"43118","inReplyTo":"7vlklf2xgd.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 2/3] merge-recursive: make empty tree a known object","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-12-10T22:54:21Z","receivedAt":"2006-12-10T22:54:21Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 10 Dec 2006, Junio C Hamano wrote:\n\n> > In contrast, the empty tree clearly ends up being an interesting special \n> > case that actually gets used occasionally, ie here we had two independent \n> > uses for the same thing..\n> \n> Two?\n\nmerge-recursive and \"diff against root\"\n\n"},{"id":"297612","messageId":"Pine.LNX.4.63.0612110015410.28348@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43118","inReplyTo":"7vpsar2xom.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 2/3] merge-recursive: make empty tree a known object","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-10T23:16:30Z","receivedAt":"2006-12-10T23:16:30Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 10 Dec 2006, Junio C Hamano wrote:\n\n> Implement \"well known\" built-in objects.\n\nAcked-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n\nCiao,\n"},{"id":"294747","messageId":"Pine.LNX.4.63.0612122347590.2807@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43118","inReplyTo":"7vmz5w5tuw.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH] t6024: fix timing problem","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-12T22:49:34Z","receivedAt":"2006-12-12T22:49:34Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThis script tests a complicated merge, where _all_ files conflict. In\nthese circumstances, the ordering of the commits -- which is affected\nnot by the timestamps in the commit message -- becomes a deciding factor\nof the merge result.\n\nSigned-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n---\n\n\tOn Sat, 9 Dec 2006, Junio C Hamano wrote:\n\n\t> There seem to be cases where stage #1 contains blob 'B' or 'A'\n\t> or nothing depending on something totally random.  Ring a bell?\n\n\tThis patch fixes it..\n\n\tDepending on the order, an add/add conflict _removes_ the file\n\tfrom the index, and as a consequence stage 1 is missing in the\n\tfinal merge (which still fails, because the return value of the\n\tprevious merge is remembered).\n\n\tHow about this: if there is an add/add conflict, we treat it as\n\tif there _was_ an empty file, and we let the shiny new xdl_merge()\n\tfind the _true_ conflicts, _instead of_ removing the file from\n\tthe index, adding both files with different \"~blabla\" markers\n\tappended to their file names to the working directory.\n\n\tHmm?\n\n t/t6024-recursive-merge.sh |   20 +++++++++++---------\n 1 files changed, 11 insertions(+), 9 deletions(-)\n\ndiff --git a/t/t6024-recursive-merge.sh b/t/t6024-recursive-merge.sh\nindex 5f821fb..9416c27 100644\n--- a/t/t6024-recursive-merge.sh\n+++ b/t/t6024-recursive-merge.sh\n@@ -11,54 +11,56 @@ test_description='Test merge without common ancestors'\n #       X   \\\n # 2 - C - E - G\n \n+export GIT_COMMITTER_DATE=\"2006-12-12 23:28:00 +0100\"\n echo 1 > a1\n git add a1\n-git commit -m 1 a1\n+GIT_AUTHOR_DATE=\"2006-12-12 23:00:00\" git commit -m 1 a1\n \n git checkout -b A master\n echo A > a1\n-git commit -m A a1\n+GIT_AUTHOR_DATE=\"2006-12-12 23:00:01\" git commit -m A a1\n \n git checkout -b B master\n echo B > a1\n-git commit -m B a1\n+GIT_AUTHOR_DATE=\"2006-12-12 23:00:02\" git commit -m B a1\n \n git checkout -b D A\n git-rev-parse B > .git/MERGE_HEAD\n echo D > a1\n git update-index a1\n-git commit -m D\n+GIT_AUTHOR_DATE=\"2006-12-12 23:00:03\" git commit -m D\n \n git symbolic-ref HEAD refs/heads/other\n echo 2 > a1\n-git commit -m 2 a1\n+GIT_AUTHOR_DATE=\"2006-12-12 23:00:04\" git commit -m 2 a1\n \n git checkout -b C\n echo C > a1\n-git commit -m C a1\n+GIT_AUTHOR_DATE=\"2006-12-12 23:00:05\" git commit -m C a1\n \n git checkout -b E C\n git-rev-parse B > .git/MERGE_HEAD\n echo E > a1\n git update-index a1\n-git commit -m E\n+GIT_AUTHOR_DATE=\"2006-12-12 23:00:06\" git commit -m E\n \n git checkout -b G E\n git-rev-parse A > .git/MERGE_HEAD\n echo G > a1\n git update-index a1\n-git commit -m G\n+GIT_AUTHOR_DATE=\"2006-12-12 23:00:07\" git commit -m G\n \n git checkout -b F D\n git-rev-parse C > .git/MERGE_HEAD\n echo F > a1\n git update-index a1\n-git commit -m F\n+GIT_AUTHOR_DATE=\"2006-12-12 23:00:08\" git commit -m F\n \n test_expect_failure \"combined merge conflicts\" \"git merge -m final G\"\n \n git ls-files --stage > out\n cat > expect << EOF\n+100644 f70f10e4db19068f79bc43844b49f3eece45c4e8 1\ta1\n 100644 cf84443e49e1b366fac938711ddf4be2d4d1d9e9 2\ta1\n 100644 fd7923529855d0b274795ae3349c5e0438333979 3\ta1\n EOF\n-- \n1.4.4.2.g473fa0-dirty\n"},{"id":"296412","messageId":"7vvekgog0r.fsf@assigned-by-dhcp.cox.net","threadId":"43118","inReplyTo":"Pine.LNX.4.63.0612122347590.2807@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] t6024: fix timing problem","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-12-12T23:23:16Z","receivedAt":"2006-12-12T23:23:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> This script tests a complicated merge, where _all_ files conflict. In\n> these circumstances, the ordering of the commits -- which is affected\n> not by the timestamps in the commit message -- becomes a deciding factor\n> of the merge result.\n\n\"not by the timestamps\", or \"by the timestamps\"?  I am\nconfused...\n\nDo you mean the commit timestamps affect which merge base commit\nbecomes ours and theirs during the computation of the virtual\nmerge base commit?  That certainly explains the problem.\n\n> \tHow about this: if there is an add/add conflict, we treat it as\n> \tif there _was_ an empty file, and we let the shiny new xdl_merge()\n> \tfind the _true_ conflicts, _instead of_ removing the file from\n> \tthe index, adding both files with different \"~blabla\" markers\n> \tappended to their file names to the working directory.\n\nI was not thinking about this t6024 test failure problem but was\nwondering about doing exactly that in merge-recursive to match\nthe \"two file merge\" magic we have in git-merge-one-file.sh ---\nI guess great minds do think alike ;-).\n\n\n"},{"id":"294477","messageId":"Pine.LNX.4.63.0612130053230.2807@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43118","inReplyTo":"7vvekgog0r.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] t6024: fix timing problem","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-12T23:59:29Z","receivedAt":"2006-12-12T23:59:29Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"hI,\n\nOn Tue, 12 Dec 2006, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > This script tests a complicated merge, where _all_ files conflict. In\n> > these circumstances, the ordering of the commits -- which is affected\n> > not by the timestamps in the commit message -- becomes a deciding factor\n> > of the merge result.\n> \n> \"not by the timestamps\", or \"by the timestamps\"?  I am confused...\n\nI deleted the \"only\", but not the \"not\" in front of it. Should have read \nmy mail before sending... Sorry.\n\n> Do you mean the commit timestamps affect which merge base commit becomes \n> ours and theirs during the computation of the virtual merge base commit?  \n> That certainly explains the problem.\n\nIt affects in which order the merge bases are merged. I remember that I \nmade a case for the oldest merge base to go first. If two of them (or all \nthree!) have the same timestamp, I _think_ they are ordered by SHA1...\n\nNow, the problem here is that two of the merge bases have a common merge \nbase, but the third has a completely different root. So, depending on \nwhich merge base goes first, the add/add conflict can remove the file from \nthe index early, in which case the next merge does not find a stage 1.\n\n> > \tHow about this: if there is an add/add conflict, we treat it as\n> > \tif there _was_ an empty file, and we let the shiny new xdl_merge()\n> > \tfind the _true_ conflicts, _instead of_ removing the file from\n> > \tthe index, adding both files with different \"~blabla\" markers\n> > \tappended to their file names to the working directory.\n> \n> I was not thinking about this t6024 test failure problem but was\n> wondering about doing exactly that in merge-recursive to match\n> the \"two file merge\" magic we have in git-merge-one-file.sh ---\n> I guess great minds do think alike ;-).\n\n*beams* Gee, thanks!\n\nCiao,\nDscho\n"},{"id":"298093","messageId":"Pine.LNX.4.63.0612130402300.2807@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43118","inReplyTo":"7vvekgog0r.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH] merge-recursive: add/add really is modify/modify with an empty base","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-13T03:05:39Z","receivedAt":"2006-12-13T03:05:39Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nUnify the handling for cases C (add/add) and D (modify/modify).\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n\n\tOn Tue, 12 Dec 2006, Junio C Hamano wrote:\n\n\t> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\t> \n\t> > How about this: if there is an add/add conflict, we treat it \n\t> > as if there _was_ an empty file, and we let the shiny new \n\t> > xdl_merge() find the _true_ conflicts, _instead of_ removing \n\t> > the file from the index, adding both files with different \n\t> > \"~blabla\" markers appended to their file names to the working \n\t> > directory.\n\t> \n\t> I was not thinking about this t6024 test failure problem but was\n\t> wondering about doing exactly that in merge-recursive to match\n\t> the \"two file merge\" magic we have in git-merge-one-file.sh\n\n\tAs can be seen with the test case, the result is more pleasing.\n\n merge-recursive.c          |   44 +++++++++++++++-----------------------------\n t/t6024-recursive-merge.sh |   12 +++++++++++-\n 2 files changed, 26 insertions(+), 30 deletions(-)\n\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex 7d203a6..5bec599 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -610,6 +610,12 @@ static void fill_mm(const unsigned char *sha1, mmfile_t *mm)\n \tunsigned long size;\n \tchar type[20];\n \n+\tif (!hashcmp(sha1, null_sha1)) {\n+\t\tmm->ptr = xstrdup(\"\");\n+\t\tmm->size = 0;\n+\t\treturn;\n+\t}\n+\n \tmm->ptr = read_sha1_file(sha1, type, &size);\n \tif (!mm->ptr || strcmp(type, blob_type))\n \t\tdie(\"unable to read blob object %s\", sha1_to_hex(sha1));\n@@ -1045,38 +1051,17 @@ static int process_entry(const char *path, struct stage_data *entry,\n \t\t\toutput(\"Adding %s\", path);\n \t\t\tupdate_file(1, sha, mode, path);\n \t\t}\n-\t} else if (!o_sha && a_sha && b_sha) {\n-\t\t/* Case C: Added in both (check for same permissions). */\n-\t\tif (sha_eq(a_sha, b_sha)) {\n-\t\t\tif (a_mode != b_mode) {\n-\t\t\t\tclean_merge = 0;\n-\t\t\t\toutput(\"CONFLICT: File %s added identically in both branches, \"\n-\t\t\t\t       \"but permissions conflict %06o->%06o\",\n-\t\t\t\t       path, a_mode, b_mode);\n-\t\t\t\toutput(\"CONFLICT: adding with permission: %06o\", a_mode);\n-\t\t\t\tupdate_file(0, a_sha, a_mode, path);\n-\t\t\t} else {\n-\t\t\t\t/* This case is handled by git-read-tree */\n-\t\t\t\tassert(0 && \"This case must be handled by git-read-tree\");\n-\t\t\t}\n-\t\t} else {\n-\t\t\tconst char *new_path1, *new_path2;\n-\t\t\tclean_merge = 0;\n-\t\t\tnew_path1 = unique_path(path, branch1);\n-\t\t\tnew_path2 = unique_path(path, branch2);\n-\t\t\toutput(\"CONFLICT (add/add): File %s added non-identically \"\n-\t\t\t       \"in both branches. Adding as %s and %s instead.\",\n-\t\t\t       path, new_path1, new_path2);\n-\t\t\tremove_file(0, path, 0);\n-\t\t\tupdate_file(0, a_sha, a_mode, new_path1);\n-\t\t\tupdate_file(0, b_sha, b_mode, new_path2);\n-\t\t}\n-\n-\t} else if (o_sha && a_sha && b_sha) {\n+\t} else if (a_sha && b_sha) {\n+\t\t/* Case C: Added in both (check for same permissions) and */\n \t\t/* case D: Modified in both, but differently. */\n+\t\tconst char *reason = \"content\";\n \t\tstruct merge_file_info mfi;\n \t\tstruct diff_filespec o, a, b;\n \n+\t\tif (!o_sha) {\n+\t\t\treason = \"add/add\";\n+\t\t\to_sha = (unsigned char *)null_sha1;\n+\t\t}\n \t\toutput(\"Auto-merging %s\", path);\n \t\to.path = a.path = b.path = (char *)path;\n \t\thashcpy(o.sha1, o_sha);\n@@ -1093,7 +1078,8 @@ static int process_entry(const char *path, struct stage_data *entry,\n \t\t\tupdate_file(1, mfi.sha, mfi.mode, path);\n \t\telse {\n \t\t\tclean_merge = 0;\n-\t\t\toutput(\"CONFLICT (content): Merge conflict in %s\", path);\n+\t\t\toutput(\"CONFLICT (%s): Merge conflict in %s\",\n+\t\t\t\t\treason, path);\n \n \t\t\tif (index_only)\n \t\t\t\tupdate_file(0, mfi.sha, mfi.mode, path);\ndiff --git a/t/t6024-recursive-merge.sh b/t/t6024-recursive-merge.sh\nindex 9416c27..964010e 100644\n--- a/t/t6024-recursive-merge.sh\n+++ b/t/t6024-recursive-merge.sh\n@@ -58,9 +58,19 @@ GIT_AUTHOR_DATE=\"2006-12-12 23:00:08\" git commit -m F\n \n test_expect_failure \"combined merge conflicts\" \"git merge -m final G\"\n \n+cat > expect << EOF\n+<<<<<<< HEAD/a1\n+F\n+=======\n+G\n+>>>>>>> 26f86b677eb03d4d956dbe108b29cb77061c1e73/a1\n+EOF\n+\n+test_expect_success \"result contains a conflict\" \"diff -u expect a1\"\n+\n git ls-files --stage > out\n cat > expect << EOF\n-100644 f70f10e4db19068f79bc43844b49f3eece45c4e8 1\ta1\n+100644 f16f906ab60483c100d1241dfc39868de9ec9fcb 1\ta1\n 100644 cf84443e49e1b366fac938711ddf4be2d4d1d9e9 2\ta1\n 100644 fd7923529855d0b274795ae3349c5e0438333979 3\ta1\n EOF\n-- \n"},{"id":"298219","messageId":"7vvekgl2z2.fsf@assigned-by-dhcp.cox.net","threadId":"43118","inReplyTo":"Pine.LNX.4.63.0612130402300.2807@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] merge-recursive: add/add really is modify/modify with an empty base","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-12-13T06:33:21Z","receivedAt":"2006-12-13T06:33:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> Unify the handling for cases C (add/add) and D (modify/modify).\n>\n> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n> ---\n>\n> \tOn Tue, 12 Dec 2006, Junio C Hamano wrote:\n>\n> \t> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \t> \n> \t> > How about this: if there is an add/add conflict, we treat it \n> \t> > as if there _was_ an empty file, and we let the shiny new \n> \t> > xdl_merge() find the _true_ conflicts, _instead of_ removing \n> \t> > the file from the index, adding both files with different \n> \t> > \"~blabla\" markers appended to their file names to the working \n> \t> > directory.\n> \t> \n> \t> I was not thinking about this t6024 test failure problem but was\n> \t> wondering about doing exactly that in merge-recursive to match\n> \t> the \"two file merge\" magic we have in git-merge-one-file.sh\n>\n> \tAs can be seen with the test case, the result is more pleasing.\n\nThis fixes the behaviour in \"both branches add the path\ndifferently\" case.  Previously merge-recursive did not create\nthe working tree file, but now it does just like merge-resolve.\n\nAlthough I would feel very happy about this change, Catalin\nmight want to be informed about potential interaction this\nchange might have with his commit 8d41555 in StGIT.\n"},{"id":"294242","messageId":"Pine.LNX.4.63.0612131232270.3635@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43118","inReplyTo":"7vvekgl2z2.fsf@assigned-by-dhcp.cox.net","subject":"StGit repo & gitweb, was Re: [PATCH] merge-recursive: add/add really is modify/modify with an empty base","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-13T11:46:56Z","receivedAt":"2006-12-13T11:46:56Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Tue, 12 Dec 2006, Junio C Hamano wrote:\n\n> Although I would feel very happy about this change, Catalin\n> might want to be informed about potential interaction this\n> change might have with his commit 8d41555 in StGIT.\n\nIndeed. Catalin, do you have any suggestion how to proceed? Do you want to \nintroduce a check if the file exists prior to re-generating it? Or do you \nneed some version check?\n\nBTW why is StGit not on kernel.org?\n\nNot that it matters: repo.or.cz has a nice mirror. Pasky, how powerful is \nthat machine? I am a happy user of the gitweb interface on that box...\n\nYet another question: On repo.or.cz, I searched for the \"commit\" \"8d41555\" \n(upper right side, very nice, although the search button is lacking, which \nis needed for some browsers like w3m). But I got _two_ results, the one I \nexpected, and its child (probably because it contains the sha1 as part of \nthe parent tag). Is this intended behaviour? After all, I search for the \ncommit...\n\nCiao,\nDscho\n"},{"id":"296110","messageId":"elopl4$3nk$1@sea.gmane.org","threadId":"43118","inReplyTo":"Pine.LNX.4.63.0612131232270.3635@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: StGit repo & gitweb, was Re: [PATCH] merge-recursive: add/add really is modify/modify with an empty base","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-12-13T11:56:37Z","receivedAt":"2006-12-13T11:56:37Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Johannes Schindelin wrote:\n\n> Yet another question: On repo.or.cz, I searched for the \"commit\" \"8d41555\" \n> (upper right side, very nice, although the search button is lacking, which \n> is needed for some browsers like w3m). \n\nThe problem is where to put it. The previous version didn't even had the\n\"select type\" but used [undocumented] search operators 'author:',\n'committer:' and 'pickaxe:'.\n\n>                                        But I got _two_ results, the one I  \n> expected, and its child (probably because it contains the sha1 as part of \n> the parent tag). Is this intended behaviour? After all, I search for the \n> commit...\n\nActually, \"commit\" is a bit of misnomer, as it searches commits contents\n(commit body). You can go to given commit easier by hand editing URL,\nediting \"a=commit;h=8d41555\".\n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n\n"},{"id":"295664","messageId":"b0943d9e0612131401s6cde6d0du5e3c6d2e34bfbbb2@mail.gmail.com","threadId":"43118","inReplyTo":"7vvekgl2z2.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] merge-recursive: add/add really is modify/modify with an empty base","fromName":"Catalin Marinas","fromEmail":"catalin.marinas@gmail.com","sentAt":"2006-12-13T22:01:21Z","receivedAt":"2006-12-13T22:01:21Z","isPatch":true,"sender":{"key":"catalin.marinas@gmail.com","avatar":null},"body":"On 13/12/06, Junio C Hamano <junkio@cox.net> wrote:\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n>\n> > Unify the handling for cases C (add/add) and D (modify/modify).\n> >\n> >       On Tue, 12 Dec 2006, Junio C Hamano wrote:\n> >\n> >       > Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> >       >\n> >       > > How about this: if there is an add/add conflict, we treat it\n> >       > > as if there _was_ an empty file, and we let the shiny new\n> >       > > xdl_merge() find the _true_ conflicts, _instead of_ removing\n> >       > > the file from the index, adding both files with different\n> >       > > \"~blabla\" markers appended to their file names to the working\n> >       > > directory.\n\nWhat is this new xdl_merge()? Is it a better replacement for diff3? In\nthis situation diff3 would actually show two confict parts, each of\nthem being the full file, with an empty ancestor.\n\n> This fixes the behaviour in \"both branches add the path\n> differently\" case.  Previously merge-recursive did not create\n> the working tree file, but now it does just like merge-resolve.\n>\n> Although I would feel very happy about this change, Catalin\n> might want to be informed about potential interaction this\n> change might have with his commit 8d41555 in StGIT.\n\nI don't think it affects StGIT. Previously, \"git-read-tree -m\" left a\nfile in the tree in this conflict situation. When I switched to\ngit-merge-recursive (to handle renames better), I noticed that the\nfile was no longer there and my merge algorithm failed. It now checks\nwhether the file is missing and it generates one.\n\nThe way StGIT handle any conflicts is not to leave the index in a\nstate with multiple stages per file. When I push a patch that is\ncausing an add/add situation, I want a version of the file to be added\nto the index (usually the one already in the tree, not in the patch\nbeing pushed) so that a \"stg status\" won't show like the patch is\nremoving that file.\n\n-- \n"},{"id":"298598","messageId":"b0943d9e0612131409x4a894f72if9c4d44cfa970be@mail.gmail.com","threadId":"43118","inReplyTo":"Pine.LNX.4.63.0612131232270.3635@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: StGit repo & gitweb, was Re: [PATCH] merge-recursive: add/add really is modify/modify with an empty base","fromName":"Catalin Marinas","fromEmail":"catalin.marinas@gmail.com","sentAt":"2006-12-13T22:09:06Z","receivedAt":"2006-12-13T22:09:06Z","isPatch":true,"sender":{"key":"catalin.marinas@gmail.com","avatar":null},"body":"On 13/12/06, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> On Tue, 12 Dec 2006, Junio C Hamano wrote:\n>\n> > Although I would feel very happy about this change, Catalin\n> > might want to be informed about potential interaction this\n> > change might have with his commit 8d41555 in StGIT.\n>\n> Indeed. Catalin, do you have any suggestion how to proceed? Do you want to\n> introduce a check if the file exists prior to re-generating it? Or do you\n> need some version check?\n\nIt currently checks whether the file exists and, if it doesn't, it is\nre-generated. I think the patch is good idea.\n\n> BTW why is StGit not on kernel.org?\n\nWhy would it be? Unless you know who to talk to for this :-), it's not\nreally a derivative of the Linux kernel.\n\n> Not that it matters: repo.or.cz has a nice mirror. Pasky, how powerful is\n> that machine? I am a happy user of the gitweb interface on that box...\n\nHopefully, when I get a bit of time, I'll try to give up the\nhttp-hosted repository and use Pasky's one exclusively.\n\nBTW, how can I notify people that only pull from the http repository\nthat it will no longer be updated (rather than them thinking the\ndevelopment stopped)? One solution would be to create a file with a\nmeaningful name in the top dir and hope people will notice it.\n\n-- \n"},{"id":"295453","messageId":"7vhcvze8l3.fsf@assigned-by-dhcp.cox.net","threadId":"43118","inReplyTo":"b0943d9e0612131401s6cde6d0du5e3c6d2e34bfbbb2@mail.gmail.com","subject":"Re: [PATCH] merge-recursive: add/add really is modify/modify with an empty base","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-12-13T22:26:16Z","receivedAt":"2006-12-13T22:26:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Catalin Marinas\" <catalin.marinas@gmail.com> writes:\n\n> On 13/12/06, Junio C Hamano <junkio@cox.net> wrote:\n>> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n>>\n> What is this new xdl_merge()? Is it a better replacement for diff3? In\n> this situation diff3 would actually show two confict parts, each of\n> them being the full file, with an empty ancestor.\n\nThe calls to xdl_merge() from merge-recursive replace\ninvocations to external \"merge\" from RCS suite.\n\nAn older merge-recursive had a bug (as you noticed and adjusted\nStGIT with the commit 8d41555) in that it did not leave anything\nin the working tree in add/add situation, while merge-resolve\nwould have left its best attempt of ancestor-less two file merge\n(which is not necessarily the straight diff3 \"no common section,\nfull copies from both\" result).  The change in question corrects\nthat problem and merge-recursive would create a file in the\nworking tree just like merge-resolve would.\n\nYou were CC'ed just in case this change in behaviour might\ninteract with the abovementioned change in StGIT, but as you say\nthe change would not break StGIT, we would all be happy ;-).\n"},{"id":"298371","messageId":"200612140006.53291.robin.rosenberg.lists@dewire.com","threadId":"43118","inReplyTo":"b0943d9e0612131409x4a894f72if9c4d44cfa970be@mail.gmail.com","subject":"Re: StGit repo & gitweb, was Re: [PATCH] merge-recursive: add/add really is modify/modify with an empty base","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg.lists@dewire.com","sentAt":"2006-12-13T23:06:52Z","receivedAt":"2006-12-13T23:06:52Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"onsdag 13 december 2006 23:09 skrev Catalin Marinas:\n> BTW, how can I notify people that only pull from the http repository\n> that it will no longer be updated (rather than them thinking the\n> development stopped)? One solution would be to create a file with a\n> meaningful name in the top dir and hope people will notice it.\n\nIf you also remove all other files, people will notice. \n\n"},{"id":"298535","messageId":"Pine.LNX.4.63.0612140045430.3635@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43118","inReplyTo":"b0943d9e0612131401s6cde6d0du5e3c6d2e34bfbbb2@mail.gmail.com","subject":"Re: [PATCH] merge-recursive: add/add really is modify/modify with an empty base","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-13T23:48:03Z","receivedAt":"2006-12-13T23:48:03Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 13 Dec 2006, Catalin Marinas wrote:\n\n> On 13/12/06, Junio C Hamano <junkio@cox.net> wrote:\n> > Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> > \n> > > Unify the handling for cases C (add/add) and D (modify/modify).\n> > >\n> > >       On Tue, 12 Dec 2006, Junio C Hamano wrote:\n> > >\n> > >       > Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> > >       >\n> > >       > > How about this: if there is an add/add conflict, we treat it\n> > >       > > as if there _was_ an empty file, and we let the shiny new\n> > >       > > xdl_merge() find the _true_ conflicts, _instead of_ removing\n> > >       > > the file from the index, adding both files with different\n> > >       > > \"~blabla\" markers appended to their file names to the working\n> > >       > > directory.\n> \n> What is this new xdl_merge()? Is it a better replacement for diff3? In \n> this situation diff3 would actually show two confict parts, each of them \n> being the full file, with an empty ancestor.\n\nxdl_merge(), as Git uses it, tries harder to find the true conflicts. So, \nif the files actually differ in only one line, just this line will be \nshown as conflict.\n\nThere is a flag passed to xdl_merge(), which tells it how hard it should \ntry to make sense of the conflict. We use the \"zealous\" option, which is \nmost accurate, but also slowest (although I have no numbers).\n\n> > This fixes the behaviour in \"both branches add the path\n> > differently\" case.  Previously merge-recursive did not create\n> > the working tree file, but now it does just like merge-resolve.\n> > \n> > Although I would feel very happy about this change, Catalin\n> > might want to be informed about potential interaction this\n> > change might have with his commit 8d41555 in StGIT.\n> \n> I don't think it affects StGIT. Previously, \"git-read-tree -m\" left a\n> file in the tree in this conflict situation. When I switched to\n> git-merge-recursive (to handle renames better), I noticed that the\n> file was no longer there and my merge algorithm failed. It now checks\n> whether the file is missing and it generates one.\n\nGreat!\n\nCiao,\nDscho\n"},{"id":"296809","messageId":"Pine.LNX.4.63.0612140048120.3635@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43118","inReplyTo":"b0943d9e0612131409x4a894f72if9c4d44cfa970be@mail.gmail.com","subject":"Re: StGit repo & gitweb, was Re: [PATCH] merge-recursive: add/add really is modify/modify with an empty base","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-13T23:50:19Z","receivedAt":"2006-12-13T23:50:19Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 13 Dec 2006, Catalin Marinas wrote:\n\n> On 13/12/06, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> > On Tue, 12 Dec 2006, Junio C Hamano wrote:\n> > \n> > > Although I would feel very happy about this change, Catalin\n> > > might want to be informed about potential interaction this\n> > > change might have with his commit 8d41555 in StGIT.\n> > \n> > Indeed. Catalin, do you have any suggestion how to proceed? Do you want to\n> > introduce a check if the file exists prior to re-generating it? Or do you\n> > need some version check?\n> \n> It currently checks whether the file exists and, if it doesn't, it is\n> re-generated. I think the patch is good idea.\n\nThanks.\n\n> > BTW why is StGit not on kernel.org?\n> \n> Why would it be? Unless you know who to talk to for this :-), it's not \n> really a derivative of the Linux kernel.\n\nThere is plenty of stuff on kernel.org which is only related to the Linux \nkernel. And StGit (even if I did not try it yet), seems to be very \nvaluable for working on the kernel.\n\n> > Not that it matters: repo.or.cz has a nice mirror. Pasky, how powerful is\n> > that machine? I am a happy user of the gitweb interface on that box...\n> \n> Hopefully, when I get a bit of time, I'll try to give up the\n> http-hosted repository and use Pasky's one exclusively.\n> \n> BTW, how can I notify people that only pull from the http repository \n> that it will no longer be updated (rather than them thinking the \n> development stopped)? One solution would be to create a file with a \n> meaningful name in the top dir and hope people will notice it.\n\nIMHO removing it altogether would be a good idea. The website should carry \nthe news of the new repository site.\n\nCiao,\nDscho\n"},{"id":"298024","messageId":"elq3ro$93b$2@sea.gmane.org","threadId":"43118","inReplyTo":"Pine.LNX.4.63.0612140048120.3635@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: StGit repo & gitweb, was Re: [PATCH] merge-recursive: add/add really is modify/modify with an empty base","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-12-13T23:57:01Z","receivedAt":"2006-12-13T23:57:01Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Johannes Schindelin wrote:\n\n>> BTW, how can I notify people that only pull from the http repository \n>> that it will no longer be updated (rather than them thinking the \n>> development stopped)? One solution would be to create a file with a \n>> meaningful name in the top dir and hope people will notice it.\n> \n> IMHO removing it altogether would be a good idea. The website should carry \n> the news of the new repository site.\n\nBy the way, would setting http-alternates help? I guess not, not without\nhaving refs copied from the other place...\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n\n"},{"id":"295712","messageId":"b0943d9e0612140331q4c3a32e2l361fd04375f091d7@mail.gmail.com","threadId":"43118","inReplyTo":"Pine.LNX.4.63.0612140045430.3635@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] merge-recursive: add/add really is modify/modify with an empty base","fromName":"Catalin Marinas","fromEmail":"catalin.marinas@gmail.com","sentAt":"2006-12-14T11:31:38Z","receivedAt":"2006-12-14T11:31:38Z","isPatch":true,"sender":{"key":"catalin.marinas@gmail.com","avatar":null},"body":"On 13/12/06, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> xdl_merge(), as Git uses it, tries harder to find the true conflicts. So,\n> if the files actually differ in only one line, just this line will be\n> shown as conflict.\n\nI gave the latest GIT a try and it works OK with StGIT.\n\nThis new merge looks much better than diff3 (or rcs merge) because it\nonly shows the true conflicts.\n\nWhat it the relation between git-merge-recursive and \"git-read-tree\n-m\" (if any)? I currently still use \"git-read-tree -m\" for some merges\nbecause of the speed gain due to the --agressive option (really\nnoticeable when picking a patch from an older branch). Probably\ngit-merge-recursive cannot implement this since it needs to track\ndeletion/additions for rename detection.\n\nAre there any other things to be aware if I completely replace the\n\"git-read-tree + diff3\" with git-merge-recursive?\n\nOne nice addition to git-merge-recursive (probably only useful to\nStGIT) would be more meaningful labeling of the conflict regions,\npassed via a command line similar to the \"diff3 -L\" option. StGIT\ngenerates \"patched\", \"current\" and \"ancestor\" labels with diff3.\n\nYet another nice feature would be the ancestor region (which diff3\ndoesn't add either but it gets added by emacs'\nediff-merge-files-with-ancestor function if you use the interactive\nmerge with StGIT).\n\n-- \n"},{"id":"297515","messageId":"20061214114145.GH1747@spearce.org","threadId":"43118","inReplyTo":"b0943d9e0612140331q4c3a32e2l361fd04375f091d7@mail.gmail.com","subject":"Re: [PATCH] merge-recursive: add/add really is modify/modify with an empty base","fromName":"Shawn Pearce","fromEmail":"spearce@spearce.org","sentAt":"2006-12-14T11:41:45Z","receivedAt":"2006-12-14T11:41:45Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Catalin Marinas <catalin.marinas@gmail.com> wrote:\n> One nice addition to git-merge-recursive (probably only useful to\n> StGIT) would be more meaningful labeling of the conflict regions,\n> passed via a command line similar to the \"diff3 -L\" option. StGIT\n> generates \"patched\", \"current\" and \"ancestor\" labels with diff3.\n\nIndeed.  Getting a SHA1 hash of the branch that I merged in by\nname with \"git merge foof\" is horrible UI.  I want to see \"foof\"\nin the conflict.  Its in my list of things I'd really like to fix,\nbut is currently low priority compared to the issues I've run into\nthis past week with git-merge-recursive's basic functions.\n\nOn the other hand Git's open source strategy is really paying off on\nresolving those problems, typically the issue is fixed and accepted\nby Junio into 'next' in under a day of identification.  :-)\n\n-- \n"},{"id":"295742","messageId":"20061214120028.GK1747@spearce.org","threadId":"43118","inReplyTo":"b0943d9e0612140331q4c3a32e2l361fd04375f091d7@mail.gmail.com","subject":"Re: [PATCH] merge-recursive: add/add really is modify/modify with an empty base","fromName":"Shawn Pearce","fromEmail":"spearce@spearce.org","sentAt":"2006-12-14T12:00:28Z","receivedAt":"2006-12-14T12:00:28Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Catalin Marinas <catalin.marinas@gmail.com> wrote:\n> What it the relation between git-merge-recursive and \"git-read-tree\n> -m\" (if any)? I currently still use \"git-read-tree -m\" for some merges\n> because of the speed gain due to the --agressive option (really\n> noticeable when picking a patch from an older branch). Probably\n> git-merge-recursive cannot implement this since it needs to track\n> deletion/additions for rename detection.\n\nThere is a difference; always has been, probably will be for a\nlong time.\n\nread-tree -m performs some trivial merges in the index.  Its manual\npage explains it in gory detail, but its the really trivial, basic\nthree way merge rules: Given two trees X and Y and some so-called\nbase B:\n\n * If X == Y == B for that file, take any of the three.\n * If X == Y, but not B, take X or Y.\n * If X changes a file, but Y == B for that file, take X.\n * If Y changes a file, but X == B for that file, take Y.\n\nI believe that the --agressive option has added some additional\nrules about trivial file deletes.  However notice the all important\nrule is not handled by read-tree -m:\n\n * If X changes a file, Y also changes file, merge them to create Z.\n\nThis is where read-tree -m punts and hands things off to\nmerge-recursive, which needs to invoke diff3 (or now the internal\nxdl_merge).  read-tree -m also currently does not handle file\nadditions, mode changes, or renames/copies.  All of which are a\nlot more expensive to compute and are slightly less common.\n\nSo Git gets decent performance by going through the rather cheap\nread-tree -m, then falling back into the slower merge-recursive\nwhen read-tree -m punted.  Given that I see about 50% of my merges\nsucceed with just read-tree -m and the other half punt over to\nmerge-recursive it just about balances out over several merges.\n\n> Are there any other things to be aware if I completely replace the\n> \"git-read-tree + diff3\" with git-merge-recursive?\n\nFrom what I understand git-merge-recursive will do everything that\ngit-read-tree -m will do, except its going to be slower doing the\nreally common, stupid cases that git-read-tree -m can handle on\nits own.\n\n-- \n"},{"id":"296304","messageId":"Pine.LNX.4.63.0612141436170.3635@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43118","inReplyTo":"b0943d9e0612140331q4c3a32e2l361fd04375f091d7@mail.gmail.com","subject":"Re: [PATCH] merge-recursive: add/add really is modify/modify with an empty base","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-14T13:44:51Z","receivedAt":"2006-12-14T13:44:51Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 14 Dec 2006, Catalin Marinas wrote:\n\n> On 13/12/06, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> > xdl_merge(), as Git uses it, tries harder to find the true conflicts. So,\n> > if the files actually differ in only one line, just this line will be\n> > shown as conflict.\n> \n> I gave the latest GIT a try and it works OK with StGIT.\n\nGreat!\n\n> What it the relation between git-merge-recursive and \"git-read-tree\n> -m\" (if any)?\n\ngit-merge-recursive internally calls the equivalent of 'git-read-tree -m' \n(it does not fork() and exec(), but rather calls the C functions \ndirectly) and does nothing more if the 'git-write-tree' succeeds. At least \nthat's the theory...\n\nIf the git-write-tree does not succeed, it is because there are unmerged \nentries, and only then, merge-recursive does the rename detection and the \nfile level merges.\n\n> One nice addition to git-merge-recursive (probably only useful to\n> StGIT) would be more meaningful labeling of the conflict regions,\n> passed via a command line similar to the \"diff3 -L\" option. StGIT\n> generates \"patched\", \"current\" and \"ancestor\" labels with diff3.\n\nThis is possible. However, it is not _that_ horrible to see \"HEAD\" and \nsome SHA1 which is obviously non-HEAD. Added to that, a quite common case \nare the intermediate merges which make merge-recursive so powerful, and \nthey are rightly called \"Temporary branch 1\" and \"... 2\".\n\n> Yet another nice feature would be the ancestor region (which diff3\n> doesn't add either but it gets added by emacs'\n> ediff-merge-files-with-ancestor function if you use the interactive\n> merge with StGIT).\n\nFeasible, yes. But the code was written without that idea, so it would \ninvolve changes in the xdmerge_t structure (add i0, chg0), recording that \nin xdl_append_merge(), and passing also the base to \nxdl_fill_merge_buffer().\n\nIs this really that nice? I never needed it... Besides, it can get really \ncrappy when the conflicting regions are too large.\n\nCiao,\nDscho\n"},{"id":"296263","messageId":"b0943d9e0612140615u2d91fec4qe3c8a3d0b6515026@mail.gmail.com","threadId":"43118","inReplyTo":"Pine.LNX.4.63.0612141436170.3635@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] merge-recursive: add/add really is modify/modify with an empty base","fromName":"Catalin Marinas","fromEmail":"catalin.marinas@gmail.com","sentAt":"2006-12-14T14:15:14Z","receivedAt":"2006-12-14T14:15:14Z","isPatch":true,"sender":{"key":"catalin.marinas@gmail.com","avatar":null},"body":"On 14/12/06, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> On Thu, 14 Dec 2006, Catalin Marinas wrote:\n> > What it the relation between git-merge-recursive and \"git-read-tree\n> > -m\" (if any)?\n>\n> git-merge-recursive internally calls the equivalent of 'git-read-tree -m'\n> (it does not fork() and exec(), but rather calls the C functions\n> directly) and does nothing more if the 'git-write-tree' succeeds. At least\n> that's the theory...\n\nOK, thanks (I imagined it might work like this).\n\n> > One nice addition to git-merge-recursive (probably only useful to\n> > StGIT) would be more meaningful labeling of the conflict regions,\n> > passed via a command line similar to the \"diff3 -L\" option. StGIT\n> > generates \"patched\", \"current\" and \"ancestor\" labels with diff3.\n>\n> This is possible. However, it is not _that_ horrible to see \"HEAD\" and\n> some SHA1 which is obviously non-HEAD. Added to that, a quite common case\n> are the intermediate merges which make merge-recursive so powerful, and\n> they are rightly called \"Temporary branch 1\" and \"... 2\".\n\nFrom the StGIT perspective, it only does a three-way merge and passes\ncommit id to git-merge-recursive, hence the complicated naming.\nHowever, it wouldn't be hard to modify StGIT to actually replace the\nhashes in the file with meaningful names.\n\n> > Yet another nice feature would be the ancestor region (which diff3\n> > doesn't add either but it gets added by emacs'\n> > ediff-merge-files-with-ancestor function if you use the interactive\n> > merge with StGIT).\n>\n> Is this really that nice? I never needed it... Besides, it can get really\n> crappy when the conflicting regions are too large.\n\nI think I only used the ancestor region for a mental representation of\nwhat xdl_merge already produces :-) since emacs (nor diff3) wasn't\nable to show the real differences. Probably no longer needed now.\n\nThanks for the explanations.\n\n-- \n"},{"id":"294816","messageId":"20061219185015.GK9399@pasky.or.cz","threadId":"43118","inReplyTo":"Pine.LNX.4.63.0612131232270.3635@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: StGit repo & gitweb, was Re: [PATCH] merge-recursive: add/add really is modify/modify with an empty base","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2006-12-19T18:50:15Z","receivedAt":"2006-12-19T18:50:15Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"On Wed, Dec 13, 2006 at 12:46:56PM CET, Johannes Schindelin wrote:\n> Not that it matters: repo.or.cz has a nice mirror. Pasky, how powerful is \n> that machine? I am a happy user of the gitweb interface on that box...\n\nSee http://repo.or.cz/about.html - two-processor P3 800MHz with 2G RAM,\nand it does quite some work besides doing repo.or.cz as well - there are\nno load problems so far, though. The gitweb load in particular is pretty\nlow, though - I think it's about 350 requests per day; the periodical\nmirroring is far more intensive, but the intervals for this could be\nreduced greatly if that would become a problem.\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nThe meaning of Stonehenge in Traflamadorian, when viewed from above, is:\n\"Replacement part being rushed with all possible speed.\"\n"},{"id":"295245","messageId":"em9f0e$iti$1@sea.gmane.org","threadId":"43118","inReplyTo":"20061219185015.GK9399@pasky.or.cz","subject":"Re: StGit repo & gitweb, was Re: [PATCH] merge-recursive: add/add really is modify/modify with an empty base","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-12-19T19:39:25Z","receivedAt":"2006-12-19T19:39:25Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Petr Baudis wrote:\n\n> On Wed, Dec 13, 2006 at 12:46:56PM CET, Johannes Schindelin wrote:\n>> Not that it matters: repo.or.cz has a nice mirror. Pasky, how powerful is \n>> that machine? I am a happy user of the gitweb interface on that box...\n> \n> See http://repo.or.cz/about.html - two-processor P3 800MHz with 2G RAM,\n> and it does quite some work besides doing repo.or.cz as well - there are\n> no load problems so far, though. The gitweb load in particular is pretty\n> low, though - I think it's about 350 requests per day; the periodical\n> mirroring is far more intensive, but the intervals for this could be\n> reduced greatly if that would become a problem.\n\nDo you do \"git repack -a -d\" (and \"git prune-packed\"), or do you use\nsome kept packs?\n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n\n"}]}