Merge branch 'jc/merge-detached-head-name'
The default merge message prepared by "git merge" records the name of the current branch; the name can be overridden with a new option to allow users to pretend a merge is made on a different branch. * jc/merge-detached-head-name: merge: allow to pretend a merge is made into a different branchmaint
						commit
						bb14cfdfd7
					
				|  | @ -9,7 +9,7 @@ git-fmt-merge-msg - Produce a merge commit message | ||||||
| SYNOPSIS | SYNOPSIS | ||||||
| -------- | -------- | ||||||
| [verse] | [verse] | ||||||
| 'git fmt-merge-msg' [-m <message>] [--log[=<n>] | --no-log] | 'git fmt-merge-msg' [-m <message>] [--into-name <branch>] [--log[=<n>] | --no-log] | ||||||
| 'git fmt-merge-msg' [-m <message>] [--log[=<n>] | --no-log] -F <file> | 'git fmt-merge-msg' [-m <message>] [--log[=<n>] | --no-log] -F <file> | ||||||
|  |  | ||||||
| DESCRIPTION | DESCRIPTION | ||||||
|  | @ -44,6 +44,10 @@ OPTIONS | ||||||
| 	Use <message> instead of the branch names for the first line | 	Use <message> instead of the branch names for the first line | ||||||
| 	of the log message.  For use with `--log`. | 	of the log message.  For use with `--log`. | ||||||
|  |  | ||||||
|  | --into-name <branch>:: | ||||||
|  | 	Prepare the merge message as if merging to the branch `<branch>`, | ||||||
|  | 	instead of the name of the real branch to which the merge is made. | ||||||
|  |  | ||||||
| -F <file>:: | -F <file>:: | ||||||
| --file <file>:: | --file <file>:: | ||||||
| 	Take the list of merged objects from <file> instead of | 	Take the list of merged objects from <file> instead of | ||||||
|  |  | ||||||
|  | @ -12,7 +12,8 @@ SYNOPSIS | ||||||
| 'git merge' [-n] [--stat] [--no-commit] [--squash] [--[no-]edit] | 'git merge' [-n] [--stat] [--no-commit] [--squash] [--[no-]edit] | ||||||
| 	[--no-verify] [-s <strategy>] [-X <strategy-option>] [-S[<keyid>]] | 	[--no-verify] [-s <strategy>] [-X <strategy-option>] [-S[<keyid>]] | ||||||
| 	[--[no-]allow-unrelated-histories] | 	[--[no-]allow-unrelated-histories] | ||||||
| 	[--[no-]rerere-autoupdate] [-m <msg>] [-F <file>] [<commit>...] | 	[--[no-]rerere-autoupdate] [-m <msg>] [-F <file>] | ||||||
|  | 	[--into-name <branch>] [<commit>...] | ||||||
| 'git merge' (--continue | --abort | --quit) | 'git merge' (--continue | --abort | --quit) | ||||||
|  |  | ||||||
| DESCRIPTION | DESCRIPTION | ||||||
|  | @ -76,6 +77,11 @@ The 'git fmt-merge-msg' command can be | ||||||
| used to give a good default for automated 'git merge' | used to give a good default for automated 'git merge' | ||||||
| invocations. The automated message can include the branch description. | invocations. The automated message can include the branch description. | ||||||
|  |  | ||||||
|  | --into-name <branch>:: | ||||||
|  | 	Prepare the default merge message as if merging to the branch | ||||||
|  | 	`<branch>`, instead of the name of the real branch to which | ||||||
|  | 	the merge is made. | ||||||
|  |  | ||||||
| -F <file>:: | -F <file>:: | ||||||
| --file=<file>:: | --file=<file>:: | ||||||
| 	Read the commit message to be used for the merge commit (in | 	Read the commit message to be used for the merge commit (in | ||||||
|  |  | ||||||
|  | @ -12,6 +12,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix) | ||||||
| { | { | ||||||
| 	const char *inpath = NULL; | 	const char *inpath = NULL; | ||||||
| 	const char *message = NULL; | 	const char *message = NULL; | ||||||
|  | 	char *into_name = NULL; | ||||||
| 	int shortlog_len = -1; | 	int shortlog_len = -1; | ||||||
| 	struct option options[] = { | 	struct option options[] = { | ||||||
| 		{ OPTION_INTEGER, 0, "log", &shortlog_len, N_("n"), | 		{ OPTION_INTEGER, 0, "log", &shortlog_len, N_("n"), | ||||||
|  | @ -23,6 +24,8 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix) | ||||||
| 		  DEFAULT_MERGE_LOG_LEN }, | 		  DEFAULT_MERGE_LOG_LEN }, | ||||||
| 		OPT_STRING('m', "message", &message, N_("text"), | 		OPT_STRING('m', "message", &message, N_("text"), | ||||||
| 			N_("use <text> as start of message")), | 			N_("use <text> as start of message")), | ||||||
|  | 		OPT_STRING(0, "into-name", &into_name, N_("name"), | ||||||
|  | 			   N_("use <name> instead of the real target branch")), | ||||||
| 		OPT_FILENAME('F', "file", &inpath, N_("file to read from")), | 		OPT_FILENAME('F', "file", &inpath, N_("file to read from")), | ||||||
| 		OPT_END() | 		OPT_END() | ||||||
| 	}; | 	}; | ||||||
|  | @ -56,6 +59,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix) | ||||||
| 	opts.add_title = !message; | 	opts.add_title = !message; | ||||||
| 	opts.credit_people = 1; | 	opts.credit_people = 1; | ||||||
| 	opts.shortlog_len = shortlog_len; | 	opts.shortlog_len = shortlog_len; | ||||||
|  | 	opts.into_name = into_name; | ||||||
|  |  | ||||||
| 	ret = fmt_merge_msg(&input, &output, &opts); | 	ret = fmt_merge_msg(&input, &output, &opts); | ||||||
| 	if (ret) | 	if (ret) | ||||||
|  |  | ||||||
|  | @ -87,6 +87,7 @@ static int signoff; | ||||||
| static const char *sign_commit; | static const char *sign_commit; | ||||||
| static int autostash; | static int autostash; | ||||||
| static int no_verify; | static int no_verify; | ||||||
|  | static char *into_name; | ||||||
|  |  | ||||||
| static struct strategy all_strategy[] = { | static struct strategy all_strategy[] = { | ||||||
| 	{ "recursive",  NO_TRIVIAL }, | 	{ "recursive",  NO_TRIVIAL }, | ||||||
|  | @ -286,6 +287,8 @@ static struct option builtin_merge_options[] = { | ||||||
| 	{ OPTION_LOWLEVEL_CALLBACK, 'F', "file", &merge_msg, N_("path"), | 	{ OPTION_LOWLEVEL_CALLBACK, 'F', "file", &merge_msg, N_("path"), | ||||||
| 		N_("read message from file"), PARSE_OPT_NONEG, | 		N_("read message from file"), PARSE_OPT_NONEG, | ||||||
| 		NULL, 0, option_read_message }, | 		NULL, 0, option_read_message }, | ||||||
|  | 	OPT_STRING(0, "into-name", &into_name, N_("name"), | ||||||
|  | 		   N_("use <name> instead of the real target")), | ||||||
| 	OPT__VERBOSITY(&verbosity), | 	OPT__VERBOSITY(&verbosity), | ||||||
| 	OPT_BOOL(0, "abort", &abort_current_merge, | 	OPT_BOOL(0, "abort", &abort_current_merge, | ||||||
| 		N_("abort the current in-progress merge")), | 		N_("abort the current in-progress merge")), | ||||||
|  | @ -1121,6 +1124,7 @@ static void prepare_merge_message(struct strbuf *merge_names, struct strbuf *mer | ||||||
| 	opts.add_title = !have_message; | 	opts.add_title = !have_message; | ||||||
| 	opts.shortlog_len = shortlog_len; | 	opts.shortlog_len = shortlog_len; | ||||||
| 	opts.credit_people = (0 < option_edit); | 	opts.credit_people = (0 < option_edit); | ||||||
|  | 	opts.into_name = into_name; | ||||||
|  |  | ||||||
| 	fmt_merge_msg(merge_names, merge_msg, &opts); | 	fmt_merge_msg(merge_names, merge_msg, &opts); | ||||||
| 	if (merge_msg->len) | 	if (merge_msg->len) | ||||||
|  |  | ||||||
|  | @ -650,12 +650,15 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out, | ||||||
|  |  | ||||||
| 	memset(&merge_parents, 0, sizeof(merge_parents)); | 	memset(&merge_parents, 0, sizeof(merge_parents)); | ||||||
|  |  | ||||||
| 	/* get current branch */ | 	/* learn the commit that we merge into and the current branch name */ | ||||||
| 	current_branch = current_branch_to_free = | 	current_branch = current_branch_to_free = | ||||||
| 		resolve_refdup("HEAD", RESOLVE_REF_READING, &head_oid, NULL); | 		resolve_refdup("HEAD", RESOLVE_REF_READING, &head_oid, NULL); | ||||||
| 	if (!current_branch) | 	if (!current_branch) | ||||||
| 		die("No current branch"); | 		die("No current branch"); | ||||||
| 	if (starts_with(current_branch, "refs/heads/")) |  | ||||||
|  | 	if (opts->into_name) | ||||||
|  | 		current_branch = opts->into_name; | ||||||
|  | 	else if (starts_with(current_branch, "refs/heads/")) | ||||||
| 		current_branch += 11; | 		current_branch += 11; | ||||||
|  |  | ||||||
| 	find_merge_parents(&merge_parents, in, &head_oid); | 	find_merge_parents(&merge_parents, in, &head_oid); | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ struct fmt_merge_msg_opts { | ||||||
| 	unsigned add_title:1, | 	unsigned add_title:1, | ||||||
| 		credit_people:1; | 		credit_people:1; | ||||||
| 	int shortlog_len; | 	int shortlog_len; | ||||||
|  | 	const char *into_name; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| extern int merge_log_config; | extern int merge_log_config; | ||||||
|  |  | ||||||
|  | @ -633,7 +633,35 @@ test_expect_success 'merge-msg with "merging" an annotated tag' ' | ||||||
| 	test_cmp expected .git/MERGE_MSG | 	test_cmp expected .git/MERGE_MSG | ||||||
| ' | ' | ||||||
|  |  | ||||||
|  | test_expect_success 'merge --into-name=<name>' ' | ||||||
|  | 	test_when_finished "git checkout main" && | ||||||
|  | 	git checkout -B side main && | ||||||
|  | 	git commit --allow-empty -m "One step ahead" && | ||||||
|  |  | ||||||
|  | 	git checkout --detach main && | ||||||
|  | 	git merge --no-ff side && | ||||||
|  | 	git show -s --format="%s" >full.0 && | ||||||
|  | 	head -n1 full.0 >actual && | ||||||
|  | 	# expect that HEAD is shown as-is | ||||||
|  | 	grep -e "Merge branch .side. into HEAD$" actual && | ||||||
|  |  | ||||||
|  | 	git reset --hard main && | ||||||
|  | 	git merge --no-ff --into-name=main side && | ||||||
|  | 	git show -s --format="%s" >full.1 && | ||||||
|  | 	head -n1 full.1 >actual && | ||||||
|  | 	# expect that we pretend to be merging to main, that is suppressed | ||||||
|  | 	grep -e "Merge branch .side.$" actual && | ||||||
|  |  | ||||||
|  | 	git checkout -b throwaway main && | ||||||
|  | 	git merge --no-ff --into-name=main side && | ||||||
|  | 	git show -s --format="%s" >full.2 && | ||||||
|  | 	head -n1 full.2 >actual && | ||||||
|  | 	# expect that we pretend to be merging to main, that is suppressed | ||||||
|  | 	grep -e "Merge branch .side.$" actual | ||||||
|  | ' | ||||||
|  |  | ||||||
| test_expect_success 'merge.suppressDest configuration' ' | test_expect_success 'merge.suppressDest configuration' ' | ||||||
|  | 	test_when_finished "git checkout main" && | ||||||
| 	git checkout -B side main && | 	git checkout -B side main && | ||||||
| 	git commit --allow-empty -m "One step ahead" && | 	git commit --allow-empty -m "One step ahead" && | ||||||
| 	git checkout main && | 	git checkout main && | ||||||
|  | @ -650,7 +678,19 @@ test_expect_success 'merge.suppressDest configuration' ' | ||||||
| 	git -c merge.suppressDest="ma?*[rn]" fmt-merge-msg <.git/FETCH_HEAD >full.3 && | 	git -c merge.suppressDest="ma?*[rn]" fmt-merge-msg <.git/FETCH_HEAD >full.3 && | ||||||
| 	head -n1 full.3 >actual && | 	head -n1 full.3 >actual && | ||||||
| 	grep -e "Merge branch .side." actual && | 	grep -e "Merge branch .side." actual && | ||||||
| 	! grep -e " into main$" actual | 	! grep -e " into main$" actual && | ||||||
|  |  | ||||||
|  | 	git checkout --detach HEAD && | ||||||
|  | 	git -c merge.suppressDest="main" fmt-merge-msg <.git/FETCH_HEAD >full.4 && | ||||||
|  | 	head -n1 full.4 >actual && | ||||||
|  | 	grep -e "Merge branch .side. into HEAD$" actual && | ||||||
|  |  | ||||||
|  | 	git -c merge.suppressDest="main" fmt-merge-msg \ | ||||||
|  | 		--into-name=main <.git/FETCH_HEAD >full.5 && | ||||||
|  | 	head -n1 full.5 >actual && | ||||||
|  | 	grep -e "Merge branch .side." actual && | ||||||
|  | 	! grep -e " into main$" actual && | ||||||
|  | 	! grep -e " into HEAD$" actual | ||||||
| ' | ' | ||||||
|  |  | ||||||
| test_done | test_done | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Junio C Hamano
						Junio C Hamano