On Fri, Mar 18, 2016 at 1:21 PM, Junio C Hamano <[email protected]> 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 <[email protected]>
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 <[email protected]>
---
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 <[email protected]>
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 <[email protected]>
---
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