Subject: Re: [PATCH v2 02/12] fmt-merge-msg: introduce a way to override the main branch name

From: Phillip Wood <[email-masked]>
Date: Mon, 15 Jun 2020 16:00:02 +0100

Hi dscho

On 15/06/2020 13:50, Johannes Schindelin via GitGitGadget wrote:
> From: Johannes Schindelin <[email-masked]>
> 
> There is a growing number of projects and companies desiring to change
> the main branch name of their repositories (see e.g.
> https://twitter.com/mislav/status/1270388510684598272 for background on
> this).

I think this is a good way of phrasing the rationale for the change

> However, there are a couple of hard-coded spots in Git's source code
> that make this endeavor harder than necessary. For example, when
> formatting the commit message for merge commits, Git appends "into
> <branch-name>" unless the current branch is the `master` branch.
> 
> Clearly, this is not what one wants when already having gone through all
> the steps to manually rename the main branch

This didn't quite scan for me maybe s/already having/one has already/ ?

> (and taking care of all the
> fall-out such as re-targeting existing Pull Requests).
> 
> Let's introduce a way to override Git's hard-coded default:
> `core.mainBranch`.
> 
> We will start supporting this config option in the `git fmt-merge-msg`
> command and successively adjust all other places where the main branch
> name is hard-coded.
> 
> Signed-off-by: Johannes Schindelin <[email-masked]>
> ---
>   Documentation/config/core.txt |  5 +++++
>   fmt-merge-msg.c               |  6 ++++--
>   refs.c                        | 27 +++++++++++++++++++++++++++
>   refs.h                        |  7 +++++++
>   t/t6200-fmt-merge-msg.sh      |  7 +++++++
>   5 files changed, 50 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/config/core.txt b/Documentation/config/core.txt
> index 74619a9c03b..32bb5368ebb 100644
> --- a/Documentation/config/core.txt
> +++ b/Documentation/config/core.txt
> @@ -626,3 +626,8 @@ core.abbrev::
>   	in your repository, which hopefully is enough for
>   	abbreviated object names to stay unique for some time.
>   	The minimum length is 4.
> +
> +core.mainBranch::
> +	The name of the main (or: primary) branch in the current repository.
> +	For historical reasons, `master` is used as the fall-back for this
> +	setting.
> diff --git a/fmt-merge-msg.c b/fmt-merge-msg.c
> index 72d32bd73b1..43f4f829242 100644
> --- a/fmt-merge-msg.c
> +++ b/fmt-merge-msg.c
> @@ -407,7 +407,7 @@ static void fmt_merge_msg_title(struct strbuf *out,
>   				const char *current_branch)
>   {
>   	int i = 0;
> -	char *sep = "";
> +	char *sep = "", *main_branch;
>   
>   	strbuf_addstr(out, "Merge ");
>   	for (i = 0; i < srcs.nr; i++) {
> @@ -451,10 +451,12 @@ static void fmt_merge_msg_title(struct strbuf *out,
>   			strbuf_addf(out, " of %s", srcs.items[i].string);
>   	}
>   
> -	if (!strcmp("master", current_branch))
> +	main_branch = git_main_branch_name();
> +	if (!strcmp(main_branch, current_branch))
>   		strbuf_addch(out, '\n');
>   	else
>   		strbuf_addf(out, " into %s\n", current_branch);
> +	free(main_branch);
>   }
>   
>   static void fmt_tag_signature(struct strbuf *tagbuf,
> diff --git a/refs.c b/refs.c
> index 224ff66c7bb..f1854cffa2f 100644
> --- a/refs.c
> +++ b/refs.c
> @@ -560,6 +560,33 @@ void expand_ref_prefix(struct argv_array *prefixes, const char *prefix)
>   		argv_array_pushf(prefixes, *p, len, prefix);
>   }
>   
> +char *repo_main_branch_name(struct repository *r)
> +{
> +	const char *config_key = "core.mainbranch";
> +	const char *config_display_key = "core.mainBranch";
> +	const char *fall_back = "master";
> +	char *name = NULL, *ret;
> +
> +	if (repo_config_get_string(r, config_key, &name) < 0)
> +		die(_("could not retrieve `%s`"), config_display_key);
> +
> +	ret = name ? name : xstrdup(fall_back);
> +
> +	if (check_refname_format(ret, REFNAME_ALLOW_ONELEVEL))
> +		die(_("invalid branch name: %s = %s"),
> +		    config_display_key, name);
> +
> +	if (name != ret)
> +		free(name);

I'm struggling to come up with a scenario where name != NULL && name != 
ret here, however once we get to patch 4 that scenario definitely does 
exist.

> +
> +	return ret;
> +}
> +
> +char *git_main_branch_name(void)
> +{
> +	return repo_main_branch_name(the_repository);
> +}
> +
>   /*
>    * *string and *len will only be substituted, and *string returned (for
>    * later free()ing) if the string passed in is a magic short-hand form
> diff --git a/refs.h b/refs.h
> index a92d2c74c83..a207ef01348 100644
> --- a/refs.h
> +++ b/refs.h
> @@ -154,6 +154,13 @@ int repo_dwim_log(struct repository *r, const char *str, int len, struct object_
>   int dwim_ref(const char *str, int len, struct object_id *oid, char **ref);
>   int dwim_log(const char *str, int len, struct object_id *oid, char **ref);
>   
> +/*
> + * Retrieves the name of the main (or: primary) branch of the given

nit pick, I'm confused by the ':'

Best Wishes

Phillip

> + * repository.
> + */
> +char *git_main_branch_name(void);
> +char *repo_main_branch_name(struct repository *r);
> +
>   /*
>    * A ref_transaction represents a collection of reference updates that
>    * should succeed or fail together.
> diff --git a/t/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh
> index e4c2a6eca43..7a873f4a05c 100755
> --- a/t/t6200-fmt-merge-msg.sh
> +++ b/t/t6200-fmt-merge-msg.sh
> @@ -158,6 +158,13 @@ test_expect_success 'setup FETCH_HEAD' '
>   	git fetch . left
>   '
>   
> +test_expect_success 'with overridden default branch name' '
> +	test_when_finished "git switch master" &&
> +	git switch -c default &&
> +	git -c core.mainBranch=default fmt-merge-msg <.git/FETCH_HEAD >actual &&
> +	! grep "into default" actual
> +'
> +
>   test_expect_success 'merge.log=3 limits shortlog length' '
>   	cat >expected <<-EOF &&
>   	Merge branch ${apos}left${apos}
>