[PATCH v2] submodule merge: update conflict error message

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When attempting to do a non-fast-forward merge in a project with
conflicts in the submodules, the merge fails and git prints the
following error:

Failed to merge submodule <submodules>
CONFLICT (submodule):Merge conflict in <submodule>
Automatic merge failed; fix conflicts and then commit the result.

Git is left in a conflicted state, which requires the user to:
 1. merge submodules
 2. add submodules changes to the superproject
 3. merge superproject
These steps are non-obvious for newer submodule users to figure out
based on the error message and neither `git submodule status` nor `git
status` provide any useful pointers. 

Update error message to the following when attempting to do a
non-fast-forward merge in a project with conflicts in the submodules.
The error message is based off of what would happen when `merge
--recurse-submodules` is eventually supported

Failed to merge submodule <submodule>
CONFLICT (submodule): Merge conflict in <submodule>
Automatic merge failed; recursive merging with submodules is currently
not supported. To manually complete the merge:
 - go to submodule (<submodule>), and merge commit <commit>
 - come back to superproject, and `git add <submodule>` to record the above merge 
 - resolve any other conflicts in the superproject
 - commit the resulting index in the superproject

Changes since v1:
 - Removed advice to abort merge
 - Error message updated to contain more commit/submodule information

Signed-off-by: Calvin Wan <calvinwan@xxxxxxxxxx>

---
 builtin/merge.c            | 23 ++++++++++++++++++++++-
 merge-ort.c                |  7 ++++++-
 merge-recursive.c          |  7 ++++++-
 merge-recursive.h          |  4 ++++
 t/t6437-submodule-merge.sh |  5 ++++-
 5 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/builtin/merge.c b/builtin/merge.c
index f178f5a3ee..7e2deea7fb 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -88,6 +88,8 @@ static const char *sign_commit;
 static int autostash;
 static int no_verify;
 static char *into_name;
+static struct oid_array conflicted_submodule_oids = OID_ARRAY_INIT;
+static struct string_list conflicted_submodule_paths = STRING_LIST_INIT_DUP;
 
 static struct strategy all_strategy[] = {
 	{ "recursive",  NO_TRIVIAL },
@@ -734,6 +736,8 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
 		}
 
 		init_merge_options(&o, the_repository);
+		o.conflicted_submodule_oids = &conflicted_submodule_oids;
+		o.conflicted_submodule_paths = &conflicted_submodule_paths;
 		if (!strcmp(strategy, "subtree"))
 			o.subtree_shift = "";
 
@@ -973,8 +977,25 @@ static int suggest_conflicts(void)
 	strbuf_release(&msgbuf);
 	fclose(fp);
 	repo_rerere(the_repository, allow_rerere_auto);
-	printf(_("Automatic merge failed; "
+	if (conflicted_submodule_oids.nr > 0) {
+		int i;
+		printf(_("Automatic merge failed; recursive merging with submodules is currently\n"
+			"not supported. To manually complete the merge:\n"));
+		for (i = 0; i < conflicted_submodule_oids.nr; i++) {
+			printf(_(" - go to submodule (%s), and merge commit %s\n"),
+				conflicted_submodule_paths.items[i].string,
+				oid_to_hex(&conflicted_submodule_oids.oid[i]));
+		}
+		printf(_(" - come back to superproject, and `git add"));
+		for (i = 0; i < conflicted_submodule_paths.nr; i++)
+			printf(_(" %s"), conflicted_submodule_paths.items[i].string);
+		printf(_("` to record the above merge \n"
+		" - resolve any other conflicts in the superproject\n"
+		" - commit the resulting index in the superproject\n"));
+	} else {
+		printf(_("Automatic merge failed; "
 			"fix conflicts and then commit the result.\n"));
+	}
 	return 1;
 }
 
diff --git a/merge-ort.c b/merge-ort.c
index 0d3f42592f..c86ee11614 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -3866,8 +3866,13 @@ static void process_entry(struct merge_options *opt,
 			const char *reason = _("content");
 			if (ci->filemask == 6)
 				reason = _("add/add");
-			if (S_ISGITLINK(merged_file.mode))
+			if (S_ISGITLINK(merged_file.mode)) {
 				reason = _("submodule");
+				if (opt->conflicted_submodule_oids && opt->conflicted_submodule_paths) {
+					oid_array_append(opt->conflicted_submodule_oids, &merged_file.oid);
+					string_list_append(opt->conflicted_submodule_paths, path);
+				}
+			}
 			path_msg(opt, path, 0,
 				 _("CONFLICT (%s): Merge conflict in %s"),
 				 reason, path);
diff --git a/merge-recursive.c b/merge-recursive.c
index fd1bbde061..ff7cdbefe9 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -3149,8 +3149,13 @@ static int handle_content_merge(struct merge_file_info *mfi,
 	}
 
 	if (!mfi->clean) {
-		if (S_ISGITLINK(mfi->blob.mode))
+		if (S_ISGITLINK(mfi->blob.mode)) {
 			reason = _("submodule");
+			if (opt->conflicted_submodule_oids && opt->conflicted_submodule_paths) {
+				oid_array_append(opt->conflicted_submodule_oids, &mfi->blob.oid);
+				string_list_append(opt->conflicted_submodule_paths, path);
+			}
+		}
 		output(opt, 1, _("CONFLICT (%s): Merge conflict in %s"),
 				reason, path);
 		if (ci && !df_conflict_remains)
diff --git a/merge-recursive.h b/merge-recursive.h
index b88000e3c2..5d267e7a43 100644
--- a/merge-recursive.h
+++ b/merge-recursive.h
@@ -51,6 +51,10 @@ struct merge_options {
 
 	/* internal fields used by the implementation */
 	struct merge_options_internal *priv;
+
+	/* fields that hold submodule conflict information */
+	struct oid_array *conflicted_submodule_oids;
+	struct string_list *conflicted_submodule_paths;
 };
 
 void init_merge_options(struct merge_options *opt, struct repository *repo);
diff --git a/t/t6437-submodule-merge.sh b/t/t6437-submodule-merge.sh
index 178413c22f..5b384dedc1 100755
--- a/t/t6437-submodule-merge.sh
+++ b/t/t6437-submodule-merge.sh
@@ -141,6 +141,7 @@ test_expect_success 'merging should conflict for non fast-forward' '
 		test_must_fail git merge c 2> actual
 	  fi &&
 	 grep $(cat expect) actual > /dev/null &&
+	 test_i18ngrep "go to submodule (sub), and merge commit $(git -C sub rev-parse sub-b)" actual &&
 	 git reset --hard)
 '
 
@@ -167,6 +168,7 @@ test_expect_success 'merging should fail for ambiguous common parent' '
 	 fi &&
 	grep $(cat expect1) actual > /dev/null &&
 	grep $(cat expect2) actual > /dev/null &&
+	test_i18ngrep "go to submodule (sub), and merge commit $(git -C sub rev-parse sub-b)" actual &&
 	git reset --hard)
 '
 
@@ -205,7 +207,8 @@ test_expect_success 'merging should fail for changes that are backwards' '
 	git commit -a -m "f" &&
 
 	git checkout -b test-backward e &&
-	test_must_fail git merge f)
+	test_must_fail git merge f >actual &&
+	test_i18ngrep "go to submodule (sub), and merge commit $(git -C sub rev-parse sub-a)" actual)
 '
 
 
-- 
2.36.1.476.g0c4daa206d-goog




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux