All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/3] git-merge: update default commit message
@ 2020-02-09 13:16 i.Dark_Templar
  2020-02-09 13:16 ` [RFC PATCH 1/3] git-merge: add option to format default message using multiple lines i.Dark_Templar
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: i.Dark_Templar @ 2020-02-09 13:16 UTC (permalink / raw)
  To: git; +Cc: i.Dark_Templar

This series of patches updates default commit message for git-merge command.

First patch adds alternative commit message formatting where
each merged object is printed on new line and adds configuration option to enable it.

New format may look good for merges with a lot of objects, but
for merge with just one object old format may still look better.
To be able to use both formats, new format type 'autoselect' is added
in patch 2, and configuration option for format selection is reworked.

Patch 3 changes default message formatting to 'autoselect' introduced
in patch 2, thus changing default behaviour of git.

i.Dark_Templar (3):
  git-merge: add option to format default message using multiple lines
  Add merge commit message type autoselect logic
  Enable merge commit message type autoselect logic by default

 Documentation/config/fmt-merge-msg.txt |  13 +++
 builtin/fmt-merge-msg.c                | 127 ++++++++++++++++++++++++-
 2 files changed, 138 insertions(+), 2 deletions(-)

--
2.24.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [RFC PATCH 1/3] git-merge: add option to format default message using multiple lines
  2020-02-09 13:16 [RFC PATCH 0/3] git-merge: update default commit message i.Dark_Templar
@ 2020-02-09 13:16 ` i.Dark_Templar
  2020-02-09 17:44   ` Junio C Hamano
  2020-02-09 13:16 ` [RFC PATCH 2/3] Add merge commit message type autoselect logic i.Dark_Templar
  2020-02-09 13:16 ` [RFC PATCH 3/3] Enable merge commit message type autoselect logic by default i.Dark_Templar
  2 siblings, 1 reply; 11+ messages in thread
From: i.Dark_Templar @ 2020-02-09 13:16 UTC (permalink / raw)
  To: git; +Cc: i.Dark_Templar

If a lot of objects is merged at once, default commit message
could become one very long line, which might be inconvenient to read.
This change implements an option to change default autogenerated message
so it'd take multiple lines, but each line wouldn't be long.

An artificial example.

Original merge commit message:
    Merge branch 'branch_with_some_long_name_1', remote-tracking branch 'clone/remote_branch_with_some_name', tags 'some_tag' and 'some_other_tag'; commit 'ae46a39cead2b42282abce725e90b561c06e94ba'; commit '33d0281e0eeb2a5e9907ebedc230e28c46865092' into merge7

Multiline merge commit message:
    Merge into merge8:
    branch 'branch_with_some_long_name_1'
    remote-tracking branch 'clone/remote_branch_with_some_name'
    tag 'some_tag'
    tag 'some_other_tag'
    commit 'ae46a39cead2b42282abce725e90b561c06e94ba'
    commit '33d0281e0eeb2a5e9907ebedc230e28c46865092'

Signed-off-by: i.Dark_Templar <darktemplar@dark-templar-archives.net>
---
 Documentation/config/fmt-merge-msg.txt |  6 +++
 builtin/fmt-merge-msg.c                | 66 +++++++++++++++++++++++++-
 2 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/Documentation/config/fmt-merge-msg.txt b/Documentation/config/fmt-merge-msg.txt
index c73cfa90b7..8c12540fa7 100644
--- a/Documentation/config/fmt-merge-msg.txt
+++ b/Documentation/config/fmt-merge-msg.txt
@@ -8,3 +8,9 @@ merge.log::
 	most the specified number of one-line descriptions from the
 	actual commits that are being merged.  Defaults to false, and
 	true is a synonym for 20.
+
+merge.multilineMessage::
+	Make default merge commit message multiline. Every merged object
+	will be written using new line. This should ensure that
+	commit message wouldn't become one very long line when
+	there are a lot of merged objects.
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index 05a92c59d8..93d44b59d9 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -20,6 +20,7 @@ static const char * const fmt_merge_msg_usage[] = {
 };
 
 static int use_branch_desc;
+static int use_multiline_default_message = 0;
 
 int fmt_merge_msg_config(const char *key, const char *value, void *cb)
 {
@@ -32,6 +33,8 @@ int fmt_merge_msg_config(const char *key, const char *value, void *cb)
 			merge_log_config = DEFAULT_MERGE_LOG_LEN;
 	} else if (!strcmp(key, "merge.branchdesc")) {
 		use_branch_desc = git_config_bool(key, value);
+	} else if (!strcmp(key, "merge.multilinemessage")) {
+		use_multiline_default_message = git_config_bool(key, value);
 	} else {
 		return git_default_config(key, value, cb);
 	}
@@ -467,6 +470,61 @@ static void fmt_merge_msg_title(struct strbuf *out,
 		strbuf_addf(out, " into %s\n", current_branch);
 }
 
+static void fmt_merge_msg_title_multiline(struct strbuf *out,
+				const char *current_branch)
+{
+	int i = 0;
+	int j = 0;
+
+	if (!strcmp("master", current_branch))
+		strbuf_addstr(out, "Merge:\n");
+	else
+		strbuf_addf(out, "Merge into %s:\n", current_branch);
+
+	for (i = 0; i < srcs.nr; i++) {
+		struct src_data *src_data = srcs.items[i].util;
+		int add_origin = 0;
+
+		if (src_data->head_status == 1) {
+			strbuf_addf(out, "%s\n", srcs.items[i].string);
+			continue;
+		}
+
+		add_origin = strcmp(".", srcs.items[i].string);
+
+		if (src_data->head_status == 3) {
+			if (!add_origin)
+				strbuf_addstr(out, "HEAD\n");
+			else
+				strbuf_addf(out, "HEAD of %s\n", srcs.items[i].string);
+		}
+		for (j = 0; j < src_data->branch.nr; j++) {
+			if (!add_origin)
+				strbuf_addf(out, "branch %s\n", src_data->branch.items[j].string);
+			else
+				strbuf_addf(out, "branch %s of %s\n", src_data->branch.items[j].string, srcs.items[i].string);
+		}
+		for (j = 0; j < src_data->r_branch.nr; j++) {
+			if (!add_origin)
+				strbuf_addf(out, "remote-tracking branch %s\n", src_data->r_branch.items[j].string);
+			else
+				strbuf_addf(out, "remote-tracking branch %s of %s\n", src_data->r_branch.items[j].string, srcs.items[i].string);
+		}
+		for (j = 0; j < src_data->tag.nr; j++) {
+			if (!add_origin)
+				strbuf_addf(out, "tag %s\n", src_data->tag.items[j].string);
+			else
+				strbuf_addf(out, "tag %s of %s\n", src_data->tag.items[j].string, srcs.items[i].string);
+		}
+		for (j = 0; j < src_data->generic.nr; j++) {
+			if (!add_origin)
+				strbuf_addf(out, "commit %s\n", src_data->generic.items[j].string);
+			else
+				strbuf_addf(out, "commit %s of %s\n", src_data->generic.items[j].string, srcs.items[i].string);
+		}
+	}
+}
+
 static void fmt_tag_signature(struct strbuf *tagbuf,
 			      struct strbuf *sig,
 			      const char *buf,
@@ -634,8 +692,12 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
 			die("error in line %d: %.*s", i, len, p);
 	}
 
-	if (opts->add_title && srcs.nr)
-		fmt_merge_msg_title(out, current_branch);
+	if (opts->add_title && srcs.nr) {
+		if (!use_multiline_default_message)
+			fmt_merge_msg_title(out, current_branch);
+		else
+			fmt_merge_msg_title_multiline(out, current_branch);
+	}
 
 	if (origins.nr)
 		fmt_merge_msg_sigs(out);
-- 
2.24.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [RFC PATCH 2/3] Add merge commit message type autoselect logic
  2020-02-09 13:16 [RFC PATCH 0/3] git-merge: update default commit message i.Dark_Templar
  2020-02-09 13:16 ` [RFC PATCH 1/3] git-merge: add option to format default message using multiple lines i.Dark_Templar
@ 2020-02-09 13:16 ` i.Dark_Templar
  2020-02-09 13:16 ` [RFC PATCH 3/3] Enable merge commit message type autoselect logic by default i.Dark_Templar
  2 siblings, 0 replies; 11+ messages in thread
From: i.Dark_Templar @ 2020-02-09 13:16 UTC (permalink / raw)
  To: git; +Cc: i.Dark_Templar

Signed-off-by: i.Dark_Templar <darktemplar@dark-templar-archives.net>
---
 Documentation/config/fmt-merge-msg.txt | 17 ++++--
 builtin/fmt-merge-msg.c                | 71 ++++++++++++++++++++++++--
 2 files changed, 78 insertions(+), 10 deletions(-)

diff --git a/Documentation/config/fmt-merge-msg.txt b/Documentation/config/fmt-merge-msg.txt
index 8c12540fa7..3829095222 100644
--- a/Documentation/config/fmt-merge-msg.txt
+++ b/Documentation/config/fmt-merge-msg.txt
@@ -9,8 +9,15 @@ merge.log::
 	actual commits that are being merged.  Defaults to false, and
 	true is a synonym for 20.
 
-merge.multilineMessage::
-	Make default merge commit message multiline. Every merged object
-	will be written using new line. This should ensure that
-	commit message wouldn't become one very long line when
-	there are a lot of merged objects.
+merge.messageType::
+	Configure default merge commit message type. `original` is used
+	if no value or an invalid value is set.
+	+
+	* `original` keeps old merge commit message format which takes only one line.
+	* `multiline` switches merge commit message to multiline mode. Every merged object
+	will be written using new line. This should ensure that commit message
+	wouldn't become one very long line when there are a lot of merged objects.
+	* `autoselect`, as it's name implies, selects one of following types
+	using arbitrary logic. Currently it selects `original` mode for merge
+	with only one additional object, otherwise switching to `multiline` mode,
+	but this behaviour may be changed in future without any notice.
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index 93d44b59d9..0bc6ce5b05 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -14,13 +14,20 @@
 #include "repository.h"
 #include "commit-reach.h"
 
+enum message_format {
+	MESSAGE_FORMAT_ORIGINAL = 0,
+	MESSAGE_FORMAT_MULTILINE = 1,
+	MESSAGE_FORMAT_AUTOSELECT = 2,
+	MESSAGE_FORMAT_DEFAULT = MESSAGE_FORMAT_ORIGINAL
+};
+
 static const char * const fmt_merge_msg_usage[] = {
 	N_("git fmt-merge-msg [-m <message>] [--log[=<n>] | --no-log] [--file <file>]"),
 	NULL
 };
 
 static int use_branch_desc;
-static int use_multiline_default_message = 0;
+static enum message_format default_message_format = MESSAGE_FORMAT_DEFAULT;
 
 int fmt_merge_msg_config(const char *key, const char *value, void *cb)
 {
@@ -33,8 +40,16 @@ int fmt_merge_msg_config(const char *key, const char *value, void *cb)
 			merge_log_config = DEFAULT_MERGE_LOG_LEN;
 	} else if (!strcmp(key, "merge.branchdesc")) {
 		use_branch_desc = git_config_bool(key, value);
-	} else if (!strcmp(key, "merge.multilinemessage")) {
-		use_multiline_default_message = git_config_bool(key, value);
+	} else if (!strcmp(key, "merge.messagetype")) {
+		if (!value)
+			return config_error_nonbool(key);
+
+		if (!strcmp(value, "autoselect"))
+			default_message_format = MESSAGE_FORMAT_AUTOSELECT;
+		else if (!strcmp(value, "original"))
+			default_message_format = MESSAGE_FORMAT_ORIGINAL;
+		else if (!strcmp(value, "multiline"))
+			default_message_format = MESSAGE_FORMAT_MULTILINE;
 	} else {
 		return git_default_config(key, value, cb);
 	}
@@ -525,6 +540,43 @@ static void fmt_merge_msg_title_multiline(struct strbuf *out,
 	}
 }
 
+static void fmt_merge_msg_title_autoselect(struct strbuf *out,
+				const char *current_branch)
+{
+	int i = 0;
+	int j = 0;
+	int objects_count = 0;
+
+	for (i = 0; i < srcs.nr; i++) {
+		struct src_data *src_data = srcs.items[i].util;
+
+		if (src_data->head_status == 1) {
+			++objects_count;
+			continue;
+		}
+		if (src_data->head_status == 3) {
+			++objects_count;
+		}
+		for (j = 0; j < src_data->branch.nr; j++) {
+			++objects_count;
+		}
+		for (j = 0; j < src_data->r_branch.nr; j++) {
+			++objects_count;
+		}
+		for (j = 0; j < src_data->tag.nr; j++) {
+			++objects_count;
+		}
+		for (j = 0; j < src_data->generic.nr; j++) {
+			++objects_count;
+		}
+	}
+
+	if (objects_count > 1)
+		fmt_merge_msg_title_multiline(out, current_branch);
+	else
+		fmt_merge_msg_title(out, current_branch);
+}
+
 static void fmt_tag_signature(struct strbuf *tagbuf,
 			      struct strbuf *sig,
 			      const char *buf,
@@ -693,10 +745,19 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
 	}
 
 	if (opts->add_title && srcs.nr) {
-		if (!use_multiline_default_message)
+		switch (default_message_format) {
+		case MESSAGE_FORMAT_ORIGINAL:
 			fmt_merge_msg_title(out, current_branch);
-		else
+			break;
+		case MESSAGE_FORMAT_MULTILINE:
 			fmt_merge_msg_title_multiline(out, current_branch);
+			break;
+		case MESSAGE_FORMAT_AUTOSELECT:
+			fmt_merge_msg_title_autoselect(out, current_branch);
+			break;
+		default:
+			BUG("merge.messagetype value is not properly processed: %d", (int) default_message_format);
+		}
 	}
 
 	if (origins.nr)
-- 
2.24.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [RFC PATCH 3/3] Enable merge commit message type autoselect logic by default
  2020-02-09 13:16 [RFC PATCH 0/3] git-merge: update default commit message i.Dark_Templar
  2020-02-09 13:16 ` [RFC PATCH 1/3] git-merge: add option to format default message using multiple lines i.Dark_Templar
  2020-02-09 13:16 ` [RFC PATCH 2/3] Add merge commit message type autoselect logic i.Dark_Templar
@ 2020-02-09 13:16 ` i.Dark_Templar
  2 siblings, 0 replies; 11+ messages in thread
From: i.Dark_Templar @ 2020-02-09 13:16 UTC (permalink / raw)
  To: git; +Cc: i.Dark_Templar

Signed-off-by: i.Dark_Templar <darktemplar@dark-templar-archives.net>
---
 Documentation/config/fmt-merge-msg.txt | 2 +-
 builtin/fmt-merge-msg.c                | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/config/fmt-merge-msg.txt b/Documentation/config/fmt-merge-msg.txt
index 3829095222..acd998cca8 100644
--- a/Documentation/config/fmt-merge-msg.txt
+++ b/Documentation/config/fmt-merge-msg.txt
@@ -10,7 +10,7 @@ merge.log::
 	true is a synonym for 20.
 
 merge.messageType::
-	Configure default merge commit message type. `original` is used
+	Configure default merge commit message type. `autoselect` is used
 	if no value or an invalid value is set.
 	+
 	* `original` keeps old merge commit message format which takes only one line.
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index 0bc6ce5b05..8fa39030d3 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -18,7 +18,7 @@ enum message_format {
 	MESSAGE_FORMAT_ORIGINAL = 0,
 	MESSAGE_FORMAT_MULTILINE = 1,
 	MESSAGE_FORMAT_AUTOSELECT = 2,
-	MESSAGE_FORMAT_DEFAULT = MESSAGE_FORMAT_ORIGINAL
+	MESSAGE_FORMAT_DEFAULT = MESSAGE_FORMAT_AUTOSELECT
 };
 
 static const char * const fmt_merge_msg_usage[] = {
-- 
2.24.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [RFC PATCH 1/3] git-merge: add option to format default message using multiple lines
  2020-02-09 13:16 ` [RFC PATCH 1/3] git-merge: add option to format default message using multiple lines i.Dark_Templar
@ 2020-02-09 17:44   ` Junio C Hamano
  2020-02-10 18:51     ` i.Dark_Templar
  0 siblings, 1 reply; 11+ messages in thread
From: Junio C Hamano @ 2020-02-09 17:44 UTC (permalink / raw)
  To: i.Dark_Templar; +Cc: git

"i.Dark_Templar" <darktemplar@dark-templar-archives.net> writes:

> If a lot of objects is merged at once, default commit message
> could become one very long line, which might be inconvenient to read.
> This change implements an option to change default autogenerated message
> so it'd take multiple lines, but each line wouldn't be long.
> 
> An artificial example.
>
> Original merge commit message:
>     Merge branch 'branch_with_some_long_name_1', remote-tracking branch 'clone/remote_branch_with_some_name', tags 'some_tag' and 'some_other_tag'; commit 'ae46a39cead2b42282abce725e90b561c06e94ba'; commit '33d0281e0eeb2a5e9907ebedc230e28c46865092' into merge7
>
> Multiline merge commit message:
>     Merge into merge8:
>     branch 'branch_with_some_long_name_1'
>     remote-tracking branch 'clone/remote_branch_with_some_name'
>     tag 'some_tag'
>     tag 'some_other_tag'
>     commit 'ae46a39cead2b42282abce725e90b561c06e94ba'
>     commit '33d0281e0eeb2a5e9907ebedc230e28c46865092'


How would these commits appear in the "git shorlog" output?  Losing
some information is OK (after all, you are making the 'title' of the
merge commit less crowded to prefer 'simpler' summary in exchange),
but you'd need to strike a good balance what to discard.  Is the
fact that the name of branch that got some unspecified new things
was 'merge8' the most important thing to convey?

If you make the commit 'title' a short one-line summary, you MUST
have a blank line after that line.  Otherwise, the 'where does the
title of this commit object end?' logic will helpfully merge all the
lines in the first paragraph (i.e. up to the first blank line) into
one long line, defeating your effort to make the summary simpler by
losing details.  That is:

    Merge 6 commits into merge8

    branch 'branch_with_some_long_name_1'
    remote-tracking ...
    ...

That's it for the 'mechanics', i.e. a discussion about how a good
design of this 'feature' should look like.

About the feature itself, I am not sure.  Even though I admit I was
the one who invented octupus merges, and it does make the history
look "pretty" in gitk when used judiciously, its practical benefit
over repeated pairwise merges is doubtful.  Besides, it makes
bisection less efficient.  So from that point of view, I am not sure
if we want a feature to encourage creation of more octopus merges.

I haven't read the code yet---I usually don't before figuring out if
the feature and its design makes sense---so I have no comment on the
actual change at this moment.  I may send a separate review message
later.

Thanks.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC PATCH 1/3] git-merge: add option to format default message using multiple lines
  2020-02-09 17:44   ` Junio C Hamano
@ 2020-02-10 18:51     ` i.Dark_Templar
  2020-03-09 12:07       ` [RFC PATCH v2 0/2] git-merge: update default commit message i.Dark_Templar
  0 siblings, 1 reply; 11+ messages in thread
From: i.Dark_Templar @ 2020-02-10 18:51 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

09.02.2020 20:44, Junio C Hamano пишет:
> "i.Dark_Templar" <darktemplar@dark-templar-archives.net> writes:
> 
>> If a lot of objects is merged at once, default commit message
>> could become one very long line, which might be inconvenient to read.
>> This change implements an option to change default autogenerated message
>> so it'd take multiple lines, but each line wouldn't be long.
>>
>> An artificial example.
>>
>> Original merge commit message:
>>     Merge branch 'branch_with_some_long_name_1', remote-tracking branch 'clone/remote_branch_with_some_name', tags 'some_tag' and 'some_other_tag'; commit 'ae46a39cead2b42282abce725e90b561c06e94ba'; commit '33d0281e0eeb2a5e9907ebedc230e28c46865092' into merge7
>>
>> Multiline merge commit message:
>>     Merge into merge8:
>>     branch 'branch_with_some_long_name_1'
>>     remote-tracking branch 'clone/remote_branch_with_some_name'
>>     tag 'some_tag'
>>     tag 'some_other_tag'
>>     commit 'ae46a39cead2b42282abce725e90b561c06e94ba'
>>     commit '33d0281e0eeb2a5e9907ebedc230e28c46865092'
> 
> 
> How would these commits appear in the "git shorlog" output?  Losing
> some information is OK (after all, you are making the 'title' of the
> merge commit less crowded to prefer 'simpler' summary in exchange),
> but you'd need to strike a good balance what to discard.  Is the
> fact that the name of branch that got some unspecified new things
> was 'merge8' the most important thing to convey?
> 
> If you make the commit 'title' a short one-line summary, you MUST
> have a blank line after that line.  Otherwise, the 'where does the
> title of this commit object end?' logic will helpfully merge all the
> lines in the first paragraph (i.e. up to the first blank line) into
> one long line, defeating your effort to make the summary simpler by
> losing details.  That is:
> 
>     Merge 6 commits into merge8
> 
>     branch 'branch_with_some_long_name_1'
>     remote-tracking ...
>     ...
> 
> That's it for the 'mechanics', i.e. a discussion about how a good
> design of this 'feature' should look like.
> 
> About the feature itself, I am not sure.  Even though I admit I was
> the one who invented octupus merges, and it does make the history
> look "pretty" in gitk when used judiciously, its practical benefit
> over repeated pairwise merges is doubtful.  Besides, it makes
> bisection less efficient.  So from that point of view, I am not sure
> if we want a feature to encourage creation of more octopus merges.
> 
> I haven't read the code yet---I usually don't before figuring out if
> the feature and its design makes sense---so I have no comment on the
> actual change at this moment.  I may send a separate review message
> later.
> 
> Thanks.
> 

Thank you for feedback.

I totally forgot about title in commit message and short log. I think
I'd like to take your suggestion and modify it a bit.
I want to add some text before enumeration of commits into message like
this:

Merge 6 commits into merge8

Following commits are merged:
branch 'branch_with_some_long_name_1'
remote-tracking ...
...

As for octopus merge, there are still some situations where it has some
advantages over series of pairwise merges, although I agree that it
might be uncommon cases. I can name linking multiple previously
unrelated histories as one such case. Bisect could be useless and
history would look better in my opinion.

If this feature would be fine with updated commit message, I'll update
my changes and send updated patch series.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [RFC PATCH v2 0/2] git-merge: update default commit message
  2020-02-10 18:51     ` i.Dark_Templar
@ 2020-03-09 12:07       ` i.Dark_Templar
  2020-03-09 12:07         ` [RFC PATCH v2 1/2] git-merge: add option to format default message using multiple lines i.Dark_Templar
  2020-03-09 12:07         ` [RFC PATCH v2 2/2] Enable multiline merge commit message by default i.Dark_Templar
  0 siblings, 2 replies; 11+ messages in thread
From: i.Dark_Templar @ 2020-03-09 12:07 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, i.Dark_Templar

This series of patches updates default commit message for git-merge command.

First patch adds alternative commit message formatting where
each merged object is printed on new line
and adds configuration option to enable new message formatting
when specified number of merged commits is detected.

This feature is turned off by default in first patch.
Second patch is optional and enables new behaviour
when at least two additional commits are merged.

i.Dark_Templar (2):
  git-merge: add option to format default message using multiple lines
  Enable multiline merge commit message by default

 Documentation/config/fmt-merge-msg.txt |   9 ++
 builtin/fmt-merge-msg.c                | 115 ++++++++++++++++++++++++-
 2 files changed, 122 insertions(+), 2 deletions(-)

--
2.24.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [RFC PATCH v2 1/2] git-merge: add option to format default message using multiple lines
  2020-03-09 12:07       ` [RFC PATCH v2 0/2] git-merge: update default commit message i.Dark_Templar
@ 2020-03-09 12:07         ` i.Dark_Templar
  2020-03-09 16:20           ` Junio C Hamano
  2020-03-09 12:07         ` [RFC PATCH v2 2/2] Enable multiline merge commit message by default i.Dark_Templar
  1 sibling, 1 reply; 11+ messages in thread
From: i.Dark_Templar @ 2020-03-09 12:07 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, i.Dark_Templar

If a lot of objects is merged at once, default commit message
could become one very long line, which might be inconvenient to read.
This change implements an option to change default autogenerated message
so it'd take multiple lines, but each line wouldn't be long.

An artificial example.

Original merge commit message:
    Merge branch 'branch_with_some_long_name_1', remote-tracking branch 'clone/remote_branch_with_some_name', tags 'some_tag' and 'some_other_tag'; commit 'ae46a39cead2b42282abce725e90b561c06e94ba'; commit '33d0281e0eeb2a5e9907ebedc230e28c46865092' into merge7

Multiline merge commit message:
    Merge 6 commits into merge8

    Following commits are merged:
    branch 'branch_with_some_long_name_1'
    remote-tracking branch 'clone/remote_branch_with_some_name'
    tag 'some_tag'
    tag 'some_other_tag'
    commit 'ae46a39cead2b42282abce725e90b561c06e94ba'
    commit '33d0281e0eeb2a5e9907ebedc230e28c46865092'

Signed-off-by: i.Dark_Templar <darktemplar@dark-templar-archives.net>
---
 Documentation/config/fmt-merge-msg.txt |   9 ++
 builtin/fmt-merge-msg.c                | 115 ++++++++++++++++++++++++-
 2 files changed, 122 insertions(+), 2 deletions(-)

diff --git a/Documentation/config/fmt-merge-msg.txt b/Documentation/config/fmt-merge-msg.txt
index c73cfa90b7..7aecf95b68 100644
--- a/Documentation/config/fmt-merge-msg.txt
+++ b/Documentation/config/fmt-merge-msg.txt
@@ -8,3 +8,12 @@ merge.log::
 	most the specified number of one-line descriptions from the
 	actual commits that are being merged.  Defaults to false, and
 	true is a synonym for 20.
+
+merge.usemultiline::
+	Switch merge commit message format to multiline format
+	if merged commits count is greater than or equal to specified
+	value. If specified value is zero or a negative one, this feature
+	is disabled.
+	When multiline commit message format is used, every merged commit
+	will be written using new line. This should ensure that commit message
+	wouldn't become one very long line when there are a lot of merged commits.
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index 736f666f64..191824c962 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -20,6 +20,7 @@ static const char * const fmt_merge_msg_usage[] = {
 };
 
 static int use_branch_desc;
+static int use_multiline = -1;
 
 int fmt_merge_msg_config(const char *key, const char *value, void *cb)
 {
@@ -32,6 +33,8 @@ int fmt_merge_msg_config(const char *key, const char *value, void *cb)
 			merge_log_config = DEFAULT_MERGE_LOG_LEN;
 	} else if (!strcmp(key, "merge.branchdesc")) {
 		use_branch_desc = git_config_bool(key, value);
+	} else if (!strcmp(key, "merge.usemultiline")) {
+		use_multiline = git_config_int(key, value);
 	} else {
 		return git_default_config(key, value, cb);
 	}
@@ -413,6 +416,39 @@ static void shortlog(const char *name,
 	string_list_clear(&subjects, 0);
 }
 
+static int fmt_merge_refs_count(void)
+{
+	int i = 0;
+	int j = 0;
+	int objects_count = 0;
+
+	for (i = 0; i < srcs.nr; i++) {
+		struct src_data *src_data = srcs.items[i].util;
+
+		if (src_data->head_status == 1) {
+			++objects_count;
+			continue;
+		}
+		if (src_data->head_status == 3) {
+			++objects_count;
+		}
+		for (j = 0; j < src_data->branch.nr; j++) {
+			++objects_count;
+		}
+		for (j = 0; j < src_data->r_branch.nr; j++) {
+			++objects_count;
+		}
+		for (j = 0; j < src_data->tag.nr; j++) {
+			++objects_count;
+		}
+		for (j = 0; j < src_data->generic.nr; j++) {
+			++objects_count;
+		}
+	}
+
+	return objects_count;
+}
+
 static void fmt_merge_msg_title(struct strbuf *out,
 				const char *current_branch)
 {
@@ -467,6 +503,68 @@ static void fmt_merge_msg_title(struct strbuf *out,
 		strbuf_addf(out, " into %s\n", current_branch);
 }
 
+static void fmt_merge_msg_title_multiline(struct strbuf *out,
+				const char *current_branch, int count)
+{
+	int i = 0;
+	int j = 0;
+
+	if (!strcmp("master", current_branch))
+		strbuf_addf(out, "Merge %d %s\n", count, (count == 1) ? "commit" : "commits");
+	else
+		strbuf_addf(out, "Merge %d %s into %s\n", count, (count == 1) ? "commit" : "commits", current_branch);
+
+	strbuf_addch(out, '\n');
+
+	if (count == 1)
+		strbuf_addstr(out, "Following commit is merged:\n");
+	else
+		strbuf_addstr(out, "Following commits are merged:\n");
+
+	for (i = 0; i < srcs.nr; i++) {
+		struct src_data *src_data = srcs.items[i].util;
+		int add_origin = 0;
+
+		if (src_data->head_status == 1) {
+			strbuf_addf(out, "%s\n", srcs.items[i].string);
+			continue;
+		}
+
+		add_origin = strcmp(".", srcs.items[i].string);
+
+		if (src_data->head_status == 3) {
+			if (!add_origin)
+				strbuf_addstr(out, "HEAD\n");
+			else
+				strbuf_addf(out, "HEAD of %s\n", srcs.items[i].string);
+		}
+		for (j = 0; j < src_data->branch.nr; j++) {
+			if (!add_origin)
+				strbuf_addf(out, "branch %s\n", src_data->branch.items[j].string);
+			else
+				strbuf_addf(out, "branch %s of %s\n", src_data->branch.items[j].string, srcs.items[i].string);
+		}
+		for (j = 0; j < src_data->r_branch.nr; j++) {
+			if (!add_origin)
+				strbuf_addf(out, "remote-tracking branch %s\n", src_data->r_branch.items[j].string);
+			else
+				strbuf_addf(out, "remote-tracking branch %s of %s\n", src_data->r_branch.items[j].string, srcs.items[i].string);
+		}
+		for (j = 0; j < src_data->tag.nr; j++) {
+			if (!add_origin)
+				strbuf_addf(out, "tag %s\n", src_data->tag.items[j].string);
+			else
+				strbuf_addf(out, "tag %s of %s\n", src_data->tag.items[j].string, srcs.items[i].string);
+		}
+		for (j = 0; j < src_data->generic.nr; j++) {
+			if (!add_origin)
+				strbuf_addf(out, "commit %s\n", src_data->generic.items[j].string);
+			else
+				strbuf_addf(out, "commit %s of %s\n", src_data->generic.items[j].string, srcs.items[i].string);
+		}
+	}
+}
+
 static void fmt_tag_signature(struct strbuf *tagbuf,
 			      struct strbuf *sig,
 			      const char *buf,
@@ -631,8 +729,21 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
 			die("error in line %d: %.*s", i, len, p);
 	}
 
-	if (opts->add_title && srcs.nr)
-		fmt_merge_msg_title(out, current_branch);
+	if (opts->add_title && srcs.nr) {
+		if (use_multiline <= 0) {
+			fmt_merge_msg_title(out, current_branch);
+		} else {
+			int count;
+
+			count = fmt_merge_refs_count();
+
+			if (count >= use_multiline) {
+				fmt_merge_msg_title_multiline(out, current_branch, count);
+			} else {
+				fmt_merge_msg_title(out, current_branch);
+			}
+		}
+	}
 
 	if (origins.nr)
 		fmt_merge_msg_sigs(out);
-- 
2.24.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [RFC PATCH v2 2/2] Enable multiline merge commit message by default
  2020-03-09 12:07       ` [RFC PATCH v2 0/2] git-merge: update default commit message i.Dark_Templar
  2020-03-09 12:07         ` [RFC PATCH v2 1/2] git-merge: add option to format default message using multiple lines i.Dark_Templar
@ 2020-03-09 12:07         ` i.Dark_Templar
  1 sibling, 0 replies; 11+ messages in thread
From: i.Dark_Templar @ 2020-03-09 12:07 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, i.Dark_Templar

Signed-off-by: i.Dark_Templar <darktemplar@dark-templar-archives.net>
---
 builtin/fmt-merge-msg.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index 191824c962..ab445110b0 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -20,7 +20,7 @@ static const char * const fmt_merge_msg_usage[] = {
 };
 
 static int use_branch_desc;
-static int use_multiline = -1;
+static int use_multiline = 2;
 
 int fmt_merge_msg_config(const char *key, const char *value, void *cb)
 {
-- 
2.24.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [RFC PATCH v2 1/2] git-merge: add option to format default message using multiple lines
  2020-03-09 12:07         ` [RFC PATCH v2 1/2] git-merge: add option to format default message using multiple lines i.Dark_Templar
@ 2020-03-09 16:20           ` Junio C Hamano
  2020-03-09 19:45             ` i.Dark_Templar
  0 siblings, 1 reply; 11+ messages in thread
From: Junio C Hamano @ 2020-03-09 16:20 UTC (permalink / raw)
  To: i.Dark_Templar; +Cc: git

"i.Dark_Templar" <darktemplar@dark-templar-archives.net> writes:

> +static int use_multiline = -1;
>  
>  int fmt_merge_msg_config(const char *key, const char *value, void *cb)
>  {
> @@ -32,6 +33,8 @@ int fmt_merge_msg_config(const char *key, const char *value, void *cb)
>  			merge_log_config = DEFAULT_MERGE_LOG_LEN;
>  	} else if (!strcmp(key, "merge.branchdesc")) {
>  		use_branch_desc = git_config_bool(key, value);
> +	} else if (!strcmp(key, "merge.usemultiline")) {
> +		use_multiline = git_config_int(key, value);
>  	} else {
>  		return git_default_config(key, value, cb);
>  	}
> @@ -413,6 +416,39 @@ static void shortlog(const char *name,
>  	string_list_clear(&subjects, 0);
>  }
>  
> +static int fmt_merge_refs_count(void)
> +{
> +	int i = 0;
> +	int j = 0;
> +	int objects_count = 0;

Call it "object_count" and drop "j"; that's shorter.

Also, this is a "STATIC" function, an implementation detail of the
fmt_merge_msg program.  There is no need to repeat that fact by
replicating fmt_merge_ in its name to differenciate with other
things, unlike the functions that are visible from other places.

Just call it "count_srcs()" or something like that and do not use
the word "ref" in its name, as "merging refs" is probably too
ancient, limiting and misleading concept---we do not merge "refs".
We merge commits (and more recently) tags, and "refs" is merely one
of the ways to name these things that are merged.


> +	for (i = 0; i < srcs.nr; i++) {
> +		struct src_data *src_data = srcs.items[i].util;
> +
> +		if (src_data->head_status == 1) {
> +			++objects_count;
> +			continue;
> +		}
> +		if (src_data->head_status == 3) {
> +			++objects_count;
> +		}

This part deserves commenting.  The bit #0 of head_status is special
in that it signals a pull of the default branch (HEAD) of the remote
repository, and it is special because in that case (and only in that
case) none of the string lists in src_data is updated, so the number
of merged heads is one more than the case where the bit #0 is off.

> +		for (j = 0; j < src_data->branch.nr; j++) {
> +			++objects_count;
> +		}
> +		for (j = 0; j < src_data->r_branch.nr; j++) {
> +			++objects_count;
> +		}
> +		for (j = 0; j < src_data->tag.nr; j++) {
> +			++objects_count;
> +		}
> +		for (j = 0; j < src_data->generic.nr; j++) {
> +			++objects_count;
> +		}

Isn't it sufficient to add .nr to object_count?  Why increment
object_count by one as many times as j counts up from 0 to .nr?

If the merge involves only the remote HEAD, then the lists are all
empty, isn't it?  I do not see the point of treating the case where
head_status is 3 == 1|2 any special, so the following is sufficient
as the replacement for the above and should be far easier to follow,
no?  Or am I missing something subtle in your version?

		if (src_data->head_status & 01)
			/* 
                         * the set of merged heads includes the
                         * default branch of the remote, aka HEAD,
			 * which is not counted in any of the lists
			 * in src_data.
			 */
			object_count++;

                object_count += (src->data->branch.nr +
                                 src->data->r_branch.nr +
                                 src->data->tag.nr +
                                 src->data->generic.nr);

By the way, if you read the original code, you may have noticed that
our codebase prefers post-increment over pre-increment, when the
difference does not matter (in other words, "a = ++b;" is perfectly
legit; it is just that we do not say "++b;" when "b++;" would do).

> +	}
> +
> +	return objects_count;
> +}
> +
>  static void fmt_merge_msg_title(struct strbuf *out,
>  				const char *current_branch)
>  {
> @@ -467,6 +503,68 @@ static void fmt_merge_msg_title(struct strbuf *out,
>  		strbuf_addf(out, " into %s\n", current_branch);
>  }
>  
> +static void fmt_merge_msg_title_multiline(struct strbuf *out,
> +				const char *current_branch, int count)
> +{
> +	int i = 0;
> +	int j = 0;
> +
> +	if (!strcmp("master", current_branch))
> +		strbuf_addf(out, "Merge %d %s\n", count, (count == 1) ? "commit" : "commits");
> +	else
> +		strbuf_addf(out, "Merge %d %s into %s\n", count, (count == 1) ? "commit" : "commits", current_branch);

Overlong lines.

> +	strbuf_addch(out, '\n');
> +
> +	if (count == 1)
> +		strbuf_addstr(out, "Following commit is merged:\n");
> +	else
> +		strbuf_addstr(out, "Following commits are merged:\n");

The above makes me wonder if you are better off having "if there is
only one, do these things, otherwise do these other things" at the
top level, i.e.

	if (count == 1) {
		strbuf_addstr(out, "Merge 1 commit");
		if (strcmp(current_branch, "master"))
			strbuf_addstr(out, " into %s", current_branch);
		strbuf_addstr(out, "\n\nFollowing commit is ...");
	} else {
		...similarly...
	}

But stepping back a bit, is there a point in handing count==1 case
in this new format in the first place?  Why waste the most precious
information real estate, which is the title line, to say a lot less
informative "merge 1 commit" instead of what topic is merged there?

Also, I am not sure if "Following commits are merged" is a good
message for a few reasons.

 - Obviously, we allow pulling and merging a signed tag and in that
   case, we are merging a tag, not a commit.

 - When we pull a topic branch and nothing else, the above code
   would say "Merge 1 commit", but there may probably be more than
   one commit on the history leading to that commit we are merging
   into our history.


What actually is happening, instead of "merge 1 commit", is that we
are merging one lineage of history, which may have one or more
commits.  The phrase suitable to call the lineage of history may be
"a topic branch", but it may be "a release tag", in which case what
you are merging would be the entire history built while developing
towards that tag that you have been missing.


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC PATCH v2 1/2] git-merge: add option to format default message using multiple lines
  2020-03-09 16:20           ` Junio C Hamano
@ 2020-03-09 19:45             ` i.Dark_Templar
  0 siblings, 0 replies; 11+ messages in thread
From: i.Dark_Templar @ 2020-03-09 19:45 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

Hi

Thank you for your feedback!

09.03.2020 19:20, Junio C Hamano пишет:
> "i.Dark_Templar" <darktemplar@dark-templar-archives.net> writes:
> 
>> +static int use_multiline = -1;
>>  
>>  int fmt_merge_msg_config(const char *key, const char *value, void *cb)
>>  {
>> @@ -32,6 +33,8 @@ int fmt_merge_msg_config(const char *key, const char *value, void *cb)
>>  			merge_log_config = DEFAULT_MERGE_LOG_LEN;
>>  	} else if (!strcmp(key, "merge.branchdesc")) {
>>  		use_branch_desc = git_config_bool(key, value);
>> +	} else if (!strcmp(key, "merge.usemultiline")) {

I'm wondering if this config option name could be improved, but out of
ideas at the moment. Maybe you have some ideas?

>> +		use_multiline = git_config_int(key, value);
>>  	} else {
>>  		return git_default_config(key, value, cb);
>>  	}
>> @@ -413,6 +416,39 @@ static void shortlog(const char *name,
>>  	string_list_clear(&subjects, 0);
>>  }
>>  
>> +static int fmt_merge_refs_count(void)
>> +{
>> +	int i = 0;
>> +	int j = 0;
>> +	int objects_count = 0;
> 
> Call it "object_count" and drop "j"; that's shorter.
> 
> Also, this is a "STATIC" function, an implementation detail of the
> fmt_merge_msg program.  There is no need to repeat that fact by
> replicating fmt_merge_ in its name to differenciate with other
> things, unlike the functions that are visible from other places.
> 
> Just call it "count_srcs()" or something like that and do not use
> the word "ref" in its name, as "merging refs" is probably too
> ancient, limiting and misleading concept---we do not merge "refs".
> We merge commits (and more recently) tags, and "refs" is merely one
> of the ways to name these things that are merged.
> 
> 

Thanks, I'll rename this function to 'count_srcs'.

>> +	for (i = 0; i < srcs.nr; i++) {
>> +		struct src_data *src_data = srcs.items[i].util;
>> +
>> +		if (src_data->head_status == 1) {
>> +			++objects_count;
>> +			continue;
>> +		}
>> +		if (src_data->head_status == 3) {
>> +			++objects_count;
>> +		}
> 
> This part deserves commenting.  The bit #0 of head_status is special
> in that it signals a pull of the default branch (HEAD) of the remote
> repository, and it is special because in that case (and only in that
> case) none of the string lists in src_data is updated, so the number
> of merged heads is one more than the case where the bit #0 is off.
> 

I didn't know about such details. Thanks.

>> +		for (j = 0; j < src_data->branch.nr; j++) {
>> +			++objects_count;
>> +		}
>> +		for (j = 0; j < src_data->r_branch.nr; j++) {
>> +			++objects_count;
>> +		}
>> +		for (j = 0; j < src_data->tag.nr; j++) {
>> +			++objects_count;
>> +		}
>> +		for (j = 0; j < src_data->generic.nr; j++) {
>> +			++objects_count;
>> +		}
> 
> Isn't it sufficient to add .nr to object_count?  Why increment
> object_count by one as many times as j counts up from 0 to .nr?
> 

That's my fault, I overlooked optimization here.

> If the merge involves only the remote HEAD, then the lists are all
> empty, isn't it?  I do not see the point of treating the case where
> head_status is 3 == 1|2 any special, so the following is sufficient
> as the replacement for the above and should be far easier to follow,
> no?  Or am I missing something subtle in your version?
> 
> 		if (src_data->head_status & 01)
> 			/* 
>                          * the set of merged heads includes the
>                          * default branch of the remote, aka HEAD,
> 			 * which is not counted in any of the lists
> 			 * in src_data.
> 			 */
> 			object_count++;
> 
>                 object_count += (src->data->branch.nr +
>                                  src->data->r_branch.nr +
>                                  src->data->tag.nr +
>                                  src->data->generic.nr);
> 
> By the way, if you read the original code, you may have noticed that
> our codebase prefers post-increment over pre-increment, when the
> difference does not matter (in other words, "a = ++b;" is perfectly
> legit; it is just that we do not say "++b;" when "b++;" would do).
> 

I copied behaviour of 'fmt_merge_msg_title' function here. Thanks for
clarifying special cases and optimizing it. I didn't know most of these
details about head_status and branches/tags/etc lists. I'll replace it
with your optimized version.

>> +	}
>> +
>> +	return objects_count;
>> +}
>> +
>>  static void fmt_merge_msg_title(struct strbuf *out,
>>  				const char *current_branch)
>>  {
>> @@ -467,6 +503,68 @@ static void fmt_merge_msg_title(struct strbuf *out,
>>  		strbuf_addf(out, " into %s\n", current_branch);
>>  }
>>  
>> +static void fmt_merge_msg_title_multiline(struct strbuf *out,
>> +				const char *current_branch, int count)
>> +{
>> +	int i = 0;
>> +	int j = 0;
>> +
>> +	if (!strcmp("master", current_branch))
>> +		strbuf_addf(out, "Merge %d %s\n", count, (count == 1) ? "commit" : "commits");
>> +	else
>> +		strbuf_addf(out, "Merge %d %s into %s\n", count, (count == 1) ? "commit" : "commits", current_branch);
> 
> Overlong lines.
> 

Thanks, I'll fix it.

>> +	strbuf_addch(out, '\n');
>> +
>> +	if (count == 1)
>> +		strbuf_addstr(out, "Following commit is merged:\n");
>> +	else
>> +		strbuf_addstr(out, "Following commits are merged:\n");
> 
> The above makes me wonder if you are better off having "if there is
> only one, do these things, otherwise do these other things" at the
> top level, i.e.
> 
> 	if (count == 1) {
> 		strbuf_addstr(out, "Merge 1 commit");
> 		if (strcmp(current_branch, "master"))
> 			strbuf_addstr(out, " into %s", current_branch);
> 		strbuf_addstr(out, "\n\nFollowing commit is ...");
> 	} else {
> 		...similarly...
> 	}
> 
> But stepping back a bit, is there a point in handing count==1 case
> in this new format in the first place?  Why waste the most precious
> information real estate, which is the title line, to say a lot less
> informative "merge 1 commit" instead of what topic is merged there?
> 

By default, this new format is disabled. In patch 2 it's enabled only
when at least 2 new objects are merged. Due to that new message format
shouldn't ever be used with default settings for only 1 merged object,
but user could set new configuration option to '1' and hit this code path.

If such format for just 1 merged object is undesired, I can modify code
and documentation to make sure it turns on only when at least 2 objects
are merged, and get rid of 1 merged object use-case after that.

> Also, I am not sure if "Following commits are merged" is a good
> message for a few reasons.
> 
>  - Obviously, we allow pulling and merging a signed tag and in that
>    case, we are merging a tag, not a commit.
> 
>  - When we pull a topic branch and nothing else, the above code
>    would say "Merge 1 commit", but there may probably be more than
>    one commit on the history leading to that commit we are merging
>    into our history.
> 
> 
> What actually is happening, instead of "merge 1 commit", is that we
> are merging one lineage of history, which may have one or more
> commits.  The phrase suitable to call the lineage of history may be
> "a topic branch", but it may be "a release tag", in which case what
> you are merging would be the entire history built while developing
> towards that tag that you have been missing.
> 

I'll describe a bit why I used a word 'commit' in this code. When
deciding how to name merged objects, I came down to two options: just
'object' or 'commit'. I used 'commit' because 'man git-merge' usually
uses this word. What word would you want to use here instead? An
'object'? 'History'? Something else?

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2020-03-09 19:45 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-09 13:16 [RFC PATCH 0/3] git-merge: update default commit message i.Dark_Templar
2020-02-09 13:16 ` [RFC PATCH 1/3] git-merge: add option to format default message using multiple lines i.Dark_Templar
2020-02-09 17:44   ` Junio C Hamano
2020-02-10 18:51     ` i.Dark_Templar
2020-03-09 12:07       ` [RFC PATCH v2 0/2] git-merge: update default commit message i.Dark_Templar
2020-03-09 12:07         ` [RFC PATCH v2 1/2] git-merge: add option to format default message using multiple lines i.Dark_Templar
2020-03-09 16:20           ` Junio C Hamano
2020-03-09 19:45             ` i.Dark_Templar
2020-03-09 12:07         ` [RFC PATCH v2 2/2] Enable multiline merge commit message by default i.Dark_Templar
2020-02-09 13:16 ` [RFC PATCH 2/3] Add merge commit message type autoselect logic i.Dark_Templar
2020-02-09 13:16 ` [RFC PATCH 3/3] Enable merge commit message type autoselect logic by default i.Dark_Templar

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.