{"thread":{"id":"41742","subject":"[PATCH] merge: refuse to create too cool a merge by default","startedAt":"2016-03-18T20:21:09Z","lastAt":"2016-04-06T19:18:33Z","messageCount":10,"participants":["Junio C Hamano","Linus Torvalds","Eric Sunshine","Ramsay Jones","David Turner"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"281173","messageId":"xmqqshznpmfe.fsf@gitster.mtv.corp.google.com","threadId":"41742","inReplyTo":null,"subject":"[PATCH] merge: refuse to create too cool a merge by default","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-18T20:21:09Z","receivedAt":"2016-03-18T20:21:09Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"While it makes sense to allow merging unrelated histories of two\nprojects that started independently into one, in the way \"gitk\" was\nmerged to \"git\" itself aka \"the coolest merge ever\", such a merge is\nstill an unusual event.  Worse, if somebody creates an independent\nhistory by starting from a tarball of an established project and\nsends a pull request to the original project, \"git merge\" however\nhappily creates such a merge without any sign of something unusual\nis happening.\n\nTeach \"git merge\" to refuse to create such a merge by default,\nunless the user passes a new \"--allow-unrelated-histories\" option to\ntell it that the user is aware that two unrelated projects are\nmerged.\n\nBecause such a \"two project merge\" is a rare event, a configuration\noption to always allow such a merge is not added.\n\nWe could add the same option to \"git pull\" and have it passed\nthrough to underlying \"git merge\".  I do not have a fundamental\nopposition against such a feature, but this commit does not do so\nand instead leaves it as low-hanging fruit for others, because such\na \"two project merge\" would be done after fetching the other project\ninto some location in the working tree of an existing project and\nmaking sure how well they fit together, it is sufficient to allow a\nlocal merge without such an option pass-through from \"git pull\" to\n\"git merge\".  Many tests that are updated by this patch does the\npass-through manually by turning:\n\n\tgit pull something\n\ninto its equivalent:\n\n\tgit fetch something &&\n        git merge --allow-unrelated-histories FETCH_HEAD\n\nIf somebody is inclined to add such an option, updated tests in this\nchange need to be adjusted back to:\n\n\tgit pull --allow-unrelated-histories something\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n\n builtin/merge.c                 | 12 +++++++++---\n t/t3412-rebase-root.sh          |  2 +-\n t/t5500-fetch-pack.sh           |  6 ++++--\n t/t6009-rev-list-parent.sh      |  4 +++-\n t/t6010-merge-base.sh           |  6 ++++--\n t/t6012-rev-list-simplify.sh    |  2 +-\n t/t6026-merge-attr.sh           |  3 ++-\n t/t6029-merge-subtree.sh        |  2 +-\n t/t6101-rev-parse-parents.sh    |  2 +-\n t/t9400-git-cvsserver-server.sh |  3 ++-\n 10 files changed, 28 insertions(+), 14 deletions(-)\n\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 101ffef..e3db41b 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -64,6 +64,7 @@ static int option_renormalize;\n static int verbosity;\n static int allow_rerere_auto;\n static int abort_current_merge;\n+static int allow_unrelated_histories;\n static int show_progress = -1;\n static int default_to_upstream = 1;\n static const char *sign_commit;\n@@ -221,6 +222,8 @@ static struct option builtin_merge_options[] = {\n \tOPT__VERBOSITY(&verbosity),\n \tOPT_BOOL(0, \"abort\", &abort_current_merge,\n \t\tN_(\"abort the current in-progress merge\")),\n+\tOPT_BOOL(0, \"allow-unrelated-histories\", &allow_unrelated_histories,\n+\t\t N_(\"allow merging unrelated histories\")),\n \tOPT_SET_INT(0, \"progress\", &show_progress, N_(\"force progress reporting\"), 1),\n \t{ OPTION_STRING, 'S', \"gpg-sign\", &sign_commit, N_(\"key-id\"),\n \t  N_(\"GPG sign commit\"), PARSE_OPT_OPTARG, NULL, (intptr_t) \"\" },\n@@ -1397,9 +1400,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \tupdate_ref(\"updating ORIG_HEAD\", \"ORIG_HEAD\", head_commit->object.oid.hash,\n \t\t   NULL, 0, UPDATE_REFS_DIE_ON_ERR);\n \n-\tif (remoteheads && !common)\n-\t\t; /* No common ancestors found. We need a real merge. */\n-\telse if (!remoteheads ||\n+\tif (remoteheads && !common) {\n+\t\t/* No common ancestors found. */\n+\t\tif (!allow_unrelated_histories)\n+\t\t\tdie(_(\"refusing to merge unrelated histories\"));\n+\t\t/* otherwise, we need a real merge. */\n+\t} else if (!remoteheads ||\n \t\t (!remoteheads->next && !common->next &&\n \t\t  common->item == remoteheads->item)) {\n \t\t/*\ndiff --git a/t/t3412-rebase-root.sh b/t/t3412-rebase-root.sh\nindex 0b52105..73a39f2 100755\n--- a/t/t3412-rebase-root.sh\n+++ b/t/t3412-rebase-root.sh\n@@ -133,7 +133,7 @@ test_expect_success 'set up second root and merge' '\n \trm A B C &&\n \ttest_commit 6 D &&\n \tgit checkout other &&\n-\tgit merge third\n+\tgit merge --allow-unrelated-histories third\n '\n \n cat > expect-third <<'EOF'\ndiff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh\nindex e5f83bf..4fca623 100755\n--- a/t/t5500-fetch-pack.sh\n+++ b/t/t5500-fetch-pack.sh\n@@ -259,7 +259,8 @@ test_expect_success 'clone shallow object count' '\n test_expect_success 'pull in shallow repo with missing merge base' '\n \t(\n \t\tcd shallow &&\n-\t\ttest_must_fail git pull --depth 4 .. A\n+\t\tgit fetch --depth 4 .. A\n+\t\ttest_must_fail git merge --allow-unrelated-histories FETCH_HEAD\n \t)\n '\n \n@@ -279,9 +280,10 @@ test_expect_success 'clone shallow depth count' '\n test_expect_success 'clone shallow object count' '\n \t(\n \t\tcd shallow &&\n+\t\tgit prune &&\n \t\tgit count-objects -v\n \t) > count.shallow &&\n-\tgrep \"^count: 55\" count.shallow\n+\tgrep \"^count: 54\" count.shallow\n '\n \n test_expect_success 'fetch --no-shallow on full repo' '\ndiff --git a/t/t6009-rev-list-parent.sh b/t/t6009-rev-list-parent.sh\nindex 66cda17..20e3e25 100755\n--- a/t/t6009-rev-list-parent.sh\n+++ b/t/t6009-rev-list-parent.sh\n@@ -47,7 +47,9 @@ test_expect_success 'setup roots, merges and octopuses' '\n \tgit checkout -b yetanotherbranch four &&\n \ttest_commit eight &&\n \tgit checkout master &&\n-\ttest_merge normalmerge newroot &&\n+\ttest_tick &&\n+\tgit merge --allow-unrelated-histories -m normalmerge newroot &&\n+\tgit tag normalmerge &&\n \ttest_tick &&\n \tgit merge -m tripus sidebranch anotherbranch &&\n \tgit tag tripus &&\ndiff --git a/t/t6010-merge-base.sh b/t/t6010-merge-base.sh\nindex 39b3238..e0c5f44 100755\n--- a/t/t6010-merge-base.sh\n+++ b/t/t6010-merge-base.sh\n@@ -215,11 +215,13 @@ test_expect_success 'criss-cross merge-base for octopus-step' '\n \tgit reset --hard E &&\n \ttest_commit CC2 &&\n \ttest_tick &&\n-\tgit merge -s ours CC1 &&\n+\t# E is a root commit unrelated to MMR root on which CC1 is based\n+\tgit merge -s ours --allow-unrelated-histories CC1 &&\n \ttest_commit CC-o &&\n \ttest_commit CCB &&\n \tgit reset --hard CC1 &&\n-\tgit merge -s ours CC2 &&\n+\t# E is a root commit unrelated to MMR root on which CC1 is based\n+\tgit merge -s ours --allow-unrelated-histories CC2 &&\n \ttest_commit CCA &&\n \n \tgit rev-parse CC1 CC2 >expected &&\ndiff --git a/t/t6012-rev-list-simplify.sh b/t/t6012-rev-list-simplify.sh\nindex b89cd6b..2a0fbb8 100755\n--- a/t/t6012-rev-list-simplify.sh\n+++ b/t/t6012-rev-list-simplify.sh\n@@ -71,7 +71,7 @@ test_expect_success setup '\n \tnote J &&\n \n \tgit checkout master &&\n-\ttest_tick && git merge -m \"Coolest\" unrelated &&\n+\ttest_tick && git merge --allow-unrelated-histories -m \"Coolest\" unrelated &&\n \tnote K &&\n \n \techo \"Immaterial\" >elif &&\ndiff --git a/t/t6026-merge-attr.sh b/t/t6026-merge-attr.sh\nindex 04c0509..ef0cbce 100755\n--- a/t/t6026-merge-attr.sh\n+++ b/t/t6026-merge-attr.sh\n@@ -176,7 +176,8 @@ test_expect_success 'up-to-date merge without common ancestor' '\n \ttest_tick &&\n \t(\n \t\tcd repo1 &&\n-\t\tgit pull ../repo2 master\n+\t\tgit fetch ../repo2 master &&\n+\t\tgit merge --allow-unrelated-histories FETCH_HEAD\n \t)\n '\n \ndiff --git a/t/t6029-merge-subtree.sh b/t/t6029-merge-subtree.sh\nindex 73fc240..3e69245 100755\n--- a/t/t6029-merge-subtree.sh\n+++ b/t/t6029-merge-subtree.sh\n@@ -49,7 +49,7 @@ test_expect_success 'setup' '\n \n test_expect_success 'initial merge' '\n \tgit remote add -f gui ../git-gui &&\n-\tgit merge -s ours --no-commit gui/master &&\n+\tgit merge -s ours --no-commit --allow-unrelated-histories gui/master &&\n \tgit read-tree --prefix=git-gui/ -u gui/master &&\n \tgit commit -m \"Merge git-gui as our subdirectory\" &&\n \tgit checkout -b work &&\ndiff --git a/t/t6101-rev-parse-parents.sh b/t/t6101-rev-parse-parents.sh\nindex 10b1452..1c6952d 100755\n--- a/t/t6101-rev-parse-parents.sh\n+++ b/t/t6101-rev-parse-parents.sh\n@@ -19,7 +19,7 @@ test_expect_success 'setup' '\n \tgit checkout --orphan tmp &&\n \ttest_commit start2 &&\n \tgit checkout master &&\n-\tgit merge -m next start2 &&\n+\tgit merge -m next --allow-unrelated-histories start2 &&\n \ttest_commit final &&\n \n \ttest_seq 40 |\ndiff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh\nindex d708cbf..432c61d 100755\n--- a/t/t9400-git-cvsserver-server.sh\n+++ b/t/t9400-git-cvsserver-server.sh\n@@ -45,7 +45,8 @@ test_expect_success 'setup' '\n   touch secondrootfile &&\n   git add secondrootfile &&\n   git commit -m \"second root\") &&\n-  git pull secondroot master &&\n+  git fetch secondroot master &&\n+  git merge --allow-unrelated-histories FETCH_HEAD &&\n   git clone -q --bare \"$WORKDIR/.git\" \"$SERVERDIR\" >/dev/null 2>&1 &&\n   GIT_DIR=\"$SERVERDIR\" git config --bool gitcvs.enabled true &&\n   GIT_DIR=\"$SERVERDIR\" git config gitcvs.logfile \"$SERVERDIR/gitcvs.log\" &&\n"},{"id":"281174","messageId":"CA+55aFz7309BkfHjD5H7tp9WE0yf1VWncxfmB3hgimJ00fbT-Q@mail.gmail.com","threadId":"41742","inReplyTo":"xmqqshznpmfe.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH] merge: refuse to create too cool a merge by default","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2016-03-18T20:25:44Z","receivedAt":"2016-03-18T20:25:44Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"On Fri, Mar 18, 2016 at 1:21 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> While it makes sense to allow merging unrelated histories of two\n> projects that started independently into one, in the way \"gitk\" was\n> merged to \"git\" itself aka \"the coolest merge ever\", such a merge is\n> still an unusual event.  Worse, if somebody creates an independent\n> history by starting from a tarball of an established project and\n> sends a pull request to the original project, \"git merge\" however\n> happily creates such a merge without any sign of something unusual\n> is happening.\n>\n> Teach \"git merge\" to refuse to create such a merge by default,\n> unless the user passes a new \"--allow-unrelated-histories\" option to\n> tell it that the user is aware that two unrelated projects are\n> merged.\n\nHeh. I had a separate set of patches for you, but hadn't sent them out\nbecause of the other test failures (which you also worked out).\n\nMine was slightly different, I just went with a \"unrelated\" merge option.\n\nI'll attach my two patches anyway, if for no other reason than the\nfact that I actually wrote a new test for this.\n\nFeel free to ignore my patches, they have nothing really different\nfrom yours, just slightly different implementation.\n\n                  Linus\n\n\nFrom 0f3e4a9294eeda6799e3e50e28809133233126db Mon Sep 17 00:00:00 2001\nFrom: Linus Torvalds <torvalds@linux-foundation.org>\nDate: Fri, 18 Mar 2016 12:46:06 -0700\nSubject: [PATCH 1/2] t3035: test merging of unrelated branches\n\nRight now this succeeds, and the test actually verifies that behavior.\n\nSigned-off-by: Linus Torvalds <torvalds@linux-foundation.org>\n---\n t/t3035-merge-recursive-across-project.sh | 28 ++++++++++++++++++++++++++++\n 1 file changed, 28 insertions(+)\n create mode 100755 t/t3035-merge-recursive-across-project.sh\n\ndiff --git a/t/t3035-merge-recursive-across-project.sh b/t/t3035-merge-recursive-across-project.sh\nnew file mode 100755\nindex 000000000000..b5d614db6b08\n--- /dev/null\n+++ b/t/t3035-merge-recursive-across-project.sh\n@@ -0,0 +1,28 @@\n+#!/bin/sh\n+\n+test_description='merge-recursive with unrelated projects\n+\n+Test rename detection by examining rename/delete conflicts.\n+\n+ * A: file A\n+\n+ * B: file B\n+'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'setup repository' \\\n+\t'echo Hello >A &&\n+\t git add A &&\n+\t git commit -m \"Branch A\" A &&\n+\t git branch A &&\n+\t git mv A B &&\n+\t echo Hi >B &&\n+\t git commit -m \"Branch B\" --amend B &&\n+\t git branch B'\n+\n+test_expect_success 'merge unrelated branches' \\\n+\t'git checkout -b merged A &&\n+\t git merge B'\n+\n+test_done\n-- \n2.8.0.rc3.9.g44915db\n\n\n\nFrom cd6b2388c73f37b3dd6180d9a42993fd219ebb31 Mon Sep 17 00:00:00 2001\nFrom: Linus Torvalds <torvalds@linux-foundation.org>\nDate: Fri, 18 Mar 2016 12:57:30 -0700\nSubject: [PATCH 2/2] merge: fail merging of unrelated branches\n\nAdd test for this, and add the \"unrelated\" merge option to allow it to succeed.\n\nSigned-off-by: Linus Torvalds <torvalds@linux-foundation.org>\n---\n merge-recursive.c                         | 6 ++++++\n merge-recursive.h                         | 1 +\n t/t3035-merge-recursive-across-project.sh | 7 +++++--\n 3 files changed, 12 insertions(+), 2 deletions(-)\n\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex b880ae50e7ee..92779db0bbe6 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -1927,6 +1927,9 @@ int merge_recursive(struct merge_options *o,\n \t\t/* if there is no common ancestor, use an empty tree */\n \t\tstruct tree *tree;\n \n+\t\tif (!o->allow_unrelated)\n+\t\t\tdie(_(\"will not merge unrelated branches\"));\n+\n \t\ttree = lookup_tree(EMPTY_TREE_SHA1_BIN);\n \t\tmerged_common_ancestors = make_virtual_commit(tree, \"ancestor\");\n \t}\n@@ -2039,6 +2042,7 @@ void init_merge_options(struct merge_options *o)\n \tmemset(o, 0, sizeof(struct merge_options));\n \to->verbosity = 2;\n \to->buffer_output = 1;\n+\to->allow_unrelated = 0;\n \to->diff_rename_limit = -1;\n \to->merge_rename_limit = -1;\n \to->renormalize = 0;\n@@ -2092,6 +2096,8 @@ int parse_merge_opt(struct merge_options *o, const char *s)\n \t\to->renormalize = 1;\n \telse if (!strcmp(s, \"no-renormalize\"))\n \t\to->renormalize = 0;\n+\telse if (!strcmp(s, \"unrelated\"))\n+\t\to->allow_unrelated = 1;\n \telse if (!strcmp(s, \"no-renames\"))\n \t\to->detect_rename = 0;\n \telse if (!strcmp(s, \"find-renames\")) {\ndiff --git a/merge-recursive.h b/merge-recursive.h\nindex 52f0201f68a3..19eb52eeb732 100644\n--- a/merge-recursive.h\n+++ b/merge-recursive.h\n@@ -15,6 +15,7 @@ struct merge_options {\n \tconst char *subtree_shift;\n \tunsigned buffer_output : 1;\n \tunsigned renormalize : 1;\n+\tunsigned allow_unrelated : 1;\n \tlong xdl_opts;\n \tint verbosity;\n \tint detect_rename;\ndiff --git a/t/t3035-merge-recursive-across-project.sh b/t/t3035-merge-recursive-across-project.sh\nindex b5d614db6b08..87902f1c8f66 100755\n--- a/t/t3035-merge-recursive-across-project.sh\n+++ b/t/t3035-merge-recursive-across-project.sh\n@@ -21,8 +21,11 @@ test_expect_success 'setup repository' \\\n \t git commit -m \"Branch B\" --amend B &&\n \t git branch B'\n \n-test_expect_success 'merge unrelated branches' \\\n+test_expect_success 'fail merging of unrelated branches' \\\n \t'git checkout -b merged A &&\n-\t git merge B'\n+\t test_must_fail git merge B'\n+\n+test_expect_success 'explicitly merge unrelated branches' \\\n+\t'git merge -Xunrelated B'\n \n test_done\n-- \n2.8.0.rc3.9.g44915db\n\n"},{"id":"281175","messageId":"xmqqoaabplue.fsf@gitster.mtv.corp.google.com","threadId":"41742","inReplyTo":"CA+55aFz7309BkfHjD5H7tp9WE0yf1VWncxfmB3hgimJ00fbT-Q@mail.gmail.com","subject":"Re: [PATCH] merge: refuse to create too cool a merge by default","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-18T20:33:45Z","receivedAt":"2016-03-18T20:33:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@linux-foundation.org> writes:\n\n> Mine was slightly different, I just went with a \"unrelated\" merge option.\n\nYeah, I was debating myself if this should be -Xunrelated specific\nto recursive or an option that is meant for all strategies.  I can\ngo either way, but I think a command-wide option is logically the\nright way to go, because you do not want two-project merge by\ndefault no matter what strategy is used (and some of you may know\nthat I had a long term plan with no lines of code yet to do yet\nanother merge strategy).\n\n> I'll attach my two patches anyway, if for no other reason than the\n> fact that I actually wrote a new test for this.\n\nThanks, but after updating existing scripts, I think those changes\nalready make sure that two-project merges work with the option.\nWhat is missing in my version is a new test that ensures the command\nfails a two-project merge by default.\n"},{"id":"281176","messageId":"CAPig+cRN_3kP8+w2inG+hm_81AXLVx6CFER+MPr_oenDqEdEug@mail.gmail.com","threadId":"41742","inReplyTo":"xmqqshznpmfe.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH] merge: refuse to create too cool a merge by default","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-03-18T21:00:27Z","receivedAt":"2016-03-18T21:00:27Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Fri, Mar 18, 2016 at 4:21 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> While it makes sense to allow merging unrelated histories of two\n> projects that started independently into one, in the way \"gitk\" was\n> merged to \"git\" itself aka \"the coolest merge ever\", such a merge is\n> still an unusual event.  Worse, if somebody creates an independent\n> history by starting from a tarball of an established project and\n> sends a pull request to the original project, \"git merge\" however\n> happily creates such a merge without any sign of something unusual\n> is happening.\n>\n> Teach \"git merge\" to refuse to create such a merge by default,\n> unless the user passes a new \"--allow-unrelated-histories\" option to\n> tell it that the user is aware that two unrelated projects are\n> merged.\n> [...]\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n> diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh\n> @@ -279,9 +280,10 @@ test_expect_success 'clone shallow depth count' '\n>  test_expect_success 'clone shallow object count' '\n>         (\n>                 cd shallow &&\n> +               git prune &&\n>                 git count-objects -v\n>         ) > count.shallow &&\n> -       grep \"^count: 55\" count.shallow\n> +       grep \"^count: 54\" count.shallow\n>  '\n\nUm, wasn't this change the subject of a separate patch[1]?\n\n[1]: http://article.gmane.org/gmane.comp.version-control.git/289246\n"},{"id":"281185","messageId":"56EC79DD.7010104@ramsayjones.plus.com","threadId":"41742","inReplyTo":"xmqqshznpmfe.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH] merge: refuse to create too cool a merge by default","fromName":"Ramsay Jones","fromEmail":"ramsay@ramsayjones.plus.com","sentAt":"2016-03-18T21:57:49Z","receivedAt":"2016-03-18T21:57:49Z","isPatch":true,"sender":{"key":"ramsay@ramsayjones.plus.com","avatar":"https://avatars.githubusercontent.com/u/33702710?v=4"},"body":"\n\nOn 18/03/16 20:21, Junio C Hamano wrote:\n> While it makes sense to allow merging unrelated histories of two\n> projects that started independently into one, in the way \"gitk\" was\n> merged to \"git\" itself aka \"the coolest merge ever\", such a merge is\n> still an unusual event.  Worse, if somebody creates an independent\n> history by starting from a tarball of an established project and\n> sends a pull request to the original project, \"git merge\" however\n> happily creates such a merge without any sign of something unusual\n> is happening.\n> \n> Teach \"git merge\" to refuse to create such a merge by default,\n> unless the user passes a new \"--allow-unrelated-histories\" option to\n> tell it that the user is aware that two unrelated projects are\n> merged.\n> \n> Because such a \"two project merge\" is a rare event, a configuration\n> option to always allow such a merge is not added.\n> \n> We could add the same option to \"git pull\" and have it passed\n> through to underlying \"git merge\".  I do not have a fundamental\n> opposition against such a feature, but this commit does not do so\n> and instead leaves it as low-hanging fruit for others, because such\n> a \"two project merge\" would be done after fetching the other project\n> into some location in the working tree of an existing project and\n> making sure how well they fit together, it is sufficient to allow a\n> local merge without such an option pass-through from \"git pull\" to\n> \"git merge\".  Many tests that are updated by this patch does the\n> pass-through manually by turning:\n> \n> \tgit pull something\n> \n> into its equivalent:\n> \n> \tgit fetch something &&\n>         git merge --allow-unrelated-histories FETCH_HEAD\n> \n> If somebody is inclined to add such an option, updated tests in this\n> change need to be adjusted back to:\n> \n> \tgit pull --allow-unrelated-histories something\n> \n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n> \n>  builtin/merge.c                 | 12 +++++++++---\n>  t/t3412-rebase-root.sh          |  2 +-\n>  t/t5500-fetch-pack.sh           |  6 ++++--\n>  t/t6009-rev-list-parent.sh      |  4 +++-\n>  t/t6010-merge-base.sh           |  6 ++++--\n>  t/t6012-rev-list-simplify.sh    |  2 +-\n>  t/t6026-merge-attr.sh           |  3 ++-\n>  t/t6029-merge-subtree.sh        |  2 +-\n>  t/t6101-rev-parse-parents.sh    |  2 +-\n>  t/t9400-git-cvsserver-server.sh |  3 ++-\n>  10 files changed, 28 insertions(+), 14 deletions(-)\n> \n\n[snip]\n\n> diff --git a/t/t6010-merge-base.sh b/t/t6010-merge-base.sh\n> index 39b3238..e0c5f44 100755\n> --- a/t/t6010-merge-base.sh\n> +++ b/t/t6010-merge-base.sh\n> @@ -215,11 +215,13 @@ test_expect_success 'criss-cross merge-base for octopus-step' '\n>  \tgit reset --hard E &&\n>  \ttest_commit CC2 &&\n>  \ttest_tick &&\n> -\tgit merge -s ours CC1 &&\n> +\t# E is a root commit unrelated to MMR root on which CC1 is based\n> +\tgit merge -s ours --allow-unrelated-histories CC1 &&\n>  \ttest_commit CC-o &&\n>  \ttest_commit CCB &&\n>  \tgit reset --hard CC1 &&\n> -\tgit merge -s ours CC2 &&\n> +\t# E is a root commit unrelated to MMR root on which CC1 is based\n> +\tgit merge -s ours --allow-unrelated-histories CC2 &&\n\nI was only skimming this patch, but the above caught my eye - I assume\nthat the comment should reference CC2 not CC1. yes?\n\nATB,\nRamsay Jones\n"},{"id":"281186","messageId":"1458339836.9385.29.camel@twopensource.com","threadId":"41742","inReplyTo":"xmqqshznpmfe.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH] merge: refuse to create too cool a merge by default","fromName":"David Turner","fromEmail":"dturner@twopensource.com","sentAt":"2016-03-18T22:23:56Z","receivedAt":"2016-03-18T22:23:56Z","isPatch":true,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"On Fri, 2016-03-18 at 13:21 -0700, Junio C Hamano wrote:\n>  Many tests that are updated by this patch does the\n> pass-through manually by turning:\n\nNit: Should be many tests ... do\n\nAlso, I didn't notice a test that shows that \"cool\" merges without\nallow-unrelated-histories are forbidden.\n"},{"id":"281187","messageId":"xmqq8u1fpfrg.fsf@gitster.mtv.corp.google.com","threadId":"41742","inReplyTo":"1458339836.9385.29.camel@twopensource.com","subject":"Re: [PATCH] merge: refuse to create too cool a merge by default","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-18T22:45:07Z","receivedAt":"2016-03-18T22:45:07Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"David Turner <dturner@twopensource.com> writes:\n\n> Also, I didn't notice a test that shows that \"cool\" merges without\n> allow-unrelated-histories are forbidden.\n\nYeah, because I didn't write one in the version that was sent out,\nwhich has been corrected in the one that will be on 'pu'.\n\nThanks.\n"},{"id":"282783","messageId":"xmqqwpoawpmq.fsf@gitster.mtv.corp.google.com","threadId":"41742","inReplyTo":"CA+55aFz7309BkfHjD5H7tp9WE0yf1VWncxfmB3hgimJ00fbT-Q@mail.gmail.com","subject":"Re: [PATCH] merge: refuse to create too cool a merge by default","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-04-06T18:36:45Z","receivedAt":"2016-04-06T18:36:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@linux-foundation.org> writes:\n\n> On Fri, Mar 18, 2016 at 1:21 PM, Junio C Hamano <gitster@pobox.com> wrote:\n>> While it makes sense to allow merging unrelated histories of two\n>> projects that started independently into one, in the way \"gitk\" was\n>> merged to \"git\" itself aka \"the coolest merge ever\", such a merge is\n>> still an unusual event.  Worse, if somebody creates an independent\n>> history by starting from a tarball of an established project and\n>> sends a pull request to the original project, \"git merge\" however\n>> happily creates such a merge without any sign of something unusual\n>> is happening.\n>>\n>> Teach \"git merge\" to refuse to create such a merge by default,\n>> unless the user passes a new \"--allow-unrelated-histories\" option to\n>> tell it that the user is aware that two unrelated projects are\n>> merged.\n>\n> Heh. I had a separate set of patches for you, but hadn't sent them out\n> because of the other test failures (which you also worked out).\n\nI was reviewing the topics to merge to 'master', and a thought\ncrossed my mind.  Both of our series only refuse to create a merge\nthat does not have any common ancestor, but shouldn't the right\nsolution refuse to add a new root?  That is, somebody may\n\n - Create a new root by mistake;\n - Pull from you to update, with --allow-unrelated-histories option;\n - Optionally, build more history on top of it; and then finally\n - Ask you to pull without telling you that there is a new root.\n\nWouldn't the \"git pull\" you do in response to this pull request have\na common ancestor (i.e. the tip of what he pulled from you in the\nsecond step) and evade this check?\n"},{"id":"282784","messageId":"CA+55aFy-mb00=KGWghx5XXfkv5dChnncoLoJA07f_2Y_or0FOw@mail.gmail.com","threadId":"41742","inReplyTo":"xmqqwpoawpmq.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH] merge: refuse to create too cool a merge by default","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2016-04-06T18:55:52Z","receivedAt":"2016-04-06T18:55:52Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"On Wed, Apr 6, 2016 at 11:36 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>\n> I was reviewing the topics to merge to 'master', and a thought\n> crossed my mind.  Both of our series only refuse to create a merge\n> that does not have any common ancestor, but shouldn't the right\n> solution refuse to add a new root?\n\nSo I think that's an independent thing, and I think you're right, it\nwould be a good feature to have. As a maintainer, it would have caught\nthe whole \"my submaintainers did something really odd, I need to talk\nto them\" before-the-fact rather than after-the-fact.\n\nThat said, I'm less worried about my submaintainers doing\n_intentionally_ annoying things, than people doing silly things by\nmistake.\n\nSo if I had a version of git that allowed me to say \"don't allow pulls\nthat add a new root commit unless I specify a '--new-root-allowed'\nflag\", then yes, I'd use that. And I guess it might not be too nasty\nto add: it could be done as part of the object checking pass after\ndownloading the pack. Was that what you were thinking of?\n\nBut at the same time, I think the existing series you have, which\nhopefully results in these things not happening by mistake in the\nfuture is the more important piece. I'd rather get good pull requests\nthan get errors and have to tell people \"you screwed up, now we'll\nneed to re-do this\".\n\nBut if you cook something up that checks that there are no new roots\nin the pull, I'd certainly appreciate that safety net.\n\n               Linus\n"},{"id":"282786","messageId":"xmqqshyywnp2.fsf@gitster.mtv.corp.google.com","threadId":"41742","inReplyTo":"CA+55aFy-mb00=KGWghx5XXfkv5dChnncoLoJA07f_2Y_or0FOw@mail.gmail.com","subject":"Re: [PATCH] merge: refuse to create too cool a merge by default","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-04-06T19:18:33Z","receivedAt":"2016-04-06T19:18:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@linux-foundation.org> writes:\n\n> ... And I guess it might not be too nasty\n> to add: it could be done as part of the object checking pass after\n> downloading the pack. Was that what you were thinking of?\n\nNot that fancy, actually.  Running an equivalent of\n\n    git rev-list --max-parents=0 ^HEAD FETCH_HEAD\n\nwas what I had in mind.  This shouldn't be too costly for a normal\ncase (O(N) where N is the number of changes on FETCH_HEAD since it\nforked from you).\n\nIt needs to be done even when FETCH_HEAD is a descendant of HEAD,\n(i.e. when we would have fast forwarded without creating a merge) to\nbe effective, as --no-allow-new-root is about not trusting your\nsubsystem people not doing silly things on purpose, unlike our\noriginal patches.\n"}]}