git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH] merge: refuse to create too cool a merge by default

From
Linus Torvalds <torvalds@linux-foundation.org>
Date
Mar 18, 2016, 20:25 UTC
Message-ID
<CA+55aFz7309BkfHjD5H7tp9WE0yf1VWncxfmB3hgimJ00fbT-Q@mail.gmail.com>
In-Reply-To
<xmqqshznpmfe.fsf@gitster.mtv.corp.google.com>
On Fri, Mar 18, 2016 at 1:21 PM, Junio C Hamano <gitster@pobox.com> wrote:
Show 13 quoted lines
> 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 <torvalds@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 <torvalds@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 <torvalds@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 <torvalds@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
Previous: Junio C HamanoNext: Junio C Hamano
Message 2 of 10 in “merge: refuse to create too cool a merge by default”
  1. merge: refuse to create too cool a merge by defaultJunio C Hamano, Mar 18, 2016
  2. Linus TorvaldsMar 18, 2016
  3. Junio C HamanoMar 18, 2016
  4. Junio C HamanoApr 6, 2016
  5. Linus TorvaldsApr 6, 2016
  6. Junio C HamanoApr 6, 2016
  7. Eric SunshineMar 18, 2016
  8. Ramsay JonesMar 18, 2016
  9. David TurnerMar 18, 2016
  10. Junio C HamanoMar 18, 2016

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.