On Fri, Mar 18, 2016 at 1:21 PM, Junio C Hamano <gits...@pobox.com> wrote:
> While it makes sense to allow merging unrelated histories of two
> projects that started independently into one, in the way "gitk" was
> merged to "git" itself aka "the coolest merge ever", such a merge is
> still an unusual event.  Worse, if somebody creates an independent
> history by starting from a tarball of an established project and
> sends a pull request to the original project, "git merge" however
> happily creates such a merge without any sign of something unusual
> is happening.
>
> Teach "git merge" to refuse to create such a merge by default,
> unless the user passes a new "--allow-unrelated-histories" option to
> tell it that the user is aware that two unrelated projects are
> merged.

Heh. I had a separate set of patches for you, but hadn't sent them out
because of the other test failures (which you also worked out).

Mine was slightly different, I just went with a "unrelated" merge option.

I'll attach my two patches anyway, if for no other reason than the
fact that I actually wrote a new test for this.

Feel free to ignore my patches, they have nothing really different
from yours, just slightly different implementation.

                  Linus
From 0f3e4a9294eeda6799e3e50e28809133233126db Mon Sep 17 00:00:00 2001
From: Linus Torvalds <torva...@linux-foundation.org>
Date: Fri, 18 Mar 2016 12:46:06 -0700
Subject: [PATCH 1/2] t3035: test merging of unrelated branches

Right now this succeeds, and the test actually verifies that behavior.

Signed-off-by: Linus Torvalds <torva...@linux-foundation.org>
---
 t/t3035-merge-recursive-across-project.sh | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)
 create mode 100755 t/t3035-merge-recursive-across-project.sh

diff --git a/t/t3035-merge-recursive-across-project.sh b/t/t3035-merge-recursive-across-project.sh
new file mode 100755
index 000000000000..b5d614db6b08
--- /dev/null
+++ b/t/t3035-merge-recursive-across-project.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+test_description='merge-recursive with unrelated projects
+
+Test rename detection by examining rename/delete conflicts.
+
+ * A: file A
+
+ * B: file B
+'
+
+. ./test-lib.sh
+
+test_expect_success 'setup repository' \
+	'echo Hello >A &&
+	 git add A &&
+	 git commit -m "Branch A" A &&
+	 git branch A &&
+	 git mv A B &&
+	 echo Hi >B &&
+	 git commit -m "Branch B" --amend B &&
+	 git branch B'
+
+test_expect_success 'merge unrelated branches' \
+	'git checkout -b merged A &&
+	 git merge B'
+
+test_done
-- 
2.8.0.rc3.9.g44915db

From cd6b2388c73f37b3dd6180d9a42993fd219ebb31 Mon Sep 17 00:00:00 2001
From: Linus Torvalds <torva...@linux-foundation.org>
Date: Fri, 18 Mar 2016 12:57:30 -0700
Subject: [PATCH 2/2] merge: fail merging of unrelated branches

Add test for this, and add the "unrelated" merge option to allow it to succeed.

Signed-off-by: Linus Torvalds <torva...@linux-foundation.org>
---
 merge-recursive.c                         | 6 ++++++
 merge-recursive.h                         | 1 +
 t/t3035-merge-recursive-across-project.sh | 7 +++++--
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/merge-recursive.c b/merge-recursive.c
index b880ae50e7ee..92779db0bbe6 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -1927,6 +1927,9 @@ int merge_recursive(struct merge_options *o,
 		/* if there is no common ancestor, use an empty tree */
 		struct tree *tree;
 
+		if (!o->allow_unrelated)
+			die(_("will not merge unrelated branches"));
+
 		tree = lookup_tree(EMPTY_TREE_SHA1_BIN);
 		merged_common_ancestors = make_virtual_commit(tree, "ancestor");
 	}
@@ -2039,6 +2042,7 @@ void init_merge_options(struct merge_options *o)
 	memset(o, 0, sizeof(struct merge_options));
 	o->verbosity = 2;
 	o->buffer_output = 1;
+	o->allow_unrelated = 0;
 	o->diff_rename_limit = -1;
 	o->merge_rename_limit = -1;
 	o->renormalize = 0;
@@ -2092,6 +2096,8 @@ int parse_merge_opt(struct merge_options *o, const char *s)
 		o->renormalize = 1;
 	else if (!strcmp(s, "no-renormalize"))
 		o->renormalize = 0;
+	else if (!strcmp(s, "unrelated"))
+		o->allow_unrelated = 1;
 	else if (!strcmp(s, "no-renames"))
 		o->detect_rename = 0;
 	else if (!strcmp(s, "find-renames")) {
diff --git a/merge-recursive.h b/merge-recursive.h
index 52f0201f68a3..19eb52eeb732 100644
--- a/merge-recursive.h
+++ b/merge-recursive.h
@@ -15,6 +15,7 @@ struct merge_options {
 	const char *subtree_shift;
 	unsigned buffer_output : 1;
 	unsigned renormalize : 1;
+	unsigned allow_unrelated : 1;
 	long xdl_opts;
 	int verbosity;
 	int detect_rename;
diff --git a/t/t3035-merge-recursive-across-project.sh b/t/t3035-merge-recursive-across-project.sh
index b5d614db6b08..87902f1c8f66 100755
--- a/t/t3035-merge-recursive-across-project.sh
+++ b/t/t3035-merge-recursive-across-project.sh
@@ -21,8 +21,11 @@ test_expect_success 'setup repository' \
 	 git commit -m "Branch B" --amend B &&
 	 git branch B'
 
-test_expect_success 'merge unrelated branches' \
+test_expect_success 'fail merging of unrelated branches' \
 	'git checkout -b merged A &&
-	 git merge B'
+	 test_must_fail git merge B'
+
+test_expect_success 'explicitly merge unrelated branches' \
+	'git merge -Xunrelated B'
 
 test_done
-- 
2.8.0.rc3.9.g44915db

Reply via email to