threads / patch / 53651

patch, 9 partsAllow overriding the default name of the default branch

Subject: [PATCH 0/9] Allow overriding the default name of the default branch

## tl;dr

180 messages between Jun 10, 2020 and Jul 14, 2020. Diffs are folded; open one to read it.

replies: 179people: 18as markdown or json

Johannes Schindelin via GitGitGadget· Jun 10, 2020, 21:19 UTC · lore

A growing number of open source projects aims to avoid the branch name master due to its negative connotation. See [1] for an existing discussion on this. The links [2], [3], and [4] describe community-driven ways for users to rename their default branches or use template edits to set a new default branch name.

[1] https://lore.kernel.org/git/CAOAHyQwyXC1Z3v7BZAC+Bq6JBaM7FvBenA-1fcqeDV==apdWDg@mail.gmail.com/

[2] https://twitter.com/mislav/status/1270388510684598272

[3] https://www.hanselman.com/blog/EasilyRenameYourGitDefaultBranchFromMasterToMain.aspx

[4] https://github.com/ethomson/retarget_prs

By necessity, existing repositories require a lot of manual work to move away from that branch name, but it should be much easier for new repositories.

This patch series allows overriding the branch name being used for new repositories' main branch. The main way to do this is the new core.defaultBranchName config option. This first patch was contributed by newcomer Dan Goodman-Wilson. Thanks for the contribution!

The other patches follow other places where "master" is hard-coded and use the new git_default_branch_name() method to consume the config option before falling back to "master".

The last patch updates documentation only after the config option is ready to apply to all of these scenarios.

This series DOES NOT change the default automatically, but only provides an opt-in mechanism for interested users. It also presents a way forward for such a transition, if and when we decide to do so. Specifically, the new GIT_TEST_DEFAULT_BRANCH_NAME environment variable could be used to update test scripts on an individual basis instead of all-at-once.

Don Goodman-Wilson (1):
  init: allow overriding the default branch name for new repositories
Johannes Schindelin (8):
  remote: respect `core.defaultBranchName`
  send-pack/transport-helper: respect `core.defaultBranchName`
  testsvn: respect `core.defaultBranchName`
  submodule: use the (possibly overridden) default branch name
  clone: learn about the possibly-configured default branch name
  fmt-merge-msg: learn about the possibly-configured default branch name
  fast-export: respect the possibly-overridden default branch name
  Document how the default branch name can be overridden
 Documentation/config/core.txt |  4 ++++
 builtin/clone.c               | 14 +++++++++++---
 builtin/fast-export.c         | 10 +++++++---
 builtin/init-db.c             |  8 +++++---
 builtin/submodule--helper.c   | 10 ++++++++--
 fmt-merge-msg.c               |  6 ++++--
 refs.c                        | 34 ++++++++++++++++++++++++++++++++++
 refs.h                        |  6 ++++++
 remote-testsvn.c              | 11 ++++++++---
 remote.c                      | 12 ++++++++----
 send-pack.c                   |  6 +++++-
 t/README                      |  4 ++++
 t/t0001-init.sh               | 20 ++++++++++++++++++++
 t/t5609-clone-branch.sh       |  9 +++++++++
 t/t6200-fmt-merge-msg.sh      |  8 ++++++++
 transport-helper.c            |  6 +++++-
 16 files changed, 146 insertions(+), 22 deletions(-)
base-commit: 0313f36c6ebecb3bffe6f15cf25a4883100f0214
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-656%2Fdscho%2Fdefault-branch-name-option-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-656/dscho/default-branch-name-option-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/656
-- 
gitgitgadget
Don Goodman-Wilson via GitGitGadget· Jun 10, 2020, 21:19 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH 1/9] init: allow overriding the default branch name for new repositories

From: Don Goodman-Wilson <don@goodman-wilson.com>

There is a growing number of projects trying to avoid the non-inclusive name `master` in their repositories. For existing repositories, this requires manual work. For new repositories, the only way to do that automatically is by copying all of Git's template directory, then hard-coding the desired default branch name into the `.git/HEAD` file, and then configuring `init.templateDir` to point to those copied template files.

To make this process much less cumbersome, let's introduce support for `core.defaultBranchName`. That way, users won't need to keep their copied template files up to date, and won't interfere with default hooks installed by their administrators.

While at it, also let users set the default branch name via the environment variable `GIT_TEST_DEFAULT_BRANCH_NAME`, in preparation for adjusting Git's test suite to a more inclusive default branch name. As is common in Git, the `GIT_TEST_*` variable takes precedence over the config setting.

Note: we use the prefix `core.` instead of `init.` because we want to
adjust also `git clone`, `git fmt-merge-msg` and other commands over the
course of the next commits to respect this setting.
Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Helped-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Don Goodman-Wilson <don@goodman-wilson.com>
---
 builtin/init-db.c |  8 +++++---
 refs.c            | 34 ++++++++++++++++++++++++++++++++++
 refs.h            |  6 ++++++
 t/t0001-init.sh   | 20 ++++++++++++++++++++
 4 files changed, 65 insertions(+), 3 deletions(-)
Show changes to 4 files +65 −3

builtin/init-db.c, refs.c, refs.h, t/t0001-init.sh

diff --git a/builtin/init-db.c b/builtin/init-db.c
index 0b7222e7188..99792adfd43 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -258,15 +258,17 @@ static int create_default_files(const char *template_path,
 		die("failed to set up refs db: %s", err.buf);
 
 	/*
-	 * Create the default symlink from ".git/HEAD" to the "master"
-	 * branch, if it does not exist yet.
+	 * Create the default symlink from ".git/HEAD" to the default
+	 * branch name, if it does not exist yet.
 	 */
 	path = git_path_buf(&buf, "HEAD");
 	reinit = (!access(path, R_OK)
 		  || readlink(path, junk, sizeof(junk)-1) != -1);
 	if (!reinit) {
-		if (create_symref("HEAD", "refs/heads/master", NULL) < 0)
+		char *default_ref = git_default_branch_name(0);
+		if (create_symref("HEAD", default_ref, NULL) < 0)
 			exit(1);
+		free(default_ref);
 	}
 
 	initialize_repository_version(fmt->hash_algo);
diff --git a/refs.c b/refs.c
index 224ff66c7bb..8499b3865cb 100644
--- a/refs.c
+++ b/refs.c
@@ -560,6 +560,40 @@ void expand_ref_prefix(struct argv_array *prefixes, const char *prefix)
 		argv_array_pushf(prefixes, *p, len, prefix);
 }
 
+char *git_default_branch_name(int short_name)
+{
+	const char *branch_name = getenv("GIT_TEST_DEFAULT_BRANCH_NAME");
+	char *from_config = NULL, *prefixed;
+
+	/*
+	 * If the default branch name was not specified via the environment
+	 * variable GIT_TEST_DEFAULT_BRANCH_NAME, retrieve it from the config
+	 * setting core.defaultBranchName. If neither are set, fall back to the
+	 * hard-coded default.
+	 */
+	if (!branch_name || !*branch_name) {
+		if (git_config_get_string("core.defaultbranchname",
+					  &from_config) < 0)
+			die(_("Could not retrieve `core.defaultBranchName`"));
+
+		if (from_config)
+			branch_name = from_config;
+		else
+			branch_name = "master";
+	}
+
+	if (short_name)
+		return from_config ? from_config : xstrdup(branch_name);
+
+	/* prepend "refs/heads/" to the branch name */
+	prefixed = xstrfmt("refs/heads/%s", branch_name);
+	if (check_refname_format(prefixed, 0))
+		die(_("invalid default branch name: '%s'"), branch_name);
+
+	free(from_config);
+	return prefixed;
+}
+
 /*
  * *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..e8d4f6e2f13 100644
--- a/refs.h
+++ b/refs.h
@@ -154,6 +154,12 @@ 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 default branch. If `short_name` is non-zero, the
+ * branch name will be prefixed with "refs/heads/".
+ */
+char *git_default_branch_name(int short_name);
+
 /*
  * A ref_transaction represents a collection of reference updates that
  * should succeed or fail together.
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index 1edd5aeb8f0..b144cd8f46b 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -464,4 +464,24 @@ test_expect_success MINGW 'redirect std handles' '
 	grep "Needed a single revision" output.txt
 '
 
+test_expect_success 'custom default branch name from config' '
+	git config --global core.defaultbranchname nmb &&
+	GIT_TEST_DEFAULT_BRANCH_NAME= git init custom-config &&
+	git config --global --unset core.defaultbranchname &&
+	git -C custom-config symbolic-ref HEAD >actual &&
+	grep nmb actual
+'
+
+test_expect_success 'custom default branch name from env' '
+	GIT_TEST_DEFAULT_BRANCH_NAME=nmb git init custom-env &&
+	git -C custom-env symbolic-ref HEAD >actual &&
+	grep nmb actual
+'
+
+test_expect_success 'invalid custom default branch name' '
+	test_must_fail env GIT_TEST_DEFAULT_BRANCH_NAME="with space" \
+		git init custom-invalid 2>err &&
+	test_i18ngrep "invalid default branch name" err
+'
+
 test_done
-- 
gitgitgadget
brian m. carlson· Jun 10, 2020, 23:22 UTC · re: Don Goodman-Wilson via GitGitGadget · lore

Re: [PATCH 1/9] init: allow overriding the default branch name for new repositories

On 2020-06-10 at 21:19:22, Don Goodman-Wilson via GitGitGadget wrote:
> +	/* prepend "refs/heads/" to the branch name */
> +	prefixed = xstrfmt("refs/heads/%s", branch_name);
> +	if (check_refname_format(prefixed, 0))
> +		die(_("invalid default branch name: '%s'"), branch_name);

I'm glad to see this part and a check for it in the test below. We wouldn't want a typo to create a broken branch name.

Show 6 quoted lines
> +test_expect_success 'invalid custom default branch name' '
> +	test_must_fail env GIT_TEST_DEFAULT_BRANCH_NAME="with space" \
> +		git init custom-invalid 2>err &&
> +	test_i18ngrep "invalid default branch name" err
> +'
> +
-- 
brian m. carlson: Houston, Texas, US
OpenPGP: https://keybase.io/bk2204
Eric Sunshine· Jun 11, 2020, 00:16 UTC · re: Don Goodman-Wilson via GitGitGadget · lore

Re: [PATCH 1/9] init: allow overriding the default branch name for new repositories

On Wed, Jun 10, 2020 at 5:19 PM Don Goodman-Wilson via GitGitGadget <gitgitgadget@gmail.com> wrote:

Show 11 quoted lines
> [...]
> To make this process much less cumbersome, let's introduce support for
> `core.defaultBranchName`. That way, users won't need to keep their
> copied template files up to date, and won't interfere with default hooks
> installed by their administrators.
> [...]
> Signed-off-by: Don Goodman-Wilson <don@goodman-wilson.com>
> ---
> diff --git a/refs.c b/refs.c
> @@ -560,6 +560,40 @@ void expand_ref_prefix(struct argv_array *prefixes, const char *prefix)
> +                       die(_("Could not retrieve `core.defaultBranchName`"));
Nit: here the error message is capitalized...
> +               if (from_config)
> +                       branch_name = from_config;
> +               else
> +                       branch_name = "master";
Non-actionable nit: could be written:
    branch_name = from_config ? from_config : "master";
> +       }
> +
> +       if (short_name)
> +               return from_config ? from_config : xstrdup(branch_name);

The logic overall is a bit difficult to follow when trying to understand when and when not to duplicate the string and when and when not to free(), but seems to be correct.

> +       /* prepend "refs/heads/" to the branch name */
> +       prefixed = xstrfmt("refs/heads/%s", branch_name);
> +       if (check_refname_format(prefixed, 0))
> +               die(_("invalid default branch name: '%s'"), branch_name);

Here, the error message is not capitalized. It would be nice for both messages to share a common capitalization scheme. These days, we tend to favor _not_ capitalizing error messages, so perhaps remove capitalization from the earlier one.

Show 5 quoted lines
> +/*
> + * Retrieves the name of the default branch. If `short_name` is non-zero, the
> + * branch name will be prefixed with "refs/heads/".
> + */
> +char *git_default_branch_name(int short_name);

Overall, the internal logic regarding duplicating/freeing strings would probably be easier to grok if there were two separate functions:

    char *git_default_branch_name(void);
    char *git_default_ref_name(void);
but that's subjective.
Johannes Schindelin· Jun 11, 2020, 14:09 UTC · re: Eric Sunshine · lore

Re: [PATCH 1/9] init: allow overriding the default branch name for new repositories

Hi Eric,
On Wed, 10 Jun 2020, Eric Sunshine wrote:
Show 15 quoted lines
> On Wed, Jun 10, 2020 at 5:19 PM Don Goodman-Wilson via GitGitGadget
> <gitgitgadget@gmail.com> wrote:
> > [...]
> > To make this process much less cumbersome, let's introduce support for
> > `core.defaultBranchName`. That way, users won't need to keep their
> > copied template files up to date, and won't interfere with default hooks
> > installed by their administrators.
> > [...]
> > Signed-off-by: Don Goodman-Wilson <don@goodman-wilson.com>
> > ---
> > diff --git a/refs.c b/refs.c
> > @@ -560,6 +560,40 @@ void expand_ref_prefix(struct argv_array *prefixes, const char *prefix)
> > +                       die(_("Could not retrieve `core.defaultBranchName`"));
>
> Nit: here the error message is capitalized...
I downcased it...
Show 8 quoted lines
> > +               if (from_config)
> > +                       branch_name = from_config;
> > +               else
> > +                       branch_name = "master";
>
> Non-actionable nit: could be written:
>
>     branch_name = from_config ? from_config : "master";
Good call.
Show 8 quoted lines
> > +       }
> > +
> > +       if (short_name)
> > +               return from_config ? from_config : xstrdup(branch_name);
>
> The logic overall is a bit difficult to follow when trying to
> understand when and when not to duplicate the string and when and when
> not to free(), but seems to be correct.

I agree that it is a bit hard to follow, but then, the function is really short, so I hoped it is okay.

Show 23 quoted lines
> > +       /* prepend "refs/heads/" to the branch name */
> > +       prefixed = xstrfmt("refs/heads/%s", branch_name);
> > +       if (check_refname_format(prefixed, 0))
> > +               die(_("invalid default branch name: '%s'"), branch_name);
>
> Here, the error message is not capitalized. It would be nice for both
> messages to share a common capitalization scheme. These days, we tend
> to favor _not_ capitalizing error messages, so perhaps remove
> capitalization from the earlier one.
>
> > +/*
> > + * Retrieves the name of the default branch. If `short_name` is non-zero, the
> > + * branch name will be prefixed with "refs/heads/".
> > + */
> > +char *git_default_branch_name(int short_name);
>
> Overall, the internal logic regarding duplicating/freeing strings
> would probably be easier to grok if there were two separate functions:
>
>     char *git_default_branch_name(void);
>     char *git_default_ref_name(void);
>
> but that's subjective.
For such a tiny nuance, I'd rather keep it as one function...

Thank you, Dscho

Junio C Hamano· Jun 11, 2020, 15:28 UTC · re: Johannes Schindelin · lore

Re: [PATCH 1/9] init: allow overriding the default branch name for new repositories

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
Show 9 quoted lines
>> Overall, the internal logic regarding duplicating/freeing strings
>> would probably be easier to grok if there were two separate functions:
>>
>>     char *git_default_branch_name(void);
>>     char *git_default_ref_name(void);
>>
>> but that's subjective.
>
> For such a tiny nuance, I'd rather keep it as one function...

And you'd need two functions, default and primary, possibly full and short. Splitting these into two here would mean you'd need four.

Jeff King· Jun 16, 2020, 12:45 UTC · re: Eric Sunshine · lore

Re: [PATCH 1/9] init: allow overriding the default branch name for new repositories

On Wed, Jun 10, 2020 at 08:16:38PM -0400, Eric Sunshine wrote:
Show 13 quoted lines
> > +/*
> > + * Retrieves the name of the default branch. If `short_name` is non-zero, the
> > + * branch name will be prefixed with "refs/heads/".
> > + */
> > +char *git_default_branch_name(int short_name);
> 
> Overall, the internal logic regarding duplicating/freeing strings
> would probably be easier to grok if there were two separate functions:
> 
>     char *git_default_branch_name(void);
>     char *git_default_ref_name(void);
> 
> but that's subjective.

Having seen one of the callers, might it be worth avoiding handing off ownership of the string entirely?

I.e., this comes from a string that's already owned for the lifetime of the process (either the environment, or a string stored by the config machinery). Could we just pass that back (or if we want to be more careful about getenv() lifetimes, we can copy it into a static owned by this function)?

Then all of the callers can stop dealing with the extra free(), and you can do:

  const char *git_default_branch_name(void)
  {
	return skip_prefix("refs/heads/", git_default_ref_name());
  }
-Peff
Jeff King· Jun 16, 2020, 12:47 UTC · re: Jeff King · lore

Re: [PATCH 1/9] init: allow overriding the default branch name for new repositories

On Tue, Jun 16, 2020 at 08:45:02AM -0400, Jeff King wrote:
Show 32 quoted lines
> On Wed, Jun 10, 2020 at 08:16:38PM -0400, Eric Sunshine wrote:
> 
> > > +/*
> > > + * Retrieves the name of the default branch. If `short_name` is non-zero, the
> > > + * branch name will be prefixed with "refs/heads/".
> > > + */
> > > +char *git_default_branch_name(int short_name);
> > 
> > Overall, the internal logic regarding duplicating/freeing strings
> > would probably be easier to grok if there were two separate functions:
> > 
> >     char *git_default_branch_name(void);
> >     char *git_default_ref_name(void);
> > 
> > but that's subjective.
> 
> Having seen one of the callers, might it be worth avoiding handing off
> ownership of the string entirely?
> 
> I.e., this comes from a string that's already owned for the lifetime of
> the process (either the environment, or a string stored by the config
> machinery). Could we just pass that back (or if we want to be more
> careful about getenv() lifetimes, we can copy it into a static owned by
> this function)?
> 
> Then all of the callers can stop dealing with the extra free(), and you
> can do:
> 
>   const char *git_default_branch_name(void)
>   {
> 	return skip_prefix("refs/heads/", git_default_ref_name());
>   }

Actually, one small hiccup is that the config option specifies the branch name, not the ref name. So you really would have to prepare a static-owned copy of it to turn "foo" into "refs/heads/foo" to get the refname.

On the other hand, that would also be a good time to run check_ref_format(). In the patch as-is, the "short" return does not check that the branch is a valid name.

-Peff
Johannes Schindelin· Jun 18, 2020, 13:08 UTC · re: Jeff King · lore

Re: [PATCH 1/9] init: allow overriding the default branch name for new repositories

Hi Peff,
On Tue, 16 Jun 2020, Jeff King wrote:
Show 43 quoted lines
> On Tue, Jun 16, 2020 at 08:45:02AM -0400, Jeff King wrote:
>
> > On Wed, Jun 10, 2020 at 08:16:38PM -0400, Eric Sunshine wrote:
> >
> > > > +/*
> > > > + * Retrieves the name of the default branch. If `short_name` is non-zero, the
> > > > + * branch name will be prefixed with "refs/heads/".
> > > > + */
> > > > +char *git_default_branch_name(int short_name);
> > >
> > > Overall, the internal logic regarding duplicating/freeing strings
> > > would probably be easier to grok if there were two separate functions:
> > >
> > >     char *git_default_branch_name(void);
> > >     char *git_default_ref_name(void);
> > >
> > > but that's subjective.
> >
> > Having seen one of the callers, might it be worth avoiding handing off
> > ownership of the string entirely?
> >
> > I.e., this comes from a string that's already owned for the lifetime of
> > the process (either the environment, or a string stored by the config
> > machinery). Could we just pass that back (or if we want to be more
> > careful about getenv() lifetimes, we can copy it into a static owned by
> > this function)?
> >
> > Then all of the callers can stop dealing with the extra free(), and you
> > can do:
> >
> >   const char *git_default_branch_name(void)
> >   {
> > 	return skip_prefix("refs/heads/", git_default_ref_name());
> >   }
>
> Actually, one small hiccup is that the config option specifies the
> branch name, not the ref name. So you really would have to prepare a
> static-owned copy of it to turn "foo" into "refs/heads/foo" to get the
> refname.
>
> On the other hand, that would also be a good time to run
> check_ref_format(). In the patch as-is, the "short" return does not
> check that the branch is a valid name.
Legit.
I will work on this.

Thanks, Dscho

Johannes Schindelin· Jun 23, 2020, 20:32 UTC · re: Jeff King · lore

Re: [PATCH 1/9] init: allow overriding the default branch name for new repositories

Hi Peff,
On Tue, 16 Jun 2020, Jeff King wrote:
Show 18 quoted lines
> On Wed, Jun 10, 2020 at 08:16:38PM -0400, Eric Sunshine wrote:
>
> > > +/*
> > > + * Retrieves the name of the default branch. If `short_name` is non-zero, the
> > > + * branch name will be prefixed with "refs/heads/".
> > > + */
> > > +char *git_default_branch_name(int short_name);
> >
> > Overall, the internal logic regarding duplicating/freeing strings
> > would probably be easier to grok if there were two separate functions:
> >
> >     char *git_default_branch_name(void);
> >     char *git_default_ref_name(void);
> >
> > but that's subjective.
>
> Having seen one of the callers, might it be worth avoiding handing off
> ownership of the string entirely?

For `git_default_branch_name()`: yes. For `repo_default_branch_name()`, not really, as that is potentially repository-specific.

(Side note: while I cannot really think of a use case where you would want to set `init.defaultBranch` in a repository-local config, there _might_ be use cases for that out there, and it _is_ how our config machinery works.)

Show 13 quoted lines
> I.e., this comes from a string that's already owned for the lifetime of
> the process (either the environment, or a string stored by the config
> machinery). Could we just pass that back (or if we want to be more
> careful about getenv() lifetimes, we can copy it into a static owned by
> this function)?
>
> Then all of the callers can stop dealing with the extra free(), and you
> can do:
>
>   const char *git_default_branch_name(void)
>   {
> 	return skip_prefix("refs/heads/", git_default_ref_name());
>   }

For ease of use, I decided to only ever return the branch name (but check the full ref).

Those callers that actually need the full ref usually also need the branch name, and it is easy enough to call `xstrfmt("refs/heads/%s", ...)`.

It might make the code a bit less efficient (but who cares, it's not like we're setting up a gazillion repositories per second all the time), but quite a bit easier to reason about.

Ciao, Dscho

Phillip Wood· Jun 11, 2020, 09:35 UTC · re: Don Goodman-Wilson via GitGitGadget · lore

Re: [PATCH 1/9] init: allow overriding the default branch name for new repositories

On 10/06/2020 22:19, Don Goodman-Wilson via GitGitGadget wrote:
> From: Don Goodman-Wilson <don@goodman-wilson.com>
> 
> There is a growing number of projects trying to avoid the non-inclusive
> name `master` in their repositories.

I think it would be helpful to explain why 'master' is no-inclusive even if it originates from the concept of a master copy. i.e. it suggests master/slave even if git is not based on that concept.

Have you got some examples of projects that have changed and the names that they are using? I think it would be helpful if we can agree on a replacement for master - if every repository uses a different name for its main branch it adds an extra complication for new contributors to those projects.

 For existing repositories, this
Show 13 quoted lines
> requires manual work. For new repositories, the only way to do that
> automatically is by copying all of Git's template directory, then
> hard-coding the desired default branch name into the `.git/HEAD` file,
> and then configuring `init.templateDir` to point to those copied
> template files.
> 
> To make this process much less cumbersome, let's introduce support for
> `core.defaultBranchName`. That way, users won't need to keep their
> copied template files up to date, and won't interfere with default hooks
> installed by their administrators.
> 
> While at it, also let users set the default branch name via the
> environment variable `GIT_TEST_DEFAULT_BRANCH_NAME`,

I'm not sure we usually promote the use of GIT_TEST_... environment variables outside of the test suite.

Show 76 quoted lines
> in preparation for
> adjusting Git's test suite to a more inclusive default branch name. As
> is common in Git, the `GIT_TEST_*` variable takes precedence over the
> config setting.
> 
> Note: we use the prefix `core.` instead of `init.` because we want to
> adjust also `git clone`, `git fmt-merge-msg` and other commands over the
> course of the next commits to respect this setting.
> 
> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> Helped-by: Derrick Stolee <dstolee@microsoft.com>
> Signed-off-by: Don Goodman-Wilson <don@goodman-wilson.com>
> ---
>  builtin/init-db.c |  8 +++++---
>  refs.c            | 34 ++++++++++++++++++++++++++++++++++
>  refs.h            |  6 ++++++
>  t/t0001-init.sh   | 20 ++++++++++++++++++++
>  4 files changed, 65 insertions(+), 3 deletions(-)
> 
> diff --git a/builtin/init-db.c b/builtin/init-db.c
> index 0b7222e7188..99792adfd43 100644
> --- a/builtin/init-db.c
> +++ b/builtin/init-db.c
> @@ -258,15 +258,17 @@ static int create_default_files(const char *template_path,
>  		die("failed to set up refs db: %s", err.buf);
>  
>  	/*
> -	 * Create the default symlink from ".git/HEAD" to the "master"
> -	 * branch, if it does not exist yet.
> +	 * Create the default symlink from ".git/HEAD" to the default
> +	 * branch name, if it does not exist yet.
>  	 */
>  	path = git_path_buf(&buf, "HEAD");
>  	reinit = (!access(path, R_OK)
>  		  || readlink(path, junk, sizeof(junk)-1) != -1);
>  	if (!reinit) {
> -		if (create_symref("HEAD", "refs/heads/master", NULL) < 0)
> +		char *default_ref = git_default_branch_name(0);
> +		if (create_symref("HEAD", default_ref, NULL) < 0)
>  			exit(1);
> +		free(default_ref);
>  	}
>  
>  	initialize_repository_version(fmt->hash_algo);
> diff --git a/refs.c b/refs.c
> index 224ff66c7bb..8499b3865cb 100644
> --- a/refs.c
> +++ b/refs.c
> @@ -560,6 +560,40 @@ void expand_ref_prefix(struct argv_array *prefixes, const char *prefix)
>  		argv_array_pushf(prefixes, *p, len, prefix);
>  }
>  
> +char *git_default_branch_name(int short_name)
> +{
> +	const char *branch_name = getenv("GIT_TEST_DEFAULT_BRANCH_NAME");
> +	char *from_config = NULL, *prefixed;
> +
> +	/*
> +	 * If the default branch name was not specified via the environment
> +	 * variable GIT_TEST_DEFAULT_BRANCH_NAME, retrieve it from the config
> +	 * setting core.defaultBranchName. If neither are set, fall back to the
> +	 * hard-coded default.
> +	 */
> +	if (!branch_name || !*branch_name) {
> +		if (git_config_get_string("core.defaultbranchname",
> +					  &from_config) < 0)
> +			die(_("Could not retrieve `core.defaultBranchName`"));
> +
> +		if (from_config)
> +			branch_name = from_config;
> +		else
> +			branch_name = "master";
> +	}
> +
> +	if (short_name)
> +		return from_config ? from_config : xstrdup(branch_name);

If short_name is set we return without validating the name is that intentional?

Show 24 quoted lines
> +
> +	/* prepend "refs/heads/" to the branch name */
> +	prefixed = xstrfmt("refs/heads/%s", branch_name);
> +	if (check_refname_format(prefixed, 0))
> +		die(_("invalid default branch name: '%s'"), branch_name);
> +
> +	free(from_config);
> +	return prefixed;
> +}
> +
>  /*
>   * *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..e8d4f6e2f13 100644
> --- a/refs.h
> +++ b/refs.h
> @@ -154,6 +154,12 @@ 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 default branch. If `short_name` is non-zero, the
> + * branch name will be prefixed with "refs/heads/".

Isn't the other way around - the branch name is prefixed with "refs/heads/" if short is zero.

Show 16 quoted lines
> + */
> +char *git_default_branch_name(int short_name);
> +
>  /*
>   * A ref_transaction represents a collection of reference updates that
>   * should succeed or fail together.
> diff --git a/t/t0001-init.sh b/t/t0001-init.sh
> index 1edd5aeb8f0..b144cd8f46b 100755
> --- a/t/t0001-init.sh
> +++ b/t/t0001-init.sh
> @@ -464,4 +464,24 @@ test_expect_success MINGW 'redirect std handles' '
>  	grep "Needed a single revision" output.txt
>  '
>  
> +test_expect_success 'custom default branch name from config' '
> +	git config --global core.defaultbranchname nmb &&

In tests we usually use 'test_config' rather than 'git config' as the former automatically cleans up the config at the end of the test.

Show 8 quoted lines
> +	GIT_TEST_DEFAULT_BRANCH_NAME= git init custom-config &&
> +	git config --global --unset core.defaultbranchname &&
> +	git -C custom-config symbolic-ref HEAD >actual &&
> +	grep nmb actual
> +'
> +
> +test_expect_success 'custom default branch name from env' '
> +	GIT_TEST_DEFAULT_BRANCH_NAME=nmb git init custom-env &&
It would be good to test that this overrides the config setting
Best Wishes
Phillip
Show 12 quoted lines
> +	git -C custom-env symbolic-ref HEAD >actual &&
> +	grep nmb actual
> +'
> +
> +test_expect_success 'invalid custom default branch name' '
> +	test_must_fail env GIT_TEST_DEFAULT_BRANCH_NAME="with space" \
> +		git init custom-invalid 2>err &&
> +	test_i18ngrep "invalid default branch name" err
> +'
> +
>  test_done
> 
Johannes Schindelin· Jun 12, 2020, 11:55 UTC · re: Phillip Wood · lore

Re: [PATCH 1/9] init: allow overriding the default branch name for new repositories

Hi Phillip,
On Thu, 11 Jun 2020, Phillip Wood wrote:
Show 9 quoted lines
> On 10/06/2020 22:19, Don Goodman-Wilson via GitGitGadget wrote:
> > From: Don Goodman-Wilson <don@goodman-wilson.com>
> >
> > There is a growing number of projects trying to avoid the non-inclusive
> > name `master` in their repositories.
>
> I think it would be helpful to explain why 'master' is no-inclusive even
> if it originates from the concept of a master copy. i.e. it suggests
> master/slave even if git is not based on that concept.

Unfortunately, we do not even have that defense: the term `master` was copied from BitKeeper, which firmly uses it in the `master/slave` context. See e.g. https://mail.gnome.org/archives/desktop-devel-list/2019-May/msg00066.html

I added a _brief_ extension to the context to the first commit's commit message. However, I do not want to go into details here because _this_ patch series is only about empowering users to change their default main branch name.

> Have you got some examples of projects that have changed and the names
> that they are using?

Yes, there are plenty examples, and I do not want to pick a tiny subset to demonstrate that. A more useful resource is probably this post: https://www.hanselman.com/blog/EasilyRenameYourGitDefaultBranchFromMasterToMain.aspx

> I think it would be helpful if we can agree on a replacement for master
> - if every repository uses a different name for its main branch it adds
> an extra complication for new contributors to those projects.

Sure, and that's what I thought we'd discuss, too, maybe at the meeting I proposed elsewhere (Emily started a new thread about it: https://lore.kernel.org/git/20200610222719.GE148632@google.com/).

Show 17 quoted lines
> >  For existing repositories, this
> > requires manual work. For new repositories, the only way to do that
> > automatically is by copying all of Git's template directory, then
> > hard-coding the desired default branch name into the `.git/HEAD` file,
> > and then configuring `init.templateDir` to point to those copied
> > template files.
> >
> > To make this process much less cumbersome, let's introduce support for
> > `core.defaultBranchName`. That way, users won't need to keep their
> > copied template files up to date, and won't interfere with default hooks
> > installed by their administrators.
> >
> > While at it, also let users set the default branch name via the
> > environment variable `GIT_TEST_DEFAULT_BRANCH_NAME`,
>
> I'm not sure we usually promote the use of GIT_TEST_... environment
> variables outside of the test suite.

True. Together with Alban's suggestion to make this purely work in the test suite (i.e. not even adjust the C code to respect that environment variable), you convinced me to (re-)move that part of the commit.

Show 35 quoted lines
> > diff --git a/refs.c b/refs.c
> > index 224ff66c7bb..8499b3865cb 100644
> > --- a/refs.c
> > +++ b/refs.c
> > @@ -560,6 +560,40 @@ void expand_ref_prefix(struct argv_array *prefixes, const char *prefix)
> >  		argv_array_pushf(prefixes, *p, len, prefix);
> >  }
> >
> > +char *git_default_branch_name(int short_name)
> > +{
> > +	const char *branch_name = getenv("GIT_TEST_DEFAULT_BRANCH_NAME");
> > +	char *from_config = NULL, *prefixed;
> > +
> > +	/*
> > +	 * If the default branch name was not specified via the environment
> > +	 * variable GIT_TEST_DEFAULT_BRANCH_NAME, retrieve it from the config
> > +	 * setting core.defaultBranchName. If neither are set, fall back to the
> > +	 * hard-coded default.
> > +	 */
> > +	if (!branch_name || !*branch_name) {
> > +		if (git_config_get_string("core.defaultbranchname",
> > +					  &from_config) < 0)
> > +			die(_("Could not retrieve `core.defaultBranchName`"));
> > +
> > +		if (from_config)
> > +			branch_name = from_config;
> > +		else
> > +			branch_name = "master";
> > +	}
> > +
> > +	if (short_name)
> > +		return from_config ? from_config : xstrdup(branch_name);
>
> If short_name is set we return without validating the name is that
> intentional?

No, unintentional. Thank you for pointing this out. It will be fixed in v2 (still working on it).

Show 27 quoted lines
> > +
> > +	/* prepend "refs/heads/" to the branch name */
> > +	prefixed = xstrfmt("refs/heads/%s", branch_name);
> > +	if (check_refname_format(prefixed, 0))
> > +		die(_("invalid default branch name: '%s'"), branch_name);
> > +
> > +	free(from_config);
> > +	return prefixed;
> > +}
> > +
> >  /*
> >   * *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..e8d4f6e2f13 100644
> > --- a/refs.h
> > +++ b/refs.h
> > @@ -154,6 +154,12 @@ 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 default branch. If `short_name` is non-zero, the
> > + * branch name will be prefixed with "refs/heads/".
>
> Isn't the other way around - the branch name is prefixed with
> "refs/heads/" if short is zero.

Absolutely. Thank you for your careful review, I read past this at least half a dozen times.

Show 19 quoted lines
> > + */
> > +char *git_default_branch_name(int short_name);
> > +
> >  /*
> >   * A ref_transaction represents a collection of reference updates that
> >   * should succeed or fail together.
> > diff --git a/t/t0001-init.sh b/t/t0001-init.sh
> > index 1edd5aeb8f0..b144cd8f46b 100755
> > --- a/t/t0001-init.sh
> > +++ b/t/t0001-init.sh
> > @@ -464,4 +464,24 @@ test_expect_success MINGW 'redirect std handles' '
> >  	grep "Needed a single revision" output.txt
> >  '
> >
> > +test_expect_success 'custom default branch name from config' '
> > +	git config --global core.defaultbranchname nmb &&
>
> In tests we usually use 'test_config' rather than 'git config' as the
> former automatically cleans up the config at the end of the test.
Right, and in this instance it is `test_config_global`.
Show 10 quoted lines
> > +	GIT_TEST_DEFAULT_BRANCH_NAME= git init custom-config &&
> > +	git config --global --unset core.defaultbranchname &&
> > +	git -C custom-config symbolic-ref HEAD >actual &&
> > +	grep nmb actual
> > +'
> > +
> > +test_expect_success 'custom default branch name from env' '
> > +	GIT_TEST_DEFAULT_BRANCH_NAME=nmb git init custom-env &&
>
> It would be good to test that this overrides the config setting

Except that we'll make this a thing that is internal to the test suite now. So this test case can go.

Thank you for helping me improve the patch series! Dscho

Junio C Hamano· Jun 12, 2020, 16:51 UTC · re: Johannes Schindelin · lore

Re: [PATCH 1/9] init: allow overriding the default branch name for new repositories

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> I added a _brief_ extension to the context to the first commit's commit
> message. However, I do not want to go into details here because _this_
> patch series is only about empowering users to change their default main
> branch name.
Sensible.

And I do not think the planned follow-up work to rename 'master' to something else needs to be defended with lengthy history lessons.

Sufficiently large part of the user population are unhappy with the use of the word 'master' as the default name of the primary branch in a newly created repository, and the mere fact that we are aware of that is good enough justification to move _away_ from 'master'. In other words, we do not have to explain why 'master' was bad, as it does not have to be bad for everybody to be replaced.

But you need to defend that the new word you picked is something everybody is happy with. That is much harder ;-).

Phillip Wood· Jun 15, 2020, 10:00 UTC · re: Junio C Hamano · lore

Re: [PATCH 1/9] init: allow overriding the default branch name for new repositories

On 12/06/2020 17:51, Junio C Hamano wrote:
Show 15 quoted lines
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
>> I added a _brief_ extension to the context to the first commit's commit
>> message. However, I do not want to go into details here because _this_
>> patch series is only about empowering users to change their default main
>> branch name.
> 
> [...]
> 
> Sufficiently large part of the user population are unhappy with the
> use of the word 'master' as the default name of the primary branch
> in a newly created repository, and the mere fact that we are aware
> of that is good enough justification to move _away_ from 'master'.
> In other words, we do not have to explain why 'master' was bad, as
> it does not have to be bad for everybody to be replaced.

This expresses what I was trying to get at with my comments much more clearly than I managed - Thank you

> 
> But you need to defend that the new word you picked is something
> everybody is happy with.  That is much harder ;-).

Indeed, though I am more optimistic about that having seen a couple of people have indicated that they don't mind too much what we choose so long as it unlikely to cause future problems.

Best Wishes
Phillip
Johannes Schindelin· Jun 14, 2020, 22:00 UTC · re: Junio C Hamano · lore

Re: [PATCH 1/9] init: allow overriding the default branch name for new repositories

Hi Junio,
On Fri, 12 Jun 2020, Junio C Hamano wrote:
Show 11 quoted lines
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > I added a _brief_ extension to the context to the first commit's commit
> > message. However, I do not want to go into details here because _this_
> > patch series is only about empowering users to change their default main
> > branch name.
>
> Sensible.
>
> And I do not think the planned follow-up work to rename 'master' to
> something else needs to be defended with lengthy history lessons.

Yes, I agree. It is probably sufficient to just point at a couple high-profile projects that already made the switch to `main`.

> Sufficiently large part of the user population are unhappy with the
> use of the word 'master' as the default name of the primary branch
> in a newly created repository, and the mere fact that we are aware
> of that is good enough justification to move _away_ from 'master'.

Yes, even Pasky says he regrets the choice of term (see https://twitter.com/xpasky/status/1271477451756056577):

	I picked the names "master" (and "origin") in the early Git tooling
	back in 2005.
	(this probably means you shouldn't give much weight to my name
	preferences :) )
	I have wished many times I would have named them "main" (and
	"upstream") instead.
Show 5 quoted lines
> In other words, we do not have to explain why 'master' was bad, as
> it does not have to be bad for everybody to be replaced.
>
> But you need to defend that the new word you picked is something
> everybody is happy with.  That is much harder ;-).

To be honest, I stopped looking for got arguments in favor of one name after a couple days, and instead focused on the consensus I saw: Chrome [*1*] and node.js [*2*] apparently stated publicly that they want to change their main branches to `main`, and GitLab [*3*] and GitHub [*4*] seem to intend to change the default for new repositories accordingly.

It is not like we have to decide for the community (as we did back in 2005). I am actually quite relieved about that.

Ciao, Dscho

URL *1*: https://twitter.com/Una/status/1271180494944829441 URL *2*: https://github.com/nodejs/node/issues/33864 URL *3*: https://gitlab.com/gitlab-org/gitlab/-/issues/221164 URL *4*: https://twitter.com/natfriedman/status/1271253144442253312 (this is not really a public announcement, I agree, but it is a public Tweet by the CEO)

Alban Gruin· Jun 11, 2020, 10:23 UTC · re: Don Goodman-Wilson via GitGitGadget · lore

Re: [PATCH 1/9] init: allow overriding the default branch name for new repositories

Hi Don & Johannes,
Le 10/06/2020 à 23:19, Don Goodman-Wilson via GitGitGadget a écrit :
Show 21 quoted lines
> From: Don Goodman-Wilson <don@goodman-wilson.com>
> 
> There is a growing number of projects trying to avoid the non-inclusive
> name `master` in their repositories. For existing repositories, this
> requires manual work. For new repositories, the only way to do that
> automatically is by copying all of Git's template directory, then
> hard-coding the desired default branch name into the `.git/HEAD` file,
> and then configuring `init.templateDir` to point to those copied
> template files.
> 
> To make this process much less cumbersome, let's introduce support for
> `core.defaultBranchName`. That way, users won't need to keep their
> copied template files up to date, and won't interfere with default hooks
> installed by their administrators.
> 
> While at it, also let users set the default branch name via the
> environment variable `GIT_TEST_DEFAULT_BRANCH_NAME`, in preparation for
> adjusting Git's test suite to a more inclusive default branch name. As
> is common in Git, the `GIT_TEST_*` variable takes precedence over the
> config setting.
> 

Why adding yet another environment variable instead of relying only on a config option? I understand it's for the tests, but can't we add a shell function in test-lib.sh (and friends) that tries to read `GIT_TEST_DEFAULT_BRANCH_NAME', and, if it exists, sets `core.defaultBranchName'?

Cheers, Alban

Junio C Hamano· Jun 11, 2020, 23:14 UTC · re: Alban Gruin · lore

Re: [PATCH 1/9] init: allow overriding the default branch name for new repositories

Alban Gruin <alban.gruin@gmail.com> writes:
Show 5 quoted lines
> Why adding yet another environment variable instead of relying only on a
> config option?  I understand it's for the tests, but can't we add a
> shell function in test-lib.sh (and friends) that tries to read
> `GIT_TEST_DEFAULT_BRANCH_NAME', and, if it exists, sets
> `core.defaultBranchName'?

Can you produce such a patch that does it cleanly? My knee jerk reaction is that I would suspect that you end up having to touch many places in the t/ scripts, but if you prove otherwise, that would certainly be appreciated.

And no, 
    git () { command git -c core.defaultBranchName=master "$@" }
is not an acceptable solution.
brian m. carlson· Jun 11, 2020, 23:46 UTC · re: Junio C Hamano · lore

Re: [PATCH 1/9] init: allow overriding the default branch name for new repositories

On 2020-06-11 at 23:14:46, Junio C Hamano wrote:
Show 18 quoted lines
> Alban Gruin <alban.gruin@gmail.com> writes:
> 
> > Why adding yet another environment variable instead of relying only on a
> > config option?  I understand it's for the tests, but can't we add a
> > shell function in test-lib.sh (and friends) that tries to read
> > `GIT_TEST_DEFAULT_BRANCH_NAME', and, if it exists, sets
> > `core.defaultBranchName'?
> 
> Can you produce such a patch that does it cleanly?  My knee jerk
> reaction is that I would suspect that you end up having to touch
> many places in the t/ scripts, but if you prove otherwise, that
> would certainly be appreciated.
> 
> And no, 
> 
>     git () { command git -c core.defaultBranchName=master "$@" }
> 
> is not an acceptable solution.

I would also be delighted to see such a solution, but my experience with the SHA-256 work tells me there's unlikely to be one. We do a lot of "git init" operations in random places in the test suite and as a consequence it's very hard to make a change without touching a large number of tests.

If we were writing things today, perhaps we would use a function (e.g., test_init_repo or such) to wrap this case, but we unfortunately didn't think about that and we're stuck with what we have now unless someone retrofits the test suite.

-- 
brian m. carlson: Houston, Texas, US
OpenPGP: https://keybase.io/bk2204
Johannes Schindelin· Jun 12, 2020, 12:45 UTC · re: brian m. carlson · lore

Re: [PATCH 1/9] init: allow overriding the default branch name for new repositories

Hi brian,
On Thu, 11 Jun 2020, brian m. carlson wrote:
Show 25 quoted lines
> On 2020-06-11 at 23:14:46, Junio C Hamano wrote:
> > Alban Gruin <alban.gruin@gmail.com> writes:
> >
> > > Why adding yet another environment variable instead of relying only on a
> > > config option?  I understand it's for the tests, but can't we add a
> > > shell function in test-lib.sh (and friends) that tries to read
> > > `GIT_TEST_DEFAULT_BRANCH_NAME', and, if it exists, sets
> > > `core.defaultBranchName'?
> >
> > Can you produce such a patch that does it cleanly?  My knee jerk
> > reaction is that I would suspect that you end up having to touch
> > many places in the t/ scripts, but if you prove otherwise, that
> > would certainly be appreciated.
> >
> > And no,
> >
> >     git () { command git -c core.defaultBranchName=master "$@" }
> >
> > is not an acceptable solution.
>
> I would also be delighted to see such a solution, but my experience with
> the SHA-256 work tells me there's unlikely to be one.  We do a lot of
> "git init" operations in random places in the test suite and as a
> consequence it's very hard to make a change without touching a large
> number of tests.
That's a valid point, indeed.
> If we were writing things today, perhaps we would use a function (e.g.,
> test_init_repo or such) to wrap this case, but we unfortunately didn't
> think about that and we're stuck with what we have now unless someone
> retrofits the test suite.

There is actually `test_create_repo` (see https://github.com/git/git/blob/v2.27.0/t/test-lib-functions.sh#L1145-L1159):

	# Most tests can use the created repository, but some may need to create
	# more.
	# Usage: test_create_repo <directory>
	test_create_repo () {
		test "$#" = 1 ||
		BUG "not 1 parameter to test-create-repo"
		repo="$1"
		mkdir -p "$repo"
		(
			cd "$repo" || error "Cannot setup test environment"
			"${GIT_TEST_INSTALLED:-$GIT_EXEC_PATH}/git$X" init \
				"--template=$GIT_BUILD_DIR/templates/blt/" >&3 2>&4 ||
			error "cannot run git init -- have you built things yet?"
			mv .git/hooks .git/hooks-disabled
		) || exit
	}
But I agree that few test scripts use it:
	$ git grep 'git init' v2.27.0 -- t/ | wc -l
	765
	$ git grep 'test_create_repo' v2.27.0 -- t/ | wc -l
	296

Ciao, Dscho

Alban Gruin· Jun 13, 2020, 18:01 UTC · re: Junio C Hamano · lore

Re: [PATCH 1/9] init: allow overriding the default branch name for new repositories

Hi Junio,
Le 12/06/2020 à 01:14, Junio C Hamano a écrit :
Show 19 quoted lines
> Alban Gruin <alban.gruin@gmail.com> writes:
> 
>> Why adding yet another environment variable instead of relying only on a
>> config option?  I understand it's for the tests, but can't we add a
>> shell function in test-lib.sh (and friends) that tries to read
>> `GIT_TEST_DEFAULT_BRANCH_NAME', and, if it exists, sets
>> `core.defaultBranchName'?
> 
> Can you produce such a patch that does it cleanly?  My knee jerk
> reaction is that I would suspect that you end up having to touch
> many places in the t/ scripts, but if you prove otherwise, that
> would certainly be appreciated.
> 
> And no, 
> 
>     git () { command git -c core.defaultBranchName=master "$@" }
> 
> is not an acceptable solution.
> 
I wanted to to do something like this:
  if test -n "$GIT_TEST_DEFAULT_BRANCH_NAME";
  then
      git config core.defaultBranchName "$GIT_TEST_DEFAULT_BRANCH_NAME"
  fi

But since we do not have a repository to store the config, it won't work. Sorry for the noise.

Alban
Johannes Schindelin· Jun 14, 2020, 08:57 UTC · re: Alban Gruin · lore

Re: [PATCH 1/9] init: allow overriding the default branch name for new repositories

Hi Alban,
On Sat, 13 Jun 2020, Alban Gruin wrote:
Show 32 quoted lines
> Hi Junio,
>
> Le 12/06/2020 à 01:14, Junio C Hamano a écrit :
> > Alban Gruin <alban.gruin@gmail.com> writes:
> >
> >> Why adding yet another environment variable instead of relying only on a
> >> config option?  I understand it's for the tests, but can't we add a
> >> shell function in test-lib.sh (and friends) that tries to read
> >> `GIT_TEST_DEFAULT_BRANCH_NAME', and, if it exists, sets
> >> `core.defaultBranchName'?
> >
> > Can you produce such a patch that does it cleanly?  My knee jerk
> > reaction is that I would suspect that you end up having to touch
> > many places in the t/ scripts, but if you prove otherwise, that
> > would certainly be appreciated.
> >
> > And no,
> >
> >     git () { command git -c core.defaultBranchName=master "$@" }
> >
> > is not an acceptable solution.
> >
>
> I wanted to to do something like this:
>
>   if test -n "$GIT_TEST_DEFAULT_BRANCH_NAME";
>   then
>       git config core.defaultBranchName "$GIT_TEST_DEFAULT_BRANCH_NAME"
>   fi
>
> But since we do not have a repository to store the config, it won't
> work.  Sorry for the noise.

We actually would have `~/.gitconfig` because `HOME` is set to `t/trash directory.<test-name>/`.

However, that would cause all kinds of issues when test scripts expect the directory to be pristine, containing only `.git/` but not `.gitconfig`.

It was a good idea to bring up; I share brian's sentiment that it would have been nice if it would have worked out.

Ciao, Dscho

Jeff King· Jun 16, 2020, 12:25 UTC · re: Johannes Schindelin · lore

Re: [PATCH 1/9] init: allow overriding the default branch name for new repositories

On Sun, Jun 14, 2020 at 10:57:41AM +0200, Johannes Schindelin wrote:
Show 33 quoted lines
> > >> Why adding yet another environment variable instead of relying only on a
> > >> config option?  I understand it's for the tests, but can't we add a
> > >> shell function in test-lib.sh (and friends) that tries to read
> > >> `GIT_TEST_DEFAULT_BRANCH_NAME', and, if it exists, sets
> > >> `core.defaultBranchName'?
> > >
> > > Can you produce such a patch that does it cleanly?  My knee jerk
> > > reaction is that I would suspect that you end up having to touch
> > > many places in the t/ scripts, but if you prove otherwise, that
> > > would certainly be appreciated.
> > >
> > > And no,
> > >
> > >     git () { command git -c core.defaultBranchName=master "$@" }
> > >
> > > is not an acceptable solution.
> > >
> >
> > I wanted to to do something like this:
> >
> >   if test -n "$GIT_TEST_DEFAULT_BRANCH_NAME";
> >   then
> >       git config core.defaultBranchName "$GIT_TEST_DEFAULT_BRANCH_NAME"
> >   fi
> >
> > But since we do not have a repository to store the config, it won't
> > work.  Sorry for the noise.
> 
> We actually would have `~/.gitconfig` because `HOME` is set to `t/trash
> directory.<test-name>/`.
> 
> However, that would cause all kinds of issues when test scripts expect the
> directory to be pristine, containing only `.git/` but not `.gitconfig`.
Putting:
  GIT_CONFIG_PARAMETERS="'core.defaultBranchName=...'"

into the environment would work (and yes, you need the single quotes embedded in the variable), and solves all of the complaints above. Further "git -c" invocations properly append to it. But:

  - there are a few tests which explicitly tweak that variable
  - it technically changes any tests of "-c" because now we'd never
    cover the case where we start without the variable defined

I think baking in a special environment variable like you have is not so bad. If this did become too common a pattern, though (special test-only environment variables that do have a separate config option), I wouldn't be opposed to a GIT_TEST_CONFIG_PARAMETERS which takes precedence over other config, and comes with a big warning label that it shouldn't be relied upon outside the test suite. That's equally ugly to GIT_TEST_DEFAULT_BRANCH_NAME, but at least solves the problem once for all of them. I'm just not sure we have enough "all of them" to make it worth doing.

-Peff
Johannes Schindelin· Jun 18, 2020, 10:17 UTC · re: Jeff King · lore

Re: [PATCH 1/9] init: allow overriding the default branch name for new repositories

Hi Peff,
On Tue, 16 Jun 2020, Jeff King wrote:
Show 48 quoted lines
> On Sun, Jun 14, 2020 at 10:57:41AM +0200, Johannes Schindelin wrote:
>
> > > >> Why adding yet another environment variable instead of relying only on a
> > > >> config option?  I understand it's for the tests, but can't we add a
> > > >> shell function in test-lib.sh (and friends) that tries to read
> > > >> `GIT_TEST_DEFAULT_BRANCH_NAME', and, if it exists, sets
> > > >> `core.defaultBranchName'?
> > > >
> > > > Can you produce such a patch that does it cleanly?  My knee jerk
> > > > reaction is that I would suspect that you end up having to touch
> > > > many places in the t/ scripts, but if you prove otherwise, that
> > > > would certainly be appreciated.
> > > >
> > > > And no,
> > > >
> > > >     git () { command git -c core.defaultBranchName=master "$@" }
> > > >
> > > > is not an acceptable solution.
> > > >
> > >
> > > I wanted to to do something like this:
> > >
> > >   if test -n "$GIT_TEST_DEFAULT_BRANCH_NAME";
> > >   then
> > >       git config core.defaultBranchName "$GIT_TEST_DEFAULT_BRANCH_NAME"
> > >   fi
> > >
> > > But since we do not have a repository to store the config, it won't
> > > work.  Sorry for the noise.
> >
> > We actually would have `~/.gitconfig` because `HOME` is set to `t/trash
> > directory.<test-name>/`.
> >
> > However, that would cause all kinds of issues when test scripts expect the
> > directory to be pristine, containing only `.git/` but not `.gitconfig`.
>
> Putting:
>
>   GIT_CONFIG_PARAMETERS="'core.defaultBranchName=...'"
>
> into the environment would work (and yes, you need the single quotes
> embedded in the variable), and solves all of the complaints above.
> Further "git -c" invocations properly append to it. But:
>
>   - there are a few tests which explicitly tweak that variable
>
>   - it technically changes any tests of "-c" because now we'd never
>     cover the case where we start without the variable defined
Indeed.
Show 9 quoted lines
> I think baking in a special environment variable like you have is not so
> bad. If this did become too common a pattern, though (special test-only
> environment variables that do have a separate config option), I wouldn't
> be opposed to a GIT_TEST_CONFIG_PARAMETERS which takes precedence over
> other config, and comes with a big warning label that it shouldn't be
> relied upon outside the test suite. That's equally ugly to
> GIT_TEST_DEFAULT_BRANCH_NAME, but at least solves the problem once for
> all of them. I'm just not sure we have enough "all of them" to make it
> worth doing.

FWIW I do not plan on using that variable for a long time. And it is not in this here patch series any longer, so let's discuss it in the future patch contribution of mine.

Thanks, Dscho

Johannes Schindelin via GitGitGadget· Jun 10, 2020, 21:19 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH 3/9] send-pack/transport-helper: respect `core.defaultBranchName`

From: Johannes Schindelin <johannes.schindelin@gmx.de>

When mentioning the default branch name in an error message, we want to go with the preference specified by the user.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 send-pack.c        | 6 +++++-
 transport-helper.c | 6 +++++-
 2 files changed, 10 insertions(+), 2 deletions(-)
Show changes to 2 files +10 −2

send-pack.c, transport-helper.c

diff --git a/send-pack.c b/send-pack.c
index 0abee22283d..f7747bed1c9 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -405,8 +405,12 @@ int send_pack(struct send_pack_args *args,
 	}
 
 	if (!remote_refs) {
+		char *branch_name = git_default_branch_name(1);
+
 		fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
-			"Perhaps you should specify a branch such as 'master'.\n");
+			"Perhaps you should specify a branch such as '%s'.\n",
+			branch_name);
+		free(branch_name);
 		return 0;
 	}
 	if (args->atomic && !atomic_supported)
diff --git a/transport-helper.c b/transport-helper.c
index a46afcb69db..cc8ae5c67ca 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -1044,9 +1044,13 @@ static int push_refs(struct transport *transport,
 	}
 
 	if (!remote_refs) {
+		char *branch_name = git_default_branch_name(1);
+
 		fprintf(stderr,
 			_("No refs in common and none specified; doing nothing.\n"
-			  "Perhaps you should specify a branch such as 'master'.\n"));
+			  "Perhaps you should specify a branch such as '%s'.\n"),
+			branch_name);
+		free(branch_name);
 		return 0;
 	}
 
-- 
gitgitgadget
Johannes Schindelin via GitGitGadget· Jun 10, 2020, 21:19 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH 2/9] remote: respect `core.defaultBranchName`

From: Johannes Schindelin <johannes.schindelin@gmx.de>

When guessing the default branch name of a remote, and there are no refs to guess from, we want to go with the preference specified by the user for the fall-back.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 remote.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
Show changes to remote.c +8 −4
diff --git a/remote.c b/remote.c
index 534c6426f1e..95fa8cc78e0 100644
--- a/remote.c
+++ b/remote.c
@@ -256,7 +256,7 @@ static void read_remotes_file(struct remote *remote)
 
 static void read_branches_file(struct remote *remote)
 {
-	char *frag;
+	char *frag, *default_branch_name = NULL;
 	struct strbuf buf = STRBUF_INIT;
 	FILE *f = fopen_or_warn(git_path("branches/%s", remote->name), "r");
 
@@ -276,7 +276,7 @@ static void read_branches_file(struct remote *remote)
 
 	/*
 	 * The branches file would have URL and optionally
-	 * #branch specified.  The "master" (or specified) branch is
+	 * #branch specified.  The default (or specified) branch is
 	 * fetched and stored in the local branch matching the
 	 * remote name.
 	 */
@@ -284,7 +284,7 @@ static void read_branches_file(struct remote *remote)
 	if (frag)
 		*(frag++) = '\0';
 	else
-		frag = "master";
+		frag = default_branch_name = git_default_branch_name(1);
 
 	add_url_alias(remote, strbuf_detach(&buf, NULL));
 	strbuf_addf(&buf, "refs/heads/%s:refs/heads/%s",
@@ -299,6 +299,7 @@ static void read_branches_file(struct remote *remote)
 	strbuf_addf(&buf, "HEAD:refs/heads/%s", frag);
 	refspec_append(&remote->push, buf.buf);
 	remote->fetch_tags = 1; /* always auto-follow */
+	free(default_branch_name);
 	strbuf_release(&buf);
 }
 
@@ -2099,7 +2100,10 @@ struct ref *guess_remote_head(const struct ref *head,
 
 	/* If refs/heads/master could be right, it is. */
 	if (!all) {
-		r = find_ref_by_name(refs, "refs/heads/master");
+		char *name = git_default_branch_name(0);
+
+		r = find_ref_by_name(refs, name);
+		free(name);
 		if (r && oideq(&r->old_oid, &head->old_oid))
 			return copy_ref(r);
 	}
-- 
gitgitgadget
Jeff King· Jun 16, 2020, 12:35 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH 2/9] remote: respect `core.defaultBranchName`

On Wed, Jun 10, 2020 at 09:19:23PM +0000, Johannes Schindelin via GitGitGadget wrote:
Show 12 quoted lines
> @@ -2099,7 +2100,10 @@ struct ref *guess_remote_head(const struct ref *head,
>  
>  	/* If refs/heads/master could be right, it is. */
>  	if (!all) {
> -		r = find_ref_by_name(refs, "refs/heads/master");
> +		char *name = git_default_branch_name(0);
> +
> +		r = find_ref_by_name(refs, name);
> +		free(name);
>  		if (r && oideq(&r->old_oid, &head->old_oid))
>  			return copy_ref(r);
>  	}
You'd perhaps want to update the comment above, too.

However, I think we should be a bit more lenient on the "reading" side default names. Just because "foo" is _my_ default branch name, does not mean it is the default on the remote side. We cannot know what the other side's default preference is, but in a world where we have 15 years of repos that may have been created with "master", it is probably still a good guess.

I.e., I think this probably ought to check the preferred name, and then fall back to the existing behavior, like:

  if (!all) {
	  char *name;
          /* try the user's preferred default branch name */
	  name = git_default_branch_name(0);
	  r = find_ref_by_name(refs, name);
	  free(name);
	  if (r && oideq(&r->old_oid, &head->old_oid))
	          return copy_ref(r);
	  /* otherwise, try "master", which is the historical default */
	  r = find_ref_by_name(refs, "refs/heads/master");
	  if (r && oideq(&r->old_oid, &head->old_oid))
	          return copy_ref(r);
  }

That will help minimize fallout when git_default_branch_name() changes, either by user config or if we switch the baked-in default. In the latter case, we might also consider hard-coding that as a guess between the user's preferred name and the historical "master".

Hopefully this would not matter _too_ much either way, as most servers would support the symref extension these days. But I still think we should do our best to minimize spots where the user may see a regression.

-Peff
Johannes Schindelin· Jun 18, 2020, 10:21 UTC · re: Jeff King · lore

Re: [PATCH 2/9] remote: respect `core.defaultBranchName`

Hi Peff,
On Tue, 16 Jun 2020, Jeff King wrote:
Show 52 quoted lines
> On Wed, Jun 10, 2020 at 09:19:23PM +0000, Johannes Schindelin via GitGitGadget wrote:
>
> > @@ -2099,7 +2100,10 @@ struct ref *guess_remote_head(const struct ref *head,
> >
> >  	/* If refs/heads/master could be right, it is. */
> >  	if (!all) {
> > -		r = find_ref_by_name(refs, "refs/heads/master");
> > +		char *name = git_default_branch_name(0);
> > +
> > +		r = find_ref_by_name(refs, name);
> > +		free(name);
> >  		if (r && oideq(&r->old_oid, &head->old_oid))
> >  			return copy_ref(r);
> >  	}
>
> You'd perhaps want to update the comment above, too.
>
> However, I think we should be a bit more lenient on the "reading" side
> default names. Just because "foo" is _my_ default branch name, does not
> mean it is the default on the remote side. We cannot know what the other
> side's default preference is, but in a world where we have 15 years of
> repos that may have been created with "master", it is probably still a
> good guess.
>
> I.e., I think this probably ought to check the preferred name, and then
> fall back to the existing behavior, like:
>
>   if (!all) {
> 	  char *name;
>
>           /* try the user's preferred default branch name */
> 	  name = git_default_branch_name(0);
> 	  r = find_ref_by_name(refs, name);
> 	  free(name);
> 	  if (r && oideq(&r->old_oid, &head->old_oid))
> 	          return copy_ref(r);
>
> 	  /* otherwise, try "master", which is the historical default */
> 	  r = find_ref_by_name(refs, "refs/heads/master");
> 	  if (r && oideq(&r->old_oid, &head->old_oid))
> 	          return copy_ref(r);
>   }
>
> That will help minimize fallout when git_default_branch_name() changes,
> either by user config or if we switch the baked-in default. In the
> latter case, we might also consider hard-coding that as a guess between
> the user's preferred name and the historical "master".
>
> Hopefully this would not matter _too_ much either way, as most servers
> would support the symref extension these days. But I still think we
> should do our best to minimize spots where the user may see a
> regression.

Sure, we could just leave this alone, or we can just ditch the special-casing of `master` here.

As you say, this does not affect any modern Git version, and IIRC the code after that special-casing tries to find any remote ref that matches the remote `HEAD`.

So it's not like we _need_ this special-casing, anyway.

Ciao, Dscho

Jeff King· Jun 18, 2020, 11:50 UTC · re: Johannes Schindelin · lore

Re: [PATCH 2/9] remote: respect `core.defaultBranchName`

On Thu, Jun 18, 2020 at 12:21:30PM +0200, Johannes Schindelin wrote:
Show 11 quoted lines
> > Hopefully this would not matter _too_ much either way, as most servers
> > would support the symref extension these days. But I still think we
> > should do our best to minimize spots where the user may see a
> > regression.
> 
> Sure, we could just leave this alone, or we can just ditch the
> special-casing of `master` here.
> 
> As you say, this does not affect any modern Git version, and IIRC the code
> after that special-casing tries to find any remote ref that matches the
> remote `HEAD`.

I think we need to be a little careful with "any modern Git", because a modern client against an old (or perhaps an alternative implementation) server might still use it. I have to imagine it's pretty rare, but I think it's still useful to return _some_ value.

But as you note, even without a symref extension, we already try to guess based on a unique branch. Probably even choosing the first one alphabetically would be reasonable. But I'd rather err on the side of historical compatibility if we can do so easily. Looking for init.mainBranch, followed by master, accomplishes that and isn't many lines of code.

-Peff
Johannes Schindelin· Jun 23, 2020, 21:15 UTC · re: Jeff King · lore

Re: [PATCH 2/9] remote: respect `core.defaultBranchName`

Hi Peff,
On Thu, 18 Jun 2020, Jeff King wrote:
Show 25 quoted lines
> On Thu, Jun 18, 2020 at 12:21:30PM +0200, Johannes Schindelin wrote:
>
> > > Hopefully this would not matter _too_ much either way, as most servers
> > > would support the symref extension these days. But I still think we
> > > should do our best to minimize spots where the user may see a
> > > regression.
> >
> > Sure, we could just leave this alone, or we can just ditch the
> > special-casing of `master` here.
> >
> > As you say, this does not affect any modern Git version, and IIRC the code
> > after that special-casing tries to find any remote ref that matches the
> > remote `HEAD`.
>
> I think we need to be a little careful with "any modern Git", because a
> modern client against an old (or perhaps an alternative implementation)
> server might still use it. I have to imagine it's pretty rare, but I
> think it's still useful to return _some_ value.
>
> But as you note, even without a symref extension, we already try to
> guess based on a unique branch. Probably even choosing the first one
> alphabetically would be reasonable. But I'd rather err on the side of
> historical compatibility if we can do so easily. Looking for
> init.mainBranch, followed by master, accomplishes that and isn't many
> lines of code.

I ended up using `init.defaultBranch` as preference, falling back to `master`, and then falling back to the first ref matching the given commit hash.

That should be safe enough.

Ciao, Dscho

Johannes Schindelin via GitGitGadget· Jun 10, 2020, 21:19 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH 7/9] fmt-merge-msg: learn about the possibly-configured default branch name

From: Johannes Schindelin <johannes.schindelin@gmx.de>

When formatting the commit message for merge commits, Git appends "into <branch-name>" unless the current branch is the default branch.

Now that we can configure what the default branch name should be, we will want to respect that setting in that scenario rather than using the compiled-in default branch name.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 fmt-merge-msg.c          | 6 ++++--
 t/t6200-fmt-merge-msg.sh | 8 ++++++++
 2 files changed, 12 insertions(+), 2 deletions(-)
Show changes to 2 files +12 −2

fmt-merge-msg.c, t/t6200-fmt-merge-msg.sh

diff --git a/fmt-merge-msg.c b/fmt-merge-msg.c
index 72d32bd73b1..5e5c1d86f1c 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 = "", *default_branch_name;
 
 	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))
+	default_branch_name = git_default_branch_name(1);
+	if (!strcmp(default_branch_name, current_branch))
 		strbuf_addch(out, '\n');
 	else
 		strbuf_addf(out, " into %s\n", current_branch);
+	free(default_branch_name);
 }
 
 static void fmt_tag_signature(struct strbuf *tagbuf,
diff --git a/t/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh
index e4c2a6eca43..a23cd157ffd 100755
--- a/t/t6200-fmt-merge-msg.sh
+++ b/t/t6200-fmt-merge-msg.sh
@@ -158,6 +158,14 @@ test_expect_success 'setup FETCH_HEAD' '
 	git fetch . left
 '
 
+test_expect_success 'with overridden default branch name' '
+	test_config core.defaultBranchName default &&
+	test_when_finished "git switch master" &&
+	git switch -c default &&
+	git 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}
-- 
gitgitgadget
Junio C Hamano· Jun 10, 2020, 22:59 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH 7/9] fmt-merge-msg: learn about the possibly-configured default branch name

"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com> writes:

Show 40 quoted lines
> From: Johannes Schindelin <johannes.schindelin@gmx.de>
>
> When formatting the commit message for merge commits, Git appends "into
> <branch-name>" unless the current branch is the default branch.
>
> Now that we can configure what the default branch name should be, we
> will want to respect that setting in that scenario rather than using the
> compiled-in default branch name.
>
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> ---
>  fmt-merge-msg.c          | 6 ++++--
>  t/t6200-fmt-merge-msg.sh | 8 ++++++++
>  2 files changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/fmt-merge-msg.c b/fmt-merge-msg.c
> index 72d32bd73b1..5e5c1d86f1c 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 = "", *default_branch_name;
>  
>  	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))
> +	default_branch_name = git_default_branch_name(1);
> +	if (!strcmp(default_branch_name, current_branch))
>  		strbuf_addch(out, '\n');
>  	else
>  		strbuf_addf(out, " into %s\n", current_branch);
> +	free(default_branch_name);
>  }

Good. J6t reminded me earlier about this one when I said "except for 'init' and 'clone' (when it cannot tell what primary branch the source of the clone uses), we do not need a hardcoded 'master'", and the series covers this case. Very pleased.

Show 20 quoted lines
>  static void fmt_tag_signature(struct strbuf *tagbuf,
> diff --git a/t/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh
> index e4c2a6eca43..a23cd157ffd 100755
> --- a/t/t6200-fmt-merge-msg.sh
> +++ b/t/t6200-fmt-merge-msg.sh
> @@ -158,6 +158,14 @@ test_expect_success 'setup FETCH_HEAD' '
>  	git fetch . left
>  '
>  
> +test_expect_success 'with overridden default branch name' '
> +	test_config core.defaultBranchName default &&
> +	test_when_finished "git switch master" &&
> +	git switch -c default &&
> +	git 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}
Johannes Schindelin via GitGitGadget· Jun 10, 2020, 21:19 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH 6/9] clone: learn about the possibly-configured default branch name

From: Johannes Schindelin <johannes.schindelin@gmx.de>

When cloning a repository without any branches, Git chooses a default branch name for the as-yet unborn branch.

Now that we can configure what the default branch name should be, we will want `git clone` to respect that setting.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 builtin/clone.c         | 14 +++++++++++---
 t/t5609-clone-branch.sh |  9 +++++++++
 2 files changed, 20 insertions(+), 3 deletions(-)
Show changes to 2 files +20 −3

builtin/clone.c, t/t5609-clone-branch.sh

diff --git a/builtin/clone.c b/builtin/clone.c
index cb48a291caf..a21d3e99f82 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1263,9 +1263,17 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		remote_head_points_at = NULL;
 		remote_head = NULL;
 		option_no_checkout = 1;
-		if (!option_bare)
-			install_branch_config(0, "master", option_origin,
-					      "refs/heads/master");
+		if (!option_bare) {
+			char *default_branch = git_default_branch_name(0);
+			const char *nick;
+
+			if (!skip_prefix(default_branch, "refs/heads/", &nick))
+				BUG("unexpected default branch '%s'",
+				    default_branch);
+			install_branch_config(0, nick, option_origin,
+					      default_branch);
+			free(default_branch);
+		}
 	}
 
 	write_refspec_config(src_ref_prefix, our_head_points_at,
diff --git a/t/t5609-clone-branch.sh b/t/t5609-clone-branch.sh
index 6e7a7be0522..66af3ac2669 100755
--- a/t/t5609-clone-branch.sh
+++ b/t/t5609-clone-branch.sh
@@ -67,4 +67,13 @@ test_expect_success 'clone -b not allowed with empty repos' '
 	test_must_fail git clone -b branch empty clone-branch-empty
 '
 
+test_expect_success 'chooses correct default branch name' '
+	GIT_TEST_DEFAULT_BRANCH_NAME= \
+		git -c core.defaultBranchName=up clone empty whats-up &&
+	test_write_lines refs/heads/up refs/heads/up >expect &&
+	git -C whats-up symbolic-ref HEAD >actual &&
+	git -C whats-up config branch.up.merge >>actual &&
+	test_cmp expect actual
+'
+
 test_done
-- 
gitgitgadget
Junio C Hamano· Jun 10, 2020, 22:58 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH 6/9] clone: learn about the possibly-configured default branch name

"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com> writes:

Show 18 quoted lines
> @@ -1263,9 +1263,17 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
>  		remote_head_points_at = NULL;
>  		remote_head = NULL;
>  		option_no_checkout = 1;
> -		if (!option_bare)
> -			install_branch_config(0, "master", option_origin,
> -					      "refs/heads/master");
> +		if (!option_bare) {
> +			char *default_branch = git_default_branch_name(0);
> +			const char *nick;
> +
> +			if (!skip_prefix(default_branch, "refs/heads/", &nick))
> +				BUG("unexpected default branch '%s'",
> +				    default_branch);
> +			install_branch_config(0, nick, option_origin,
> +					      default_branch);
> +			free(default_branch);
> +		}

Good catch. Normal clone would follow whatever primary branch the other side uses by pointing at it with its "HEAD" but this codepath to deal with a clone of an empty repository needs to use a default, so this is an appropriate change.

Show 19 quoted lines
>  	write_refspec_config(src_ref_prefix, our_head_points_at,
> diff --git a/t/t5609-clone-branch.sh b/t/t5609-clone-branch.sh
> index 6e7a7be0522..66af3ac2669 100755
> --- a/t/t5609-clone-branch.sh
> +++ b/t/t5609-clone-branch.sh
> @@ -67,4 +67,13 @@ test_expect_success 'clone -b not allowed with empty repos' '
>  	test_must_fail git clone -b branch empty clone-branch-empty
>  '
>  
> +test_expect_success 'chooses correct default branch name' '
> +	GIT_TEST_DEFAULT_BRANCH_NAME= \
> +		git -c core.defaultBranchName=up clone empty whats-up &&
> +	test_write_lines refs/heads/up refs/heads/up >expect &&
> +	git -C whats-up symbolic-ref HEAD >actual &&
> +	git -C whats-up config branch.up.merge >>actual &&
> +	test_cmp expect actual
> +'
> +
>  test_done
Johannes Schindelin via GitGitGadget· Jun 10, 2020, 21:19 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH 8/9] fast-export: respect the possibly-overridden default branch name

From: Johannes Schindelin <johannes.schindelin@gmx.de>

When anonymizing commit history, we are careful to leave the branch name of the default branch alone.

When the default branch name is overridden via the config or via the environment variable, we will want `git fast-export` to use that overridden name instead.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 builtin/fast-export.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
Show changes to builtin/fast-export.c +7 −3
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 85868162eec..028dd9969a2 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -515,13 +515,17 @@ static const char *anonymize_refname(const char *refname)
 	};
 	static struct hashmap refs;
 	static struct strbuf anon = STRBUF_INIT;
+	static char *default_branch_name;
 	int i;
 
 	/*
-	 * We also leave "master" as a special case, since it does not reveal
-	 * anything interesting.
+	 * We also leave the default branch name as a special case, since it
+	 * does not reveal anything interesting.
 	 */
-	if (!strcmp(refname, "refs/heads/master"))
+	if (!default_branch_name)
+		default_branch_name = git_default_branch_name(0);
+
+	if (!strcmp(refname, default_branch_name))
 		return refname;
 
 	strbuf_reset(&anon);
-- 
gitgitgadget
Matt Rogers· Jun 10, 2020, 21:54 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Show 5 quoted lines
> -        * We also leave "master" as a special case, since it does not reveal
> -        * anything interesting.
> +        * We also leave the default branch name as a special case, since it
> +        * does not reveal anything interesting.
>          */

I feel this is a weird thing to do, since you're trying to anonymize the branch name,and now the default branch is identifiable with your config file. For example, if the default branch contains the name of my project/repo then this sounds like a recipe for accidentally sharing it. I feel a better alternative would be to exclude nothing from the anonymization or the proposed default default branch name

Show 11 quoted lines
> -       if (!strcmp(refname, "refs/heads/master"))
> +       if (!default_branch_name)
> +               default_branch_name = git_default_branch_name(0);
> +
> +       if (!strcmp(refname, default_branch_name))
>                 return refname;
>
>         strbuf_reset(&anon);
> --
> gitgitgadget
>
-- 
Matthew Rogers
Junio C Hamano· Jun 10, 2020, 23:25 UTC · re: Matt Rogers · lore

Re: [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Matt Rogers <mattr94@gmail.com> writes:
Show 12 quoted lines
>> -        * We also leave "master" as a special case, since it does not reveal
>> -        * anything interesting.
>> +        * We also leave the default branch name as a special case, since it
>> +        * does not reveal anything interesting.
>>          */
> I feel this is a weird thing to do, since you're trying to anonymize the branch
> name,and now the default branch is identifiable with your config file.  For
> example, if the default branch contains the name of my project/repo then this
> sounds like a recipe for accidentally sharing it. I feel a better
> alternative would
> be to exclude nothing from the anonymization or the proposed default default
> branch name

I wonder if anything bad happens if we keep *no* refs intact in this function. "Since it does not reveal anything interesting" is an excuse why not munging it may be OK, but it does not explain why we prefer not munging it actively.

If there is no reason to keep _some_ refs as-is, I agree that it is perfectly sensible not to have this special case at all.

Thanks.
Show 11 quoted lines
>> -       if (!strcmp(refname, "refs/heads/master"))
>> +       if (!default_branch_name)
>> +               default_branch_name = git_default_branch_name(0);
>> +
>> +       if (!strcmp(refname, default_branch_name))
>>                 return refname;
>>
>>         strbuf_reset(&anon);
>> --
>> gitgitgadget
>>
brian m. carlson· Jun 10, 2020, 23:39 UTC · re: Matt Rogers · lore

Re: [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

On 2020-06-10 at 21:54:01, Matt Rogers wrote:
Show 12 quoted lines
> > -        * We also leave "master" as a special case, since it does not reveal
> > -        * anything interesting.
> > +        * We also leave the default branch name as a special case, since it
> > +        * does not reveal anything interesting.
> >          */
> I feel this is a weird thing to do, since you're trying to anonymize the branch
> name,and now the default branch is identifiable with your config file.  For
> example, if the default branch contains the name of my project/repo then this
> sounds like a recipe for accidentally sharing it. I feel a better
> alternative would
> be to exclude nothing from the anonymization or the proposed default default
> branch name

I think this is fine because it only reveals the name of your particular choice of default branch. The goal of the --anonymize option is to allow people to maintain the structure of their repositories while stripping private information from them, primarily for debugging purposes (e.g., providing to us for troubleshooting).

The things people want to prevent exposing are their code, data, project names, user names, etc.: that is, anything identifying, privileged, or private. The default branch name isn't any of those things; we know you have one, and for troubleshooting purposes, we aren't that interested in what you called it. You've almost certainly picked it out of a set of one of 20 words that people use for this purpose, none of which are private, and all of which are shared by millions of other repositories.

In the extremely unlikely case that it does matter, invoking git with something like "-c default.branch=$(git hash-object /dev/null)" would be sufficient to anonymize all branches.

I should point out that people frequently ask for the output of "git config -l" for troubleshooting, and most people wouldn't consider their default branch name to be worth sanitizing there.

-- 
brian m. carlson: Houston, Texas, US
OpenPGP: https://keybase.io/bk2204
Matt Rogers· Jun 11, 2020, 00:20 UTC · re: brian m. carlson · lore

Re: [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Show 14 quoted lines
> I think this is fine because it only reveals the name of your particular
> choice of default branch.  The goal of the --anonymize option is to
> allow people to maintain the structure of their repositories while
> stripping private information from them, primarily for debugging
> purposes (e.g., providing to us for troubleshooting).
>
> The things people want to prevent exposing are their code, data, project
> names, user names, etc.: that is, anything identifying, privileged, or
> private.  The default branch name isn't any of those things; we know you
> have one, and for troubleshooting purposes, we aren't that interested in
> what you called it.  You've almost certainly picked it out of a set of
> one of 20 words that people use for this purpose, none of which are
> private, and all of which are shared by millions of other repositories.
>

I think that's not very convincing. If branch names in general are identifying enough to warrant anonymization then shouldn't the default name be too?

Show 7 quoted lines
> In the extremely unlikely case that it does matter, invoking git with
> something like "-c default.branch=$(git hash-object /dev/null)" would be
> sufficient to anonymize all branches.
>
> I should point out that people frequently ask for the output of "git
> config -l" for troubleshooting, and most people wouldn't consider their
> default branch name to be worth sanitizing there.

I think this is a little presumptuous, most people wouldn't consider it to be worth sanitizing because there isn't currently such a config setting. If I give you the the output of "git config -l" then I think it's obvious that all of my configuration settings will be included (and therefore I can choose to sanitize accordingly), but if I'm giving an exported repository I think should be anonymized, but my default branch, which someone could innocently base on a project or company name, could easily be accidentally included in that output which could lead to a frustrating experience

> --
> brian m. carlson: Houston, Texas, US
> OpenPGP: https://keybase.io/bk2204
-- 
Matthew Rogers
Junio C Hamano· Jun 11, 2020, 05:26 UTC · re: Matt Rogers · lore

Re: [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Matt Rogers <mattr94@gmail.com> writes:
> I think that's not very convincing.  If branch names in general are identifying
> enough to warrant anonymization then shouldn't the default name be too?

It is a good argument. I also heard a rumor that often branch names contain codewords given to pre-released hardware that are highly confidential in certain circles, and heard that it is one of the reasons why Gerrit has server side ACL that lets you hide some branches from authenticated users that can access other branches.

Again, the original comment explains why 'master' without such a configuration knob was not worth protecting, but what it does not explain is why keeping it (and only that branch name) unmunged gives a more useful result than munging everything. From the point of view of "I want to debug the shape of the DAG, without the actual user data", munging 'master' to 'ref47' while other branches like 'next' are munged to 'ref%d' does not make it harder to use or less useful for the debugging than only 'master' is kept intact in the output stream.

Johannes Schindelin· Jun 11, 2020, 14:05 UTC · re: Junio C Hamano · lore

Re: [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Hi,
On Wed, 10 Jun 2020, Junio C Hamano wrote:
Show 10 quoted lines
> Matt Rogers <mattr94@gmail.com> writes:
>
> > I think that's not very convincing.  If branch names in general are identifying
> > enough to warrant anonymization then shouldn't the default name be too?
>
> It is a good argument.  I also heard a rumor that often branch names
> contain codewords given to pre-released hardware that are highly
> confidential in certain circles, and heard that it is one of the
> reasons why Gerrit has server side ACL that lets you hide some
> branches from authenticated users that can access other branches.

Yes, branch names in general _can_ contain information users may prefer to keep private.

However, we're not talking about branch names in general. We are talking about the default name of the main branch, to be picked in _all_ of your new repositories.

Show 9 quoted lines
> Again, the original comment explains why 'master' without such a
> configuration knob was not worth protecting, but what it does not
> explain is why keeping it (and only that branch name) unmunged gives
> a more useful result than munging everything.  From the point of
> view of "I want to debug the shape of the DAG, without the actual
> user data", munging 'master' to 'ref47' while other branches like
> 'next' are munged to 'ref%d' does not make it harder to use or less
> useful for the debugging than only 'master' is kept intact in the
> output stream.

Yes. And you're unlikely to configure the default name to be used for all of your future `git init` operations to be something non-generic.

I am still highly doubtful of Matt's suggestion that it would be worth protecting the default name of the main branch to be used for _each_ and _any_ new repository.

Now, if you suggest that `git fast-export --anonymize` should either not special-case the main branch, or at least have a configurable set of names it skips from protecting, then I will be much more in favor of those suggestions. However, those suggestions are quite a bit orthogonal to the patch series at hand, so I would want to discuss them in their own code contribution instead of here.

Ciao, Dscho

Junio C Hamano· Jun 11, 2020, 15:05 UTC · re: Johannes Schindelin · lore

Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
Show 12 quoted lines
>> It is a good argument.  I also heard a rumor that often branch names
>> contain codewords given to pre-released hardware that are highly
>> confidential in certain circles, and heard that it is one of the
>> reasons why Gerrit has server side ACL that lets you hide some
>> branches from authenticated users that can access other branches.
>
> Yes, branch names in general _can_ contain information users may prefer to
> keep private.
>
> However, we're not talking about branch names in general. We are talking
> about the default name of the main branch, to be picked in _all_ of your
> new repositories.

No, we are talking about the name of the branch, chosen to be the primary one, in one particular repository whose contents are exported via fast-export with explicit request from the user to anonymize end-user data.

Show 9 quoted lines
> Yes. And you're unlikely to configure the default name to be used for all
> of your future `git init` operations to be something non-generic.
>
> Now, if you suggest that `git fast-export --anonymize` should either not
> special-case the main branch, or at least have a configurable set of names
> it skips from protecting, then I will be much more in favor of those
> suggestions. However, those suggestions are quite a bit orthogonal to the
> patch series at hand, so I would want to discuss them in their own code
> contribution instead of here.

I think after writing the message about your "two variable" approach, you would retract the "something non-generic" part in the above sentence. The original "we redact branch names but 'master' is used by and known by everybody so there is no need to redact" would have been a good argument. Perhaps there is a value to keep the primary branch identifiable even in an export stream that has all the refnames and payload anonymized, and leaving 'master' intact would have been a viable approach for solving that issue.

That trick NO LONGER applies once you allow the name of the primary branch customizable, and the end user has used a name that is not to be exposed. Yes, "we want to ensure that readers of the export stream can identify which ref is the primary branch of the repository" is orthogonal from "how do we make primary branch configurable in a live repository?" and "how do we make the default name used for the primary branch in repositories newly created?". But because the old solution would not work in the new world order this topic created, a new solution needs to be found when you move the world to the new order.

An easy solution would be to reserve "ref0" for the primary branch in the repository and anonymize other refs "ref1", "ref2", ...

That can be done as a preparatory step regardless of the "'master' may not be in the name of the primary branch in this repository" topic.

-- >8 --
Subject: [PATCH] fast-export: do anonymize the primary branch name

In a fast-export stream with --anonymize option, all the end-user data including refnames are munged to prevent exposure, but the 'master' branch is left intact.

There is a comment that explains why it is OK to leave 'master' unanonymized (because everybody calls the primary branch 'master' and it is no secret), but that does not justify why it is bad to anonymize 'master' and make it undistinguishable from other branches. Assuming there _is_ a need to allow the readers of the output to tell where the tip of the primary branch is, let's keep the special casing of 'master', but still anonymize it to "ref0". Because all other branches will be given ref+N where N is a positive integer, this will keep the primary branch identifiable in the output stream, without exposing what the name of the primary branch is in the repository the export stream was taken from.

This is in preparation for introducing a mechanism to affect the name of the primary branch used in the repository. Once the mechanism is in use, the name of the primary branch won't be 'master', and may not be allowed to be exposed.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin/fast-export.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
Show changes to builtin/fast-export.c +2 −2
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 85868162ee..a306a60d25 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -497,7 +497,7 @@ static void *anonymize_ref_component(const void *old, size_t *len)
 {
 	static int counter;
 	struct strbuf out = STRBUF_INIT;
-	strbuf_addf(&out, "ref%d", counter++);
+	strbuf_addf(&out, "ref%d", ++counter);
 	return strbuf_detach(&out, len);
 }
 
@@ -522,7 +522,7 @@ static const char *anonymize_refname(const char *refname)
 	 * anything interesting.
 	 */
 	if (!strcmp(refname, "refs/heads/master"))
-		return refname;
+		return "ref0";
 
 	strbuf_reset(&anon);
 	for (i = 0; i < ARRAY_SIZE(prefixes); i++) {
Junio C Hamano· Jun 11, 2020, 16:44 UTC · re: Junio C Hamano · lore

Re: Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Junio C Hamano <gitster@pobox.com> writes:
Show 30 quoted lines
> But because the old solution would not work in the new world order
> this topic created, a new solution needs to be found when you move
> the world to the new order.
>
> An easy solution would be to reserve "ref0" for the primary branch
> in the repository and anonymize other refs "ref1", "ref2", ...
>
> That can be done as a preparatory step regardless of the "'master'
> may not be in the name of the primary branch in this repository"
> topic.
> ...
> diff --git a/builtin/fast-export.c b/builtin/fast-export.c
> index 85868162ee..a306a60d25 100644
> --- a/builtin/fast-export.c
> +++ b/builtin/fast-export.c
> @@ -497,7 +497,7 @@ static void *anonymize_ref_component(const void *old, size_t *len)
>  {
>  	static int counter;
>  	struct strbuf out = STRBUF_INIT;
> -	strbuf_addf(&out, "ref%d", counter++);
> +	strbuf_addf(&out, "ref%d", ++counter);
>  	return strbuf_detach(&out, len);
>  }
>  
> @@ -522,7 +522,7 @@ static const char *anonymize_refname(const char *refname)
>  	 * anything interesting.
>  	 */
>  	if (!strcmp(refname, "refs/heads/master"))
> -		return refname;
> +		return "ref0";
This is obviously wrong.  It should return "refs/heads/ref0".

But another thing we could do, which is probably more backward compatible, is to return "refs/heads/master" from here. That way, consumers of "fast-export" stream that expect 'master' to be the primary branch would not get upset when the data source runs a newer version of Git that allows the primary branch name to be customized.

Which means that, before such a change to allow the primary branch name to be customized happens, there is no need for such a preparatory patch, because the status quo is just fine. So, I'm OK with retracting the above. "ref0" is not special, so there is no need to have the first hunk above, either.

However, when the customization being discussed is implemented via the "get_default_branch_name()" and "get_primary_branch_name()" functions, we should update these lines like so:

- if (!strcmp(refname, "refs/heads/master")) - return "refs/heads/master"; + if (!strcmp(refname, get_primary_branch_name(DO_NOT_ABBREV))) + return get_default_branch_name(DO_NOT_ABBREV);

That is, the name of the "primary" branch used at the data source is replaced by the more generic "this is the default" branch name used in a random "git init" repository.

Imagine that there is a project that has an integration branch per each device type, named after the confidential device name, owned by a company. An employee of the company works on one device type in his own clone of the repository, and the primary branch in the repository is set to that confidential device's name.

The employee can create an anonymized output, replacing the confidential name with a generic "default" name that is not confidential, like 'main' in the new world order or 'master' in the backward compatible world order, with such an updated code.

After having thought about it a bit longer, I actually do prefer to use the "ref0" approach, as it is possible for the employee in the above example to have the "default" branch name tied to the primary branch for the hardware type the emploee works on in the ~/.gitconfig so the "alternative" I suggested in this message will reveal the confidential name.

So, I guess we should just fix the patch I am responding to to return "refs/heads/ref0" instead of "ref0", and queue it as one of the preparatory steps.

Junio C Hamano· Jun 11, 2020, 18:18 UTC · re: Junio C Hamano · lore

Re: Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Junio C Hamano <gitster@pobox.com> writes:
Show 25 quoted lines
>> diff --git a/builtin/fast-export.c b/builtin/fast-export.c
>> index 85868162ee..a306a60d25 100644
>> --- a/builtin/fast-export.c
>> +++ b/builtin/fast-export.c
>> @@ -497,7 +497,7 @@ static void *anonymize_ref_component(const void *old, size_t *len)
>>  {
>>  	static int counter;
>>  	struct strbuf out = STRBUF_INIT;
>> -	strbuf_addf(&out, "ref%d", counter++);
>> +	strbuf_addf(&out, "ref%d", ++counter);
>>  	return strbuf_detach(&out, len);
>>  }
>>  
>> @@ -522,7 +522,7 @@ static const char *anonymize_refname(const char *refname)
>>  	 * anything interesting.
>>  	 */
>>  	if (!strcmp(refname, "refs/heads/master"))
>> -		return refname;
>> +		return "ref0";
>
> This is obviously wrong.  It should return "refs/heads/ref0".
> ...
> So, I guess we should just fix the patch I am responding to to
> return "refs/heads/ref0" instead of "ref0", and queue it as one of
> the preparatory steps.

... and the follow-up step to become part of the series you are working on to allow customing what the primary branch is called would turn the second hunk to

	-	if (!strcmp(refname, "refs/heads/master"))
	+	if (!strcmp(refname, get_primary_branch_name(0)))
			return "refs/heads/ref0";

By the way, with your "two variables" approach to make both the "default" (for 'init' and 'clone') and the "primary" (for 'fmt-merge-msg' and 'fast-export') configurable, we'd need accessor function(s) for the primary branch name for the given repository. The get_primary_branch_name() helper function might want to take a "struct repository *" argument in addition to "please give me an abbreviated refname" boolean, given the recent push to pass the struct to everybody.

Johannes Schindelin· Jun 12, 2020, 12:07 UTC · re: Junio C Hamano · lore

Re: Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Hi Junio,
On Thu, 11 Jun 2020, Junio C Hamano wrote:
Show 35 quoted lines
> Junio C Hamano <gitster@pobox.com> writes:
>
> >> diff --git a/builtin/fast-export.c b/builtin/fast-export.c
> >> index 85868162ee..a306a60d25 100644
> >> --- a/builtin/fast-export.c
> >> +++ b/builtin/fast-export.c
> >> @@ -497,7 +497,7 @@ static void *anonymize_ref_component(const void *old, size_t *len)
> >>  {
> >>  	static int counter;
> >>  	struct strbuf out = STRBUF_INIT;
> >> -	strbuf_addf(&out, "ref%d", counter++);
> >> +	strbuf_addf(&out, "ref%d", ++counter);
> >>  	return strbuf_detach(&out, len);
> >>  }
> >>
> >> @@ -522,7 +522,7 @@ static const char *anonymize_refname(const char *refname)
> >>  	 * anything interesting.
> >>  	 */
> >>  	if (!strcmp(refname, "refs/heads/master"))
> >> -		return refname;
> >> +		return "ref0";
> >
> > This is obviously wrong.  It should return "refs/heads/ref0".
> > ...
> > So, I guess we should just fix the patch I am responding to to
> > return "refs/heads/ref0" instead of "ref0", and queue it as one of
> > the preparatory steps.
>
> ... and the follow-up step to become part of the series you are
> working on to allow customing what the primary branch is called
> would turn the second hunk to
>
> 	-	if (!strcmp(refname, "refs/heads/master"))
> 	+	if (!strcmp(refname, get_primary_branch_name(0)))
> 			return "refs/heads/ref0";
Right.
Show 8 quoted lines
> By the way, with your "two variables" approach to make both the
> "default" (for 'init' and 'clone') and the "primary" (for
> 'fmt-merge-msg' and 'fast-export') configurable, we'd need accessor
> function(s) for the primary branch name for the given repository.
> The get_primary_branch_name() helper function might want to take a
> "struct repository *" argument in addition to "please give me an
> abbreviated refname" boolean, given the recent push to pass the
> struct to everybody.

My current state defines a `repo_main_branch_name(flags)` function where the flags can be `MAIN_BRANCH_SHORT_NAME` and `MAIN_BRANCH_FOR_INIT`.

So I think we're on the same page.

BTW I heard from a couple sides that "primary" would imply that there is also a "secondary" branch, and potentially an ordering of all branches, which is why I did not really consider "primary" as candidate. Besides, it is so much more awkward to type than "main" (especially when you're as tired as I am right now...).

That's why I try to stay with "main" for the moment.

Ciao, Dscho

Junio C Hamano· Jun 12, 2020, 12:32 UTC · re: Johannes Schindelin · lore

Re: Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
Show 7 quoted lines
> BTW I heard from a couple sides that "primary" would imply that there is
> also a "secondary" branch, and potentially an ordering of all branches,
> which is why I did not really consider "primary" as candidate. Besides, it
> is so much more awkward to type than "main" (especially when you're as
> tired as I am right now...).
>
> That's why I try to stay with "main" for the moment.

You are reading too much into it. I used "primary" because I needed a word that clearly conveys the concept of being a special among others, a word that is about the concept which is different from the concept of "default", and that is clearly different from any of the candidates floated as concrete words to replace 'master'. Because I wanted to say things like:

    In the context of fast-export, you'd want to special case the
    "primary" branch name, because unlike the "default" branch name
    (which we envision to be 'main' for most people in the new world
    order, so it may be less worth anonymizing because of the same
    reason the current code keeps 'master' as-is), its name can be
    sensitive.

without becoming unnecessarily ambiguous (replace 'primary' with 'main' in the above).

It was not because I do not want us to pick 'main' as the replacement word for 'master' as the default branch name.

And a set of things, among which there is a concept of "one thing that is special and different from all the others", does not necessarily have to be a totally ordered set. When cloning, we say that the (often bare) repository at the other end indicates which branch is the primary branch of the project by pointing at it with its HEAD (which is the reason why we try to fork it to our local branch namespace and check it out after cloning). There is no "secondary" in such a use case, and there is no need to have one.

Johannes Schindelin· Jun 12, 2020, 12:03 UTC · re: Junio C Hamano · lore

Re: Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Hi Junio,
On Thu, 11 Jun 2020, Junio C Hamano wrote:
Show 34 quoted lines
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> >> It is a good argument.  I also heard a rumor that often branch names
> >> contain codewords given to pre-released hardware that are highly
> >> confidential in certain circles, and heard that it is one of the
> >> reasons why Gerrit has server side ACL that lets you hide some
> >> branches from authenticated users that can access other branches.
> >
> > Yes, branch names in general _can_ contain information users may prefer to
> > keep private.
> >
> > However, we're not talking about branch names in general. We are talking
> > about the default name of the main branch, to be picked in _all_ of your
> > new repositories.
>
> No, we are talking about the name of the branch, chosen to be the
> primary one, in one particular repository whose contents are
> exported via fast-export with explicit request from the user to
> anonymize end-user data.
>
> > Yes. And you're unlikely to configure the default name to be used for all
> > of your future `git init` operations to be something non-generic.
> >
> > Now, if you suggest that `git fast-export --anonymize` should either not
> > special-case the main branch, or at least have a configurable set of names
> > it skips from protecting, then I will be much more in favor of those
> > suggestions. However, those suggestions are quite a bit orthogonal to the
> > patch series at hand, so I would want to discuss them in their own code
> > contribution instead of here.
>
>
> I think after writing the message about your "two variable"
> approach, you would retract the "something non-generic" part in the
> above sentence.
You are absolutely correct!
> [...]
> -- >8 --
> Subject: [PATCH] fast-export: do anonymize the primary branch name

I like this approach a lot. Do you want me to integrate it into this patch series, or rather have it as a stand-alone patch?

Ciao, Dscho

Junio C Hamano· Jun 12, 2020, 12:50 UTC · re: Johannes Schindelin · lore

Re: Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>> Subject: [PATCH] fast-export: do anonymize the primary branch name
>
> I like this approach a lot. Do you want me to integrate it into this patch
> series, or rather have it as a stand-alone patch?

I do not see any need for an off-series preparation step. Without configurable primary branch, keeping 'master' as 'master' used in the current code is an OK way to anonymize refs and still keep the primary line of development in the output identifyable. The "ref0" trick becomes necessary only when we introduce configurable primary; even though it would not hurt to switch to the "ref0" approach to anonymize-but-still-the-primary-is-identifiable early, it just is not necessary to do so.

I'd say that we should take <xmqqpna5bq2l.fsf_-_@gitster.c.googlers.com> with two changes,

 - see if the "refname" matches the fully
   spelled primary branch name by asking repo_main_branch_name(repo,
   0), instead of comparing with "refs/heads/master", and
 - if matches return "refs/heads/ref0" instead of "ref0".

and replace your [PATCH 8/9] (or whichever the counterpart patch is in the rerolled series) with it.

Thanks.
Johannes Schindelin· Jun 12, 2020, 12:53 UTC · re: Junio C Hamano · lore

Re: Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Hi Junio,
On Thu, 11 Jun 2020, Junio C Hamano wrote:
Show 10 quoted lines
> diff --git a/builtin/fast-export.c b/builtin/fast-export.c
> index 85868162ee..a306a60d25 100644
> --- a/builtin/fast-export.c
> +++ b/builtin/fast-export.c
> @@ -522,7 +522,7 @@ static const char *anonymize_refname(const char *refname)
>  	 * anything interesting.
>  	 */
>  	if (!strcmp(refname, "refs/heads/master"))
> -		return refname;
> +		return "ref0";
I just realized that the comment above reads:
        /*
         * We also leave "master" as a special case, since it does not reveal
         * anything interesting.
         */

Obviously, we need to change that comment here because we do not leave the name unchanged. How about this?

        /*
         * We special-case the main branch, anonymizing it to `ref0`.
         */

Ciao, Dscho

>
>  	strbuf_reset(&anon);
>  	for (i = 0; i < ARRAY_SIZE(prefixes); i++) {
>
Johannes Schindelin· Jun 12, 2020, 13:18 UTC · re: Johannes Schindelin · lore

Re: Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Hi Junio,
On Fri, 12 Jun 2020, Johannes Schindelin wrote:
Show 27 quoted lines
> On Thu, 11 Jun 2020, Junio C Hamano wrote:
>
> > diff --git a/builtin/fast-export.c b/builtin/fast-export.c
> > index 85868162ee..a306a60d25 100644
> > --- a/builtin/fast-export.c
> > +++ b/builtin/fast-export.c
> > @@ -522,7 +522,7 @@ static const char *anonymize_refname(const char *refname)
> >  	 * anything interesting.
> >  	 */
> >  	if (!strcmp(refname, "refs/heads/master"))
> > -		return refname;
> > +		return "ref0";
>
> I just realized that the comment above reads:
>
>         /*
>          * We also leave "master" as a special case, since it does not reveal
>          * anything interesting.
>          */
>
>
> Obviously, we need to change that comment here because we do not leave the
> name unchanged. How about this?
>
>         /*
>          * We special-case the main branch, anonymizing it to `ref0`.
>          */
Also, t9351 obviously needs to be adjusted. This one works for me:
-- snipsnap --
From: Junio C Hamano <gitster@pobox.com>
Date: Thu, 11 Jun 2020 08:05:38 -0700
Subject: [PATCH] fast-export: do anonymize the primary branch name

In a fast-export stream with --anonymize option, all the end-user data including refnames are munged to prevent exposure, but the 'master' branch is left intact.

There is a comment that explains why it is OK to leave 'master' unanonymized (because everybody calls the primary branch 'master' and it is no secret), but that does not justify why it is bad to anonymize 'master' and make it undistinguishable from other branches. Assuming there _is_ a need to allow the readers of the output to tell where the tip of the primary branch is, let's keep the special casing of 'master', but still anonymize it to "ref0". Because all other branches will be given ref+N where N is a positive integer, this will keep the primary branch identifiable in the output stream, without exposing what the name of the primary branch is in the repository the export stream was taken from.

This is in preparation for introducing a mechanism to affect the name of the primary branch used in the repository. Once the mechanism is in use, the name of the primary branch won't be 'master', and may not be allowed to be exposed.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 builtin/fast-export.c            | 7 +++----
 t/t9351-fast-export-anonymize.sh | 9 +++++----
 2 files changed, 8 insertions(+), 8 deletions(-)
Show changes to 2 files +8 −9

builtin/fast-export.c, t/t9351-fast-export-anonymize.sh

diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 85868162eec..f10e3b35e5b 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -497,7 +497,7 @@ static void *anonymize_ref_component(const void *old, size_t *len)
 {
 	static int counter;
 	struct strbuf out = STRBUF_INIT;
-	strbuf_addf(&out, "ref%d", counter++);
+	strbuf_addf(&out, "ref%d", ++counter);
 	return strbuf_detach(&out, len);
 }

@@ -518,11 +518,10 @@ static const char *anonymize_refname(const char *refname)
 	int i;

 	/*
-	 * We also leave "master" as a special case, since it does not reveal
-	 * anything interesting.
+	 * We special-case the main branch, anonymizing it to `ref0`.
 	 */
 	if (!strcmp(refname, "refs/heads/master"))
-		return refname;
+		return "refs/heads/ref0";

 	strbuf_reset(&anon);
 	for (i = 0; i < ARRAY_SIZE(prefixes); i++) {
diff --git a/t/t9351-fast-export-anonymize.sh b/t/t9351-fast-export-anonymize.sh
index 897dc509075..2415f0ec213 100755
--- a/t/t9351-fast-export-anonymize.sh
+++ b/t/t9351-fast-export-anonymize.sh
@@ -26,8 +26,9 @@ test_expect_success 'stream omits path names' '
 	! grep xyzzy stream
 '

-test_expect_success 'stream allows master as refname' '
-	grep master stream
+test_expect_success 'stream translates master to ref0' '
+	grep refs/heads/ref0 stream &&
+	! grep master stream
 '

 test_expect_success 'stream omits other refnames' '
@@ -57,7 +58,7 @@ test_expect_success 'import stream to new repository' '
 test_expect_success 'result has two branches' '
 	git for-each-ref --format="%(refname)" refs/heads >branches &&
 	test_line_count = 2 branches &&
-	other_branch=$(grep -v refs/heads/master branches)
+	other_branch=$(grep -v refs/heads/ref0 branches)
 '

 test_expect_success 'repo has original shape and timestamps' '
@@ -65,7 +66,7 @@ test_expect_success 'repo has original shape and timestamps' '
 		git log --format="%m %ct" --left-right --boundary "$@"
 	} &&
 	(cd .. && shape master...other) >expect &&
-	shape master...$other_branch >actual &&
+	shape ref0...$other_branch >actual &&
 	test_cmp expect actual
 '

--
2.26.0.windows.1
Junio C Hamano· Jun 12, 2020, 15:19 UTC · re: Johannes Schindelin · lore

Re: Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
Show 26 quoted lines
> Also, t9351 obviously needs to be adjusted. This one works for me:
>
> -- snipsnap --
> From: Junio C Hamano <gitster@pobox.com>
> Date: Thu, 11 Jun 2020 08:05:38 -0700
> Subject: [PATCH] fast-export: do anonymize the primary branch name
>
> In a fast-export stream with --anonymize option, all the end-user
> data including refnames are munged to prevent exposure, but the
> 'master' branch is left intact.
> ...
> This is in preparation for introducing a mechanism to affect the
> name of the primary branch used in the repository.  Once the
> mechanism is in use, the name of the primary branch won't be
> 'master', and may not be allowed to be exposed.
>
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> ---
>  builtin/fast-export.c            | 7 +++----
>  t/t9351-fast-export-anonymize.sh | 9 +++++----
>  2 files changed, 8 insertions(+), 8 deletions(-)
> ...
>  	if (!strcmp(refname, "refs/heads/master"))
> -		return refname;
> +		return "refs/heads/ref0";

As I said already, I personally do not think that this needs to be a preparatory patch to anonymize 'master' that cannot be configured to something else into 'ref0'. This will become necessary when we make the primary branch configurable, so I think it is easier to replace the counterpart to your [PATCH 8/9] in the original series with it in the v2 series.

Regarding the update to the comment before this "special case", I would suggest to explain "why" not just "what".

Thanks.
Junio C Hamano· Jun 12, 2020, 15:22 UTC · re: Junio C Hamano · lore

Re: Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Junio C Hamano <gitster@pobox.com> writes:
Show 6 quoted lines
> As I said already, I personally do not think that this needs to be a
> preparatory patch to anonymize 'master' that cannot be configured to
> something else into 'ref0'.  This will become necessary when we make
> the primary branch configurable, so I think it is easier to replace
> the counterpart to your [PATCH 8/9] in the original series with it
> in the v2 series.

Ah, I forgot to say, if you think it is easier to manage the main set of patches for the topic to eject as much preparatory changes as possible, I do not at all mind treating this as one of the preparatory step and queue it separately, making the main series depend on it. I just wanted to say that it is not necessary, even though it does not hurt.

> Regarding the update to the comment before this "special case", I
> would suggest to explain "why" not just "what".
>
> Thanks.
Johannes Schindelin· Jun 13, 2020, 05:00 UTC · re: Junio C Hamano · lore

Re: Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Hi Junio,
On Fri, 12 Jun 2020, Junio C Hamano wrote:
Show 15 quoted lines
> Junio C Hamano <gitster@pobox.com> writes:
>
> > As I said already, I personally do not think that this needs to be a
> > preparatory patch to anonymize 'master' that cannot be configured to
> > something else into 'ref0'.  This will become necessary when we make
> > the primary branch configurable, so I think it is easier to replace
> > the counterpart to your [PATCH 8/9] in the original series with it
> > in the v2 series.
>
> Ah, I forgot to say, if you think it is easier to manage the main
> set of patches for the topic to eject as much preparatory changes as
> possible, I do not at all mind treating this as one of the
> preparatory step and queue it separately, making the main series
> depend on it.  I just wanted to say that it is not necessary, even
> though it does not hurt.

Due to the need to adjust t9351, I think it is clearer if it is a two-part change: one to introduce the "main branch -> ref0" change, and another one to respect `core.mainBranch`. Those are separate concerns in my mind.

I moved the first one to the beginning of the patch series so that you're still at liberty to take it early vs keeping it within the topic branch.

Thanks, Dscho

Junio C Hamano· Jun 12, 2020, 15:14 UTC · re: Johannes Schindelin · lore

Re: Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
Show 14 quoted lines
> I just realized that the comment above reads:
>
>         /*
>          * We also leave "master" as a special case, since it does not reveal
>          * anything interesting.
>          */
>
>
> Obviously, we need to change that comment here because we do not leave the
> name unchanged. How about this?
>
>         /*
>          * We special-case the main branch, anonymizing it to `ref0`.
>          */
If you are going to update it, why not make it useful?

I complained number of times during the discussion that the original comment explains why leaving 'master' as-is does not reveal anything useful to adversaries but does not justify what the code attempts to achieve by special casing 'master' in the first place.

It is not an improvement to literally adjust that inadequate comment to the new world order to just parrot what the code already says without explaining why it does so.

	/*
	 * Anonymize the name used for the primary branch in this
	 * repository, but reserve `ref0` for it, so that it can
	 * be identified among other refs in the output.
	 */

is the minimum I would expect before calling it an improvement. We could add

	It is often `main` for new repositories (and `master` for
	aged ones) and such well-known names may not need
	anonymizing, but it could be configured to use a secret word
	that the user may not want to reveal.

at the end to explain the motivation behind anonymizing even more, if we wanted to.

Now, "so that ..." part is totally a fabrication based on my best guess. I do not know what the original author was thinking when the decision to leave the master as-is was made.

Thanks.
Johannes Sixt· Jun 13, 2020, 11:49 UTC · re: Junio C Hamano · lore

Re: Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Am 12.06.20 um 17:14 schrieb Junio C Hamano:
Show 16 quoted lines
> 	/*
> 	 * Anonymize the name used for the primary branch in this
> 	 * repository, but reserve `ref0` for it, so that it can
> 	 * be identified among other refs in the output.
> 	 */
> 
> is the minimum I would expect before calling it an improvement.  We
> could add
> 
> 	It is often `main` for new repositories (and `master` for
> 	aged ones) and such well-known names may not need
> 	anonymizing, but it could be configured to use a secret word
> 	that the user may not want to reveal.
> 
> at the end to explain the motivation behind anonymizing even more,
> if we wanted to.

IMO, making the primary branch identifiable is a reasonable justification to treat it specially. But then, why does it have to be renamed to 'ref0'? Couldn't it just be renamed to Git's default primary branch name, be it 'master' today or 'main' or whatever in the future? After the anonymization, nobody will know whether that was the real name of the primary branch or not. Leaving it at 'master'/'main' reduces the mental burden of the recipient of the anonymous repo.

-- Hannes
Junio C Hamano· Jun 13, 2020, 16:25 UTC · re: Johannes Sixt · lore

Re: Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Johannes Sixt <j6t@kdbg.org> writes:
Show 22 quoted lines
> Am 12.06.20 um 17:14 schrieb Junio C Hamano:
>> 	/*
>> 	 * Anonymize the name used for the primary branch in this
>> 	 * repository, but reserve `ref0` for it, so that it can
>> 	 * be identified among other refs in the output.
>> 	 */
>> 
>> is the minimum I would expect before calling it an improvement.  We
>> could add
>> 
>> 	It is often `main` for new repositories (and `master` for
>> 	aged ones) and such well-known names may not need
>> 	anonymizing, but it could be configured to use a secret word
>> 	that the user may not want to reveal.
>> 
>> at the end to explain the motivation behind anonymizing even more,
>> if we wanted to.
>
> IMO, making the primary branch identifiable is a reasonable
> justification to treat it specially. But then, why does it have to be
> renamed to 'ref0'? Couldn't it just be renamed to Git's default primary
> branch name, be it 'master' today or 'main' or whatever in the future?
That comes from https://lore.kernel.org/git/xmqqtuzha6xn.fsf@gitster.c.googlers.com/

But I agree with you 100% if you literally mean 'master' (or 'main') hardcoded without any end-user customization. What I rejected and replaced with the vanilla "ref0" was to return the configured name that will be used for the primary branch in new repositories. The above proposal suggested a faulty:

- if (!strcmp(refname, "refs/heads/master")) - return refname; + if (!strcmp(refname, get_primary_branch_name(DO_NOT_ABBREV))) + return get_default_branch_name(DO_NOT_ABBREV);

A corrected code should return a hardwired constant 'main' (it probably gets behind a C preprocessor macro, but the point is that we do not want end-user customization) for the reason stated in that message.

Thanks.
Johannes Schindelin· Jun 13, 2020, 14:47 UTC · re: Junio C Hamano · lore

Re: Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Hi Junio & Hannes,
On Sat, 13 Jun 2020, Junio C Hamano wrote:
Show 42 quoted lines
> Johannes Sixt <j6t@kdbg.org> writes:
>
> > Am 12.06.20 um 17:14 schrieb Junio C Hamano:
> >> 	/*
> >> 	 * Anonymize the name used for the primary branch in this
> >> 	 * repository, but reserve `ref0` for it, so that it can
> >> 	 * be identified among other refs in the output.
> >> 	 */
> >>
> >> is the minimum I would expect before calling it an improvement.  We
> >> could add
> >>
> >> 	It is often `main` for new repositories (and `master` for
> >> 	aged ones) and such well-known names may not need
> >> 	anonymizing, but it could be configured to use a secret word
> >> 	that the user may not want to reveal.
> >>
> >> at the end to explain the motivation behind anonymizing even more,
> >> if we wanted to.
> >
> > IMO, making the primary branch identifiable is a reasonable
> > justification to treat it specially. But then, why does it have to be
> > renamed to 'ref0'? Couldn't it just be renamed to Git's default primary
> > branch name, be it 'master' today or 'main' or whatever in the future?
>
> That comes from https://lore.kernel.org/git/xmqqtuzha6xn.fsf@gitster.c.googlers.com/
>
> But I agree with you 100% if you literally mean 'master' (or 'main')
> hardcoded without any end-user customization.  What I rejected and
> replaced with the vanilla "ref0" was to return the configured name
> that will be used for the primary branch in new repositories.  The
> above proposal suggested a faulty:
>
> -	if (!strcmp(refname, "refs/heads/master"))
> -		return refname;
> +	if (!strcmp(refname, get_primary_branch_name(DO_NOT_ABBREV)))
> +		return get_default_branch_name(DO_NOT_ABBREV);
>
> A corrected code should return a hardwired constant 'main' (it
> probably gets behind a C preprocessor macro, but the point is that
> we do not want end-user customization) for the reason stated in that
> message.
I like `ref0` better, for two reasons:
- it is more consistent to just have all anonymized branches be named
  `ref<N>`, and
- using `main` both for an original `main` and an original `master` can be
  a bit confusing, as the reader might assume that this branch name (as it
  does not follow the `ref<N>` convention) was _not_ anonymized, when it
  very well might have been.

Ciao, Dscho

Junio C Hamano· Jun 13, 2020, 18:49 UTC · re: Johannes Schindelin · lore

Re: Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
Show 14 quoted lines
>> A corrected code should return a hardwired constant 'main' (it
>> probably gets behind a C preprocessor macro, but the point is that
>> we do not want end-user customization) for the reason stated in that
>> message.
>
> I like `ref0` better, for two reasons:
>
> - it is more consistent to just have all anonymized branches be named
>   `ref<N>`, and
>
> - using `main` both for an original `main` and an original `master` can be
>   a bit confusing, as the reader might assume that this branch name (as it
>   does not follow the `ref<N>` convention) was _not_ anonymized, when it
>   very well might have been.

A pro for keeping a hardcoded 'master' is that it is compatible with the current world order, and flipping it to hardcoded 'main' upon transition is just to use the moral equivalent, so we do not need to immediately have to change anything. The _new_ consistency across ref<N> does feel attractive, but because it is new, there always is a pushback not to "fix" what is not broken.

I am personally OK either way.  

By the way, we'd need to devise a transition plan for switching the default branch name (i.e. the name used for the primary branch in a newly created repository unless the user configures it to some other value) to 'main' (oh, I just found one reason why I will not want to use that name in my project(s)---it is too close to 'maint').

It might roughly go like:
 1. We introduce core.defaultBranchName; when it is not set, its
    value defaults to 'master' in the 1st phase of the transition.
    "git init" and "git clone" however issue a warning that says
    "unless you configure core.defaultBranchName, we use 'master'
    for now for backward compatibility but we will start using
    'main' in three major releases of Git in the future".  These
    commands use the default branch name when creating a new
    repository in the 1st phase, and set core.primaryBranchName to
    that name in the resulting repository.
    This is to encourage early adopters to set it to 'maint'^W'main'
    (eek, see, I again made that typo), while allowing those who
    have toolset that depends more heavily on the current default
    branch name than other people to set it to 'master' for
    stability.
    In the 1st phase, a few commands that care about what the
    primary branch is in a repository (i.e. fmt-merge-msg and
    fast-export are the two we have identified so far) pay attention
    to the core.primaryBranchName configuration, and default to
    'master' if the configuration does not exist.  
    These commands issue a warning that says "unless you configure
    core.primaryBranchName in the repository, we use 'master' for
    now but we will start using 'main' in three major releases of
    Git in the future".
    The above two warning messages will be squelched once the user
    sets respective configuration variable.
 2. We flip the default for the two variables from 'master' to
    'main' in three major releases of Git (i.e. 24-30 weeks from the
    1st phase).  The two warning messages added for the 1st phase
    will be reworded for the updated default.  We no longer need to
    say "in three major releases" in there.
 3. After long time passes, remove the warning.
Johannes Schindelin· Jun 14, 2020, 08:55 UTC · re: Junio C Hamano · lore

Re: Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Hi Junio,
On Sat, 13 Jun 2020, Junio C Hamano wrote:
Show 31 quoted lines
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> >> A corrected code should return a hardwired constant 'main' (it
> >> probably gets behind a C preprocessor macro, but the point is that
> >> we do not want end-user customization) for the reason stated in that
> >> message.
> >
> > I like `ref0` better, for two reasons:
> >
> > - it is more consistent to just have all anonymized branches be named
> >   `ref<N>`, and
> >
> > - using `main` both for an original `main` and an original `master` can be
> >   a bit confusing, as the reader might assume that this branch name (as it
> >   does not follow the `ref<N>` convention) was _not_ anonymized, when it
> >   very well might have been.
>
> A pro for keeping a hardcoded 'master' is that it is compatible with
> the current world order, and flipping it to hardcoded 'main' upon
> transition is just to use the moral equivalent, so we do not need to
> immediately have to change anything.  The _new_ consistency across
> ref<N> does feel attractive, but because it is new, there always is
> a pushback not to "fix" what is not broken.
>
> I am personally OK either way.
>
> By the way, we'd need to devise a transition plan for switching the
> default branch name (i.e. the name used for the primary branch in a
> newly created repository unless the user configures it to some other
> value) to 'main' (oh, I just found one reason why I will not want to
> use that name in my project(s)---it is too close to 'maint').

Yes, the trouble with `maint` did cross my mind, but I try not to "overfit" to git/git. :-)

Show 39 quoted lines
> It might roughly go like:
>
>  1. We introduce core.defaultBranchName; when it is not set, its
>     value defaults to 'master' in the 1st phase of the transition.
>     "git init" and "git clone" however issue a warning that says
>     "unless you configure core.defaultBranchName, we use 'master'
>     for now for backward compatibility but we will start using
>     'main' in three major releases of Git in the future".  These
>     commands use the default branch name when creating a new
>     repository in the 1st phase, and set core.primaryBranchName to
>     that name in the resulting repository.
>
>     This is to encourage early adopters to set it to 'maint'^W'main'
>     (eek, see, I again made that typo), while allowing those who
>     have toolset that depends more heavily on the current default
>     branch name than other people to set it to 'master' for
>     stability.
>
>     In the 1st phase, a few commands that care about what the
>     primary branch is in a repository (i.e. fmt-merge-msg and
>     fast-export are the two we have identified so far) pay attention
>     to the core.primaryBranchName configuration, and default to
>     'master' if the configuration does not exist.
>
>     These commands issue a warning that says "unless you configure
>     core.primaryBranchName in the repository, we use 'master' for
>     now but we will start using 'main' in three major releases of
>     Git in the future".
>
>     The above two warning messages will be squelched once the user
>     sets respective configuration variable.
>
>  2. We flip the default for the two variables from 'master' to
>     'main' in three major releases of Git (i.e. 24-30 weeks from the
>     1st phase).  The two warning messages added for the 1st phase
>     will be reworded for the updated default.  We no longer need to
>     say "in three major releases" in there.
>
>  3. After long time passes, remove the warning.

Yes, that's what I had in my mind, too (modulo the concrete part about the three major versions, which is something I would have asked about at some stage, thank you for answering that question already!).

Thank you, Dscho

Junio C Hamano· Jun 17, 2020, 20:06 UTC · re: Johannes Schindelin · lore

Re: Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> Yes, the trouble with `maint` did cross my mind, but I try not to
> "overfit" to git/git. :-)

I do not think it is overfitting; if the solution cannot even support the originating project well, there is something wrong.

Most likely, I'd be tempted to rename it myself away from any name that is too similar to 'maint'; perhaps to 'stable' (or 'devo', h/t tla ;-).

Johannes Schindelin· Jun 23, 2020, 21:11 UTC · re: Junio C Hamano · lore

Re: Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Hi Junio,
On Wed, 17 Jun 2020, Junio C Hamano wrote:
Show 11 quoted lines
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > Yes, the trouble with `maint` did cross my mind, but I try not to
> > "overfit" to git/git. :-)
>
> I do not think it is overfitting; if the solution cannot even
> support the originating project well, there is something wrong.
>
> Most likely, I'd be tempted to rename it myself away from any name
> that is too similar to 'maint'; perhaps to 'stable' (or 'devo', h/t
> tla ;-).

You could also use `next` instead of `master`, which would make intuitive sense because the commits that make it into that branch are slated to be part of the next major Git version.

And a relatively obvious name for the current `next` might be `cooking`.

I refrained from proposing this earlier, thinking that this would be too disruptive, but since `pu` was renamed to `seen`...

:-)

Ciao, Dscho

Junio C Hamano· Jun 23, 2020, 21:32 UTC · re: Johannes Schindelin · lore

Re: Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
Show 8 quoted lines
> You could also use `next` instead of `master`, which would make intuitive
> sense because the commits that make it into that branch are slated to be
> part of the next major Git version.
>
> And a relatively obvious name for the current `next` might be `cooking`.
>
> I refrained from proposing this earlier, thinking that this would be too
> disruptive, but since `pu` was renamed to `seen`...

Renaming 'pu' away from two-letter has a positive technical and social effect. Using 'next' for anything but what it currently means does not have any such upside and only the downside of confusing people.

As to 'cooking', I am not sure. Personally I consider that the topics that are in 'next' plus those that are soon to be in 'next' are all 'cooking'. But I do not think anybody's dying to rename 'next', so...

Johannes Schindelin· Jun 13, 2020, 14:44 UTC · re: Junio C Hamano · lore

Re: Re* [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Hi Junio,
On Fri, 12 Jun 2020, Junio C Hamano wrote:
Show 23 quoted lines
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > I just realized that the comment above reads:
> >
> >         /*
> >          * We also leave "master" as a special case, since it does not reveal
> >          * anything interesting.
> >          */
> >
> >
> > Obviously, we need to change that comment here because we do not leave the
> > name unchanged. How about this?
> >
> >         /*
> >          * We special-case the main branch, anonymizing it to `ref0`.
> >          */
>
> If you are going to update it, why not make it useful?
>
> I complained number of times during the discussion that the original
> comment explains why leaving 'master' as-is does not reveal anything
> useful to adversaries but does not justify what the code attempts to
> achieve by special casing 'master' in the first place.
True. Sorry about forgetting that when adjusting the code comment.

In my defense, I am/was much more worried about transmogrifying the patch series to reflect the separation between `init.defaultBranch` and `core.mainBranch` and the associated fall-out (I highly doubt that the range-diff between v1 and v2 will be useful...).

Show 9 quoted lines
> It is not an improvement to literally adjust that inadequate comment
> to the new world order to just parrot what the code already says
> without explaining why it does so.
>
> 	/*
> 	 * Anonymize the name used for the primary branch in this
> 	 * repository, but reserve `ref0` for it, so that it can
> 	 * be identified among other refs in the output.
> 	 */
That is indeed an improvement, thank you so much.
Show 10 quoted lines
> is the minimum I would expect before calling it an improvement.  We
> could add
>
> 	It is often `main` for new repositories (and `master` for
> 	aged ones) and such well-known names may not need
> 	anonymizing, but it could be configured to use a secret word
> 	that the user may not want to reveal.
>
> at the end to explain the motivation behind anonymizing even more,
> if we wanted to.

Maybe we add that to the comment in the patch that teaches `fast-export` about `core.mainBranch`? Yeah, I think I like that idea best.

> Now, "so that ..." part is totally a fabrication based on my best
> guess.  I do not know what the original author was thinking when the
> decision to leave the master as-is was made.

This comment comes from a8722750985 (teach fast-export an --anonymize option, 2014-08-27), and I agree that there is no explicit explanation why the main branch is special-cased.

However, I think that your guess is a good one: it might be an interesting aspect to identify the commits from the main branch, without necessarily needing to know the actual name of said branch, e.g. to reproduce a reported issue.

Ciao, Dscho

Johannes Schindelin· Jun 11, 2020, 13:57 UTC · re: Matt Rogers · lore

Re: [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Hi Matt,
On Wed, 10 Jun 2020, Matt Rogers wrote:
Show 12 quoted lines
> > -        * We also leave "master" as a special case, since it does not reveal
> > -        * anything interesting.
> > +        * We also leave the default branch name as a special case, since it
> > +        * does not reveal anything interesting.
> >          */
> I feel this is a weird thing to do, since you're trying to anonymize the branch
> name,and now the default branch is identifiable with your config file.  For
> example, if the default branch contains the name of my project/repo then this
> sounds like a recipe for accidentally sharing it. I feel a better
> alternative would
> be to exclude nothing from the anonymization or the proposed default default
> branch name

I don't think that the name of the main branch should be subject to anonymizing, whether it be `master` or anything else.

Ciao, Dscho

Junio C Hamano· Jun 11, 2020, 18:19 UTC · re: Johannes Schindelin · lore

Re: [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
Show 19 quoted lines
> Hi Matt,
>
> On Wed, 10 Jun 2020, Matt Rogers wrote:
>
>> > -        * We also leave "master" as a special case, since it does not reveal
>> > -        * anything interesting.
>> > +        * We also leave the default branch name as a special case, since it
>> > +        * does not reveal anything interesting.
>> >          */
>> I feel this is a weird thing to do, since you're trying to anonymize the branch
>> name,and now the default branch is identifiable with your config file.  For
>> example, if the default branch contains the name of my project/repo then this
>> sounds like a recipe for accidentally sharing it. I feel a better
>> alternative would
>> be to exclude nothing from the anonymization or the proposed default default
>> branch name
>
> I don't think that the name of the main branch should be subject to
> anonymizing, whether it be `master` or anything else.

"Here is why" is missing ;-) I think you realized that it needs to be, after you wrote the "ah, we need two, the default for new ones and the name of the primary branch in a particular repository", as we are dealing with the latter here.

Thanks.
Johannes Schindelin· Jun 12, 2020, 12:07 UTC · re: Junio C Hamano · lore

Re: [PATCH 8/9] fast-export: respect the possibly-overridden default branch name

Hi Junio,
On Thu, 11 Jun 2020, Junio C Hamano wrote:
Show 26 quoted lines
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > Hi Matt,
> >
> > On Wed, 10 Jun 2020, Matt Rogers wrote:
> >
> >> > -        * We also leave "master" as a special case, since it does not reveal
> >> > -        * anything interesting.
> >> > +        * We also leave the default branch name as a special case, since it
> >> > +        * does not reveal anything interesting.
> >> >          */
> >> I feel this is a weird thing to do, since you're trying to anonymize the branch
> >> name,and now the default branch is identifiable with your config file.  For
> >> example, if the default branch contains the name of my project/repo then this
> >> sounds like a recipe for accidentally sharing it. I feel a better
> >> alternative would
> >> be to exclude nothing from the anonymization or the proposed default default
> >> branch name
> >
> > I don't think that the name of the main branch should be subject to
> > anonymizing, whether it be `master` or anything else.
>
> "Here is why" is missing ;-)  I think you realized that it needs to
> be, after you wrote the "ah, we need two, the default for new ones
> and the name of the primary branch in a particular repository", as
> we are dealing with the latter here.
Yep, absolutely.

Thanks, Dscho

Johannes Schindelin via GitGitGadget· Jun 10, 2020, 21:19 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH 9/9] Document how the default branch name can be overridden

From: Johannes Schindelin <johannes.schindelin@gmx.de>

There is a `GIT_TEST_*` environment variable and a `core.` config setting (with the former taking precendence over the latter) to allow overriding what name Git uses by default as main branch of new repositories.

Now that all kinds of Git operations have learned to respect those, let's document them.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 Documentation/config/core.txt | 4 ++++
 t/README                      | 4 ++++
 2 files changed, 8 insertions(+)
Show changes to 2 files +8 −0

Documentation/config/core.txt, t/README

diff --git a/Documentation/config/core.txt b/Documentation/config/core.txt
index 74619a9c03b..a11e1abdf59 100644
--- a/Documentation/config/core.txt
+++ b/Documentation/config/core.txt
@@ -626,3 +626,7 @@ 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.defaultBranchName::
+	Allows overriding the default branch name e.g. when initializing
+	a new repository or when cloning an empty repository.
diff --git a/t/README b/t/README
index cf863837ab9..b32f520a27f 100644
--- a/t/README
+++ b/t/README
@@ -421,6 +421,10 @@ GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=<boolean>, when true (which is
 the default when running tests), errors out when an abbreviated option
 is used.
 
+GIT_TEST_DEFAULT_BRANCH_NAME allows overriding the default branch name
+that is used for example when initializing new repositories, or when
+cloning a repository that has no branches yet.
+
 Naming Tests
 ------------
 
-- 
gitgitgadget
Junio C Hamano· Jun 11, 2020, 00:18 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH 9/9] Document how the default branch name can be overridden

"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com> writes:

Show 12 quoted lines
> diff --git a/Documentation/config/core.txt b/Documentation/config/core.txt
> index 74619a9c03b..a11e1abdf59 100644
> --- a/Documentation/config/core.txt
> +++ b/Documentation/config/core.txt
> @@ -626,3 +626,7 @@ 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.defaultBranchName::
> +	Allows overriding the default branch name e.g. when initializing
> +	a new repository or when cloning an empty repository.

As we saw in [PATCH 7/9], it also affects for which branch an auto-generated merge message omits "into $branch" at the end.

The behaviour change of "merge" might matter more than we think here in a hand-wavy way, and it certainly does affect more than 'init' and 'clone' (both of which are one time operation per repository), because setting this in ~/.gitconfig would affect all the repositories, whose merges into their 'master' suddenly starts saying "into master" at the end, unlike existing merges. So it probably is worth highlighting it here.

Show 14 quoted lines
> diff --git a/t/README b/t/README
> index cf863837ab9..b32f520a27f 100644
> --- a/t/README
> +++ b/t/README
> @@ -421,6 +421,10 @@ GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=<boolean>, when true (which is
>  the default when running tests), errors out when an abbreviated option
>  is used.
>  
> +GIT_TEST_DEFAULT_BRANCH_NAME allows overriding the default branch name
> +that is used for example when initializing new repositories, or when
> +cloning a repository that has no branches yet.
> +
>  Naming Tests
>  ------------
Johannes Schindelin via GitGitGadget· Jun 10, 2020, 21:19 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH 5/9] submodule: use the (possibly overridden) default branch name

From: Johannes Schindelin <johannes.schindelin@gmx.de>

To allow for overriding the default branch name, we have introduced a config setting. With this patch, the `git submodule` command learns about this, too.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 builtin/submodule--helper.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
Show changes to builtin/submodule--helper.c +8 −2
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 46c03d2a126..0b4abb5a64b 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1980,8 +1980,14 @@ static const char *remote_submodule_branch(const char *path)
 		branch = sub->branch;
 	free(key);
 
-	if (!branch)
-		return "master";
+	if (!branch) {
+		static char *default_branch;
+
+		if (!default_branch)
+			default_branch = git_default_branch_name(1);
+
+		return default_branch;
+	}
 
 	if (!strcmp(branch, ".")) {
 		const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
-- 
gitgitgadget
Denton Liu· Jun 15, 2020, 10:46 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH 5/9] submodule: use the (possibly overridden) default branch name

On Wed, Jun 10, 2020 at 09:19:26PM +0000, Johannes Schindelin via GitGitGadget wrote:
Show 7 quoted lines
> From: Johannes Schindelin <johannes.schindelin@gmx.de>
> 
> To allow for overriding the default branch name, we have introduced a
> config setting. With this patch, the `git submodule` command learns
> about this, too.
> 
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>

One thing to consider: in the future, if we move away from "master" or even allow the value to be configurable, we're gonna end up breaking a lot of repositories this way.

If a developer regularly pulls in submodule updates via `git submodule update --remote`, when the default branch name changes, this will suddenly stop working. This will require developers who use submodules to "fix" their .gitmodules file.

If it's configurable, this problem might be even worse. It could lead to scenarios where one developer might go "works for me" while another developer (who may set the configuration and forget about it) would be confused about why it's not working for them.

Just a couple thoughts I had while looking at this patch.
Johannes Schindelin via GitGitGadget· Jun 10, 2020, 21:19 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH 4/9] testsvn: respect `core.defaultBranchName`

From: Johannes Schindelin <johannes.schindelin@gmx.de>

Since the default branch name can now be configured, the `testsvn` remote helper needs to be told about it.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 remote-testsvn.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)
Show changes to remote-testsvn.c +8 −3
diff --git a/remote-testsvn.c b/remote-testsvn.c
index 3af708c5b67..a48d74f35cd 100644
--- a/remote-testsvn.c
+++ b/remote-testsvn.c
@@ -13,7 +13,7 @@
 static const char *url;
 static int dump_from_file;
 static const char *private_ref;
-static const char *remote_ref = "refs/heads/master";
+static char *remote_ref;
 static const char *marksfilename, *notes_ref;
 struct rev_note { unsigned int rev_nr; };
 
@@ -286,7 +286,7 @@ int cmd_main(int argc, const char **argv)
 			private_ref_sb = STRBUF_INIT, marksfilename_sb = STRBUF_INIT,
 			notes_ref_sb = STRBUF_INIT;
 	static struct remote *remote;
-	const char *url_in;
+	const char *url_in, *default_branch;
 
 	setup_git_directory();
 	if (argc < 2 || argc > 3) {
@@ -294,6 +294,10 @@ int cmd_main(int argc, const char **argv)
 		return 1;
 	}
 
+	remote_ref = git_default_branch_name(0);
+	if (!skip_prefix(remote_ref, "refs/heads/", &default_branch))
+		BUG("unexpected remote_ref '%s'", remote_ref);
+
 	remote = remote_get(argv[1]);
 	url_in = (argc == 3) ? argv[2] : remote->url[0];
 
@@ -306,7 +310,8 @@ int cmd_main(int argc, const char **argv)
 		url = url_sb.buf;
 	}
 
-	strbuf_addf(&private_ref_sb, "refs/svn/%s/master", remote->name);
+	strbuf_addf(&private_ref_sb, "refs/svn/%s/%s",
+		    remote->name, default_branch);
 	private_ref = private_ref_sb.buf;
 
 	strbuf_addf(&notes_ref_sb, "refs/notes/%s/revs", remote->name);
-- 
gitgitgadget
Junio C Hamano· Jun 10, 2020, 23:11 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH 0/9] Allow overriding the default name of the default branch

"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com> writes:

Show 5 quoted lines
> A growing number of open source projects aims to avoid the branch name 
> master due to its negative connotation. See [1] for an existing discussion
> on this. The links [2], [3], and [4] describe community-driven ways for
> users to rename their default branches or use template edits to set a new
> default branch name.

I scanned the series quickly and the patches seem to cover all the places I was aware of that has the hard-coded knowledge of the default branch name being 'master'. Looking good.

Show 5 quoted lines
> This series DOES NOT change the default automatically, but only provides an
> opt-in mechanism for interested users. It also presents a way forward for
> such a transition, if and when we decide to do so. Specifically, the new
> GIT_TEST_DEFAULT_BRANCH_NAME environment variable could be used to update
> test scripts on an individual basis instead of all-at-once.

Yes. I've been thinking about a way that does not hurt workflows used in existing projects while allowing a "git init" that is run to create a new repository by a new user who does not have any special customization in ~/.gitconfig to use the branch name that replaces the 'master' (I do not mind changing away from 'master', but I am not yet convinced it should be 'main', by the way---the actual choice of the final name does not matter at this point of the design of backward compatibility plan).

I think "git init" that is creating a new repository (iow, do not do anything when reinitializing an existing repostiory) can

 - look at config.defaultBranchName in /etc/gitconfig or
   ~/.gitconfig before initializing the per-repository config in
   $GIT_DIR/config it just created (or it is about to create).
 - if there is no config.defaultBranchName configured, then set the
   per-repository configuration to 'main' in the per-repository
   configuration.  Otherwise do not do anything.

And then we make sure Don's git_default_branch_name() works this way:

 (0) if there is config.defaultBranchName in relevant config file
     (i.e. /etc/gitconfig, ~/.gitconfig or per-repo config), use the
     specified name.
 (1) otherwise use 'master' (not 'main').

That way, an existing repository will keep using 'master' unless the user shows the preference (and accepts responsibilities for possible fallouts) in ~/.gitconfig or the repository's .git/config, while a new repository created by a user who does not show any particular preference will use 'main'.

Junio C Hamano· Jun 11, 2020, 05:42 UTC · re: Junio C Hamano · lore

Re: [PATCH 0/9] Allow overriding the default name of the default branch

Junio C Hamano <gitster@pobox.com> writes:
Show 43 quoted lines
> "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
> writes:
> ...
>> This series DOES NOT change the default automatically, but only provides an
>> opt-in mechanism for interested users. It also presents a way forward for
>> such a transition, if and when we decide to do so. Specifically, the new
>> GIT_TEST_DEFAULT_BRANCH_NAME environment variable could be used to update
>> test scripts on an individual basis instead of all-at-once.
>
> Yes.  I've been thinking about a way that does not hurt workflows
> used in existing projects while allowing a "git init" that is run to
> create a new repository by a new user who does not have any special
> customization in ~/.gitconfig to use the branch name that replaces
> the 'master' (I do not mind changing away from 'master', but I am
> not yet convinced it should be 'main', by the way---the actual
> choice of the final name does not matter at this point of the design
> of backward compatibility plan).  
>
> I think "git init" that is creating a new repository (iow, do not do
> anything when reinitializing an existing repostiory) can
>
>  - look at config.defaultBranchName in /etc/gitconfig or
>    ~/.gitconfig before initializing the per-repository config in
>    $GIT_DIR/config it just created (or it is about to create).
>
>  - if there is no config.defaultBranchName configured, then set the
>    per-repository configuration to 'main' in the per-repository
>    configuration.  Otherwise do not do anything.
>
> And then we make sure Don's git_default_branch_name() works this
> way:
>
>  (0) if there is config.defaultBranchName in relevant config file
>      (i.e. /etc/gitconfig, ~/.gitconfig or per-repo config), use the
>      specified name.
>
>  (1) otherwise use 'master' (not 'main').
>
> That way, an existing repository will keep using 'master' unless the
> user shows the preference (and accepts responsibilities for possible
> fallouts) in ~/.gitconfig or the repository's .git/config, while a
> new repository created by a user who does not show any particular
> preference will use 'main'.

A useful addition to these 9-patch series (i.e. even before the default for vanilla usage gets changed) might be to give an example to use "git config" to grab the default branch name, e.g.

    name=$(git config core.defaultBranchName || echo master)

Better yet (because the above forces the end users to write 'master' in their script), we might want to teach "git var" about the variable, so that the above can be written like so:

    name=$(git var defaultBranchName)

For those not so familiar with "git var", it is a command to query "magic" variables whose value can be retrieved from different places and is backed by non-trivial logic. "What's the editor to be used?" is queried by "git var GIT_EDITOR", but that is not a simple:

    if test -n "$GIT_EDITOR"
    then
	echo "$GIT_EDITOR"
    else
	echo vi
    fi

It takes the fallback `EDITOR` environment variable, and core.editor configuration variable, into account, for example.

Similarly, "what is the default branch name" is not just about the value of one configuration variable. GIT_TEST_DEFAULT_BRANCH_NAME environment needs to be consulted, and when there is nothing configured, it needs to say 'master', so that end-users who use "git var" do not have to hardcode the string 'master' in their script.

Johannes Schindelin· Jun 11, 2020, 13:44 UTC · re: Junio C Hamano · lore

Re: [PATCH 0/9] Allow overriding the default name of the default branch

Hi Junio,
On Wed, 10 Jun 2020, Junio C Hamano wrote:
Show 12 quoted lines
> "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
> writes:
>
> > A growing number of open source projects aims to avoid the branch name
> > master due to its negative connotation. See [1] for an existing discussion
> > on this. The links [2], [3], and [4] describe community-driven ways for
> > users to rename their default branches or use template edits to set a new
> > default branch name.
>
> I scanned the series quickly and the patches seem to cover all the
> places I was aware of that has the hard-coded knowledge of the
> default branch name being 'master'.  Looking good.
Thanks!
Show 41 quoted lines
> > This series DOES NOT change the default automatically, but only
> > provides an opt-in mechanism for interested users. It also presents a
> > way forward for such a transition, if and when we decide to do so.
> > Specifically, the new GIT_TEST_DEFAULT_BRANCH_NAME environment
> > variable could be used to update test scripts on an individual basis
> > instead of all-at-once.
>
> Yes.  I've been thinking about a way that does not hurt workflows
> used in existing projects while allowing a "git init" that is run to
> create a new repository by a new user who does not have any special
> customization in ~/.gitconfig to use the branch name that replaces
> the 'master' (I do not mind changing away from 'master', but I am
> not yet convinced it should be 'main', by the way---the actual
> choice of the final name does not matter at this point of the design
> of backward compatibility plan).
>
> I think "git init" that is creating a new repository (iow, do not do
> anything when reinitializing an existing repostiory) can
>
>  - look at config.defaultBranchName in /etc/gitconfig or
>    ~/.gitconfig before initializing the per-repository config in
>    $GIT_DIR/config it just created (or it is about to create).
>
>  - if there is no config.defaultBranchName configured, then set the
>    per-repository configuration to 'main' in the per-repository
>    configuration.  Otherwise do not do anything.
>
> And then we make sure Don's git_default_branch_name() works this
> way:
>
>  (0) if there is config.defaultBranchName in relevant config file
>      (i.e. /etc/gitconfig, ~/.gitconfig or per-repo config), use the
>      specified name.
>
>  (1) otherwise use 'master' (not 'main').
>
> That way, an existing repository will keep using 'master' unless the
> user shows the preference (and accepts responsibilities for possible
> fallouts) in ~/.gitconfig or the repository's .git/config, while a
> new repository created by a user who does not show any particular
> preference will use 'main'.

I read this (way too late) last night and slept over it. Together with your comment on the `fmt-merge-msg` patch, I think you are really on to something: we need _two_ config settings, as there are two distinct concepts at play here:

- One setting to specify the default branch name for newly-initialized
  repositories (such as `git init`, unless it re-initializes, and `git
  clone` when the cloned repository does not yet contain any branches).
  This should probably be called `init.defaultBranchName` (even if `git
  clone` picks it up, too), and be overrideable by
  `GIT_TEST_DEFAULT_BRANCH_NAME`.
- And another one, to define the default branch name for the _current_
  repository. This setting would be configured implicitly upon `git init`
  and `git clone`. For repositories where it is not set, we would assume
  `master` for backwards-compatibility.
  Technically, this should probably not even be a config option because it
  is _strictly_ per-repo. But maybe it is not _so_ much per-repo: if I
  want to rename all my main branches in all of my local repositories, I
  might opt to configure this in `~/.gitconfig`.
  Maybe a good name for this would be `repo.mainBranch` (and it would
  contain the full ref name, e.g. `refs/heads/main`, not just `main`).

And then `git fmt-merge-msg` (and your proposed `git var` addition, which I like a lot, maybe `git var mainBranch`?) will pick up the latter.

That way, existing repositories would not be affected by `GIT_TEST_DEFAULT_BRANCH_NAME` or `init.defaultBranchName` at all. Only new repositories would pick it up.

Does that sound like a plan?

Ciao, Dscho

Junio C Hamano· Jun 11, 2020, 14:44 UTC · re: Johannes Schindelin · lore

Re: [PATCH 0/9] Allow overriding the default name of the default branch

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
Show 12 quoted lines
> I read this (way too late) last night and slept over it. Together with
> your comment on the `fmt-merge-msg` patch, I think you are really on to
> something: we need _two_ config settings, as there are two distinct
> concepts at play here:
>
> - One setting to specify the default branch name for newly-initialized
>   repositories (such as `git init`, unless it re-initializes, and `git
>   clone` when the cloned repository does not yet contain any branches).
>
>   This should probably be called `init.defaultBranchName` (even if `git
>   clone` picks it up, too), and be overrideable by
>   `GIT_TEST_DEFAULT_BRANCH_NAME`.
Yes.
> - And another one, to define the default branch name for the _current_
>   repository. This setting would be configured implicitly upon `git init`

Nit. This is not the "default" branch name. It is "which branch is the primary one in this repository?" There is no default.

Show 10 quoted lines
>   and `git clone`. For repositories where it is not set, we would assume
>   `master` for backwards-compatibility.
>
>   Technically, this should probably not even be a config option because it
>   is _strictly_ per-repo. But maybe it is not _so_ much per-repo: if I
>   want to rename all my main branches in all of my local repositories, I
>   might opt to configure this in `~/.gitconfig`.
>
>   Maybe a good name for this would be `repo.mainBranch` (and it would
>   contain the full ref name, e.g. `refs/heads/main`, not just `main`).

I think core.* namespace originally were supposed to be about "this" repository, so instead of introducing "repo.*", I'd recommend just sticking it in "core.*", perhaps "core.primaryBranchName".

And for help the scripts in t/, GIT_TEST_PRIMARY_BRANCH_NAME would be a handy thing to have.

> And then `git fmt-merge-msg` (and your proposed `git var` addition, which
> I like a lot, maybe `git var mainBranch`?) will pick up the latter.

You may need "git fast-export" to know about it (I do not think you should special case the primary branch but that is a topic of another thread).

Show 5 quoted lines
> That way, existing repositories would not be affected by
> `GIT_TEST_DEFAULT_BRANCH_NAME` or `init.defaultBranchName` at all. Only
> new repositories would pick it up.
>
> Does that sound like a plan?

So the idea is that init.* one affects "init" and "clone" (and any other operation that creates a new repository and have to pick a branch to point the HEAD at), lack of which defaults to 'main', and the other one affects "fmt-merge-msg", "fast-export" (and any other operation that wants to know which branch is the primary one in the repository), lack of which defaults to 'master'?

And an updated version of Git would record the latter in the repository it just created, based on the former, so that things won't get broken when the user sets the latter in ~/.gitconfig?

I think such a two-variable configuration would also work.  

I was aiming at not needing any configuration for new people and the approach I illustrated for you with just a single variable was an outcome from it. One possible downside of the one-variable approach is that existing users with repositories whose primary branch needs to stay 'master' cannot set the core.defaultBrnachName in ~/.gitconfig until they iterate over all the "sticking to 'master'" repositories and set the core.defaultBrnachName variable in them, but with the two variable approach, that particular downside is eliminated, which I like. I haven't thought things through to see if there are downside in the two variable approach, but just like "If you have some repositories that want to stick to 'master', set the config in them before you set the config globally to something different from 'master'" would be a semi-workable workaround for the downside in the one variable approach, I suspect any downside in the two variable approach we will identify would have an easy workaround, too.

Thanks.
brian m. carlson· Jun 10, 2020, 23:41 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH 0/9] Allow overriding the default name of the default branch

On 2020-06-10 at 21:19:21, Johannes Schindelin via GitGitGadget wrote:
Show 37 quoted lines
> A growing number of open source projects aims to avoid the branch name 
> master due to its negative connotation. See [1] for an existing discussion
> on this. The links [2], [3], and [4] describe community-driven ways for
> users to rename their default branches or use template edits to set a new
> default branch name.
> 
> [1] 
> https://lore.kernel.org/git/CAOAHyQwyXC1Z3v7BZAC+Bq6JBaM7FvBenA-1fcqeDV==apdWDg@mail.gmail.com/
> 
> [2] https://twitter.com/mislav/status/1270388510684598272
> 
> [3] 
> https://www.hanselman.com/blog/EasilyRenameYourGitDefaultBranchFromMasterToMain.aspx
> 
> [4] https://github.com/ethomson/retarget_prs
> 
> By necessity, existing repositories require a lot of manual work to move
> away from that branch name, but it should be much easier for new
> repositories.
> 
> This patch series allows overriding the branch name being used for new
> repositories' main branch. The main way to do this is the new 
> core.defaultBranchName config option. This first patch was contributed by
> newcomer Dan Goodman-Wilson. Thanks for the contribution!
> 
> The other patches follow other places where "master" is hard-coded and use
> the new git_default_branch_name() method to consume the config option before
> falling back to "master".
> 
> The last patch updates documentation only after the config option is ready
> to apply to all of these scenarios.
> 
> This series DOES NOT change the default automatically, but only provides an
> opt-in mechanism for interested users. It also presents a way forward for
> such a transition, if and when we decide to do so. Specifically, the new
> GIT_TEST_DEFAULT_BRANCH_NAME environment variable could be used to update
> test scripts on an individual basis instead of all-at-once.

I've looked over this series, and I have no additional comments beyond what I've mentioned and what Junio pointed out at the end of the series. With those provisos, I'm generally happy with it, and glad to see these patches hit the list.

-- 
brian m. carlson: Houston, Texas, US
OpenPGP: https://keybase.io/bk2204
Taylor Blau· Jun 11, 2020, 01:07 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH 0/9] Allow overriding the default name of the default branch

Hi Johannes (and Dan)
On Wed, Jun 10, 2020 at 09:19:21PM +0000, Johannes Schindelin via GitGitGadget wrote:
Show 19 quoted lines
> A growing number of open source projects aims to avoid the branch name
> master due to its negative connotation. See [1] for an existing discussion
> on this. The links [2], [3], and [4] describe community-driven ways for
> users to rename their default branches or use template edits to set a new
> default branch name.
>
> [1]
> https://lore.kernel.org/git/CAOAHyQwyXC1Z3v7BZAC+Bq6JBaM7FvBenA-1fcqeDV==apdWDg@mail.gmail.com/
>
> [2] https://twitter.com/mislav/status/1270388510684598272
>
> [3]
> https://www.hanselman.com/blog/EasilyRenameYourGitDefaultBranchFromMasterToMain.aspx
>
> [4] https://github.com/ethomson/retarget_prs
>
> By necessity, existing repositories require a lot of manual work to move
> away from that branch name, but it should be much easier for new
> repositories.

This is (somewhat) orthogonal to the topic here, but I wonder if we could be doing anything to make this easier for users.

Could servers remember that a branch has ``moved'' and alert users as such when they pull? Even better, it would be nice if this alert from the server could allow clients to automatically rename their refs appropriately so that this transition is as easy as possible, even for existing repositories.

> This patch series allows overriding the branch name being used for new
> repositories' main branch. The main way to do this is the new
> core.defaultBranchName config option. This first patch was contributed by
> newcomer Dan Goodman-Wilson. Thanks for the contribution!

Welcome, Dan! This is a fantastic first contribution, and I would be honored to help and move this forward in anyway that I can.

I should note that I am technically "out of office" (which normally wouldn't mean much, but this time means that I am on a road-trip, and so am only at my computer infrequently). I am catching up on just a few emails here, but I'll be able to help out more (and would be honored to do so) once I am really back next Monday.

Show 12 quoted lines
> The other patches follow other places where "master" is hard-coded and use
> the new git_default_branch_name() method to consume the config option before
> falling back to "master".
>
> The last patch updates documentation only after the config option is ready
> to apply to all of these scenarios.
>
> This series DOES NOT change the default automatically, but only provides an
> opt-in mechanism for interested users. It also presents a way forward for
> such a transition, if and when we decide to do so. Specifically, the new
> GIT_TEST_DEFAULT_BRANCH_NAME environment variable could be used to update
> test scripts on an individual basis instead of all-at-once.

Provided that the eventual plan is to seriously evaluate a name other than "master", I think that this is a good way forward that clears the way for us to make this change easily, without forcing us to come to a conclusion on what name will replace "master" today.

For what it's worth, I am completely in favor of abandoning this term. My colleagues at GitHub (as has been mentioned previously on the list) are in favor of this as well, and it is my understanding that other providers feel similarly.

I would be in favor of any non-offensive name that we can reach consensus on. "trunk" sounds nice to me, but I think that it may cause problems for non-native English speakers, so perhaps "main" or "default" would suffice (maybe "main" is better, since it retains muscle memory for the first two characters without being offensive--at least, as far as I can tell. If I am wrong, please correct me and we should consider something else).

All of that said, I can't emphasize enough how little I care about *what* name we replace "master" with, so long as it is (1) replaced with a non-offensive term, (2) that that change is done uniformly throughout the "Git Ecosystem" and (3) that the community can reach consensus on the new term in a respectful, appropriate, and considerate way. I only provided a few suggestions to get the conversation flowing, although I suspect that my help isn't needed there.

Show 38 quoted lines
> Don Goodman-Wilson (1):
>   init: allow overriding the default branch name for new repositories
>
> Johannes Schindelin (8):
>   remote: respect `core.defaultBranchName`
>   send-pack/transport-helper: respect `core.defaultBranchName`
>   testsvn: respect `core.defaultBranchName`
>   submodule: use the (possibly overridden) default branch name
>   clone: learn about the possibly-configured default branch name
>   fmt-merge-msg: learn about the possibly-configured default branch name
>   fast-export: respect the possibly-overridden default branch name
>   Document how the default branch name can be overridden
>
>  Documentation/config/core.txt |  4 ++++
>  builtin/clone.c               | 14 +++++++++++---
>  builtin/fast-export.c         | 10 +++++++---
>  builtin/init-db.c             |  8 +++++---
>  builtin/submodule--helper.c   | 10 ++++++++--
>  fmt-merge-msg.c               |  6 ++++--
>  refs.c                        | 34 ++++++++++++++++++++++++++++++++++
>  refs.h                        |  6 ++++++
>  remote-testsvn.c              | 11 ++++++++---
>  remote.c                      | 12 ++++++++----
>  send-pack.c                   |  6 +++++-
>  t/README                      |  4 ++++
>  t/t0001-init.sh               | 20 ++++++++++++++++++++
>  t/t5609-clone-branch.sh       |  9 +++++++++
>  t/t6200-fmt-merge-msg.sh      |  8 ++++++++
>  transport-helper.c            |  6 +++++-
>  16 files changed, 146 insertions(+), 22 deletions(-)
>
>
> base-commit: 0313f36c6ebecb3bffe6f15cf25a4883100f0214
> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-656%2Fdscho%2Fdefault-branch-name-option-v1
> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-656/dscho/default-branch-name-option-v1
> Pull-Request: https://github.com/gitgitgadget/git/pull/656
> --
> gitgitgadget

Thanks, Taylor

Johannes Schindelin· Jun 11, 2020, 14:33 UTC · re: Taylor Blau · lore

Re: [PATCH 0/9] Allow overriding the default name of the default branch

Hi Taylor,
On Wed, 10 Jun 2020, Taylor Blau wrote:
Show 29 quoted lines
> On Wed, Jun 10, 2020 at 09:19:21PM +0000, Johannes Schindelin via GitGitGadget wrote:
> > A growing number of open source projects aims to avoid the branch name
> > master due to its negative connotation. See [1] for an existing discussion
> > on this. The links [2], [3], and [4] describe community-driven ways for
> > users to rename their default branches or use template edits to set a new
> > default branch name.
> >
> > [1]
> > https://lore.kernel.org/git/CAOAHyQwyXC1Z3v7BZAC+Bq6JBaM7FvBenA-1fcqeDV==apdWDg@mail.gmail.com/
> >
> > [2] https://twitter.com/mislav/status/1270388510684598272
> >
> > [3]
> > https://www.hanselman.com/blog/EasilyRenameYourGitDefaultBranchFromMasterToMain.aspx
> >
> > [4] https://github.com/ethomson/retarget_prs
> >
> > By necessity, existing repositories require a lot of manual work to move
> > away from that branch name, but it should be much easier for new
> > repositories.
>
> This is (somewhat) orthogonal to the topic here, but I wonder if we
> could be doing anything to make this easier for users.
>
> Could servers remember that a branch has ``moved'' and alert users as
> such when they pull? Even better, it would be nice if this alert from
> the server could allow clients to automatically rename their refs
> appropriately so that this transition is as easy as possible, even for
> existing repositories.

I would _love_ to have `git fetch origin master` work, spitting out a message `the main branch name changed to [...] please update your configuration`.

And then maybe an easy way to update the configuration (`git remote set-main-branch <nick> <refname>` might make sense).

As you say, it is orthogonal to this here patch series, but definitely related in spirit because we _want_ to make it easier for users to move away from the current main branch name.

Show 7 quoted lines
> > This patch series allows overriding the branch name being used for new
> > repositories' main branch. The main way to do this is the new
> > core.defaultBranchName config option. This first patch was contributed by
> > newcomer Dan Goodman-Wilson. Thanks for the contribution!
>
> Welcome, Dan! This is a fantastic first contribution, and I would be
> honored to help and move this forward in anyway that I can.
Sorry, my typo: it's Don, not Dan ;-)
Show 5 quoted lines
> I should note that I am technically "out of office" (which normally
> wouldn't mean much, but this time means that I am on a road-trip, and so
> am only at my computer infrequently). I am catching up on just a few
> emails here, but I'll be able to help out more (and would be honored to
> do so) once I am really back next Monday.
Well, go back enjoying your road trip! :-P See you on Monday.
Show 17 quoted lines
> > The other patches follow other places where "master" is hard-coded and use
> > the new git_default_branch_name() method to consume the config option before
> > falling back to "master".
> >
> > The last patch updates documentation only after the config option is ready
> > to apply to all of these scenarios.
> >
> > This series DOES NOT change the default automatically, but only provides an
> > opt-in mechanism for interested users. It also presents a way forward for
> > such a transition, if and when we decide to do so. Specifically, the new
> > GIT_TEST_DEFAULT_BRANCH_NAME environment variable could be used to update
> > test scripts on an individual basis instead of all-at-once.
>
> Provided that the eventual plan is to seriously evaluate a name other
> than "master", I think that this is a good way forward that clears the
> way for us to make this change easily, without forcing us to come to a
> conclusion on what name will replace "master" today.
That is exactly the intention of this patch series.

I _do_ want to put my weight behind changing the default. Obviously, this will take quite a bit of time (but maybe less than I originally thought, as we are only talking about changing the default for _new_ repositories).

Even if this endeavor fails, though, this here patch series will be good to have.

> For what it's worth, I am completely in favor of abandoning this term.
> My colleagues at GitHub (as has been mentioned previously on the list)
> are in favor of this as well, and it is my understanding that other
> providers feel similarly.

From what I read at https://gitlab.com/gitlab-org/gitlab/-/issues/221164, GitLab is on board, too.

Show 7 quoted lines
> I would be in favor of any non-offensive name that we can reach
> consensus on. "trunk" sounds nice to me, but I think that it may cause
> problems for non-native English speakers, so perhaps "main" or
> "default" would suffice (maybe "main" is better, since it retains muscle
> memory for the first two characters without being offensive--at least,
> as far as I can tell. If I am wrong, please correct me and we should
> consider something else).
My personal preference was "default" on Monday, and "main" ever since.
Show 7 quoted lines
> All of that said, I can't emphasize enough how little I care about
> *what* name we replace "master" with, so long as it is (1) replaced with
> a non-offensive term, (2) that that change is done uniformly throughout
> the "Git Ecosystem" and (3) that the community can reach consensus on
> the new term in a respectful, appropriate, and considerate way. I only
> provided a few suggestions to get the conversation flowing, although I
> suspect that my help isn't needed there.

Indeed. I laid out the patch series in such a way that we should be able to pick a different default main branch name than "main", even if it is my current working hypothesis that this will prevail.

As I said, my preference was "default", and that's how my big patch series looked like, so I know how much work it is to change to a different name (because I changed it to "main"). It is quite a bit of work, but manageable.

Ciao, Dscho

Pratyush Yadav· Jun 15, 2020, 10:03 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH 0/9] Allow overriding the default name of the default branch

Hi,
On 10/06/20 09:19PM, Johannes Schindelin via GitGitGadget wrote:
Show 37 quoted lines
> A growing number of open source projects aims to avoid the branch name 
> master due to its negative connotation. See [1] for an existing discussion
> on this. The links [2], [3], and [4] describe community-driven ways for
> users to rename their default branches or use template edits to set a new
> default branch name.
> 
> [1] 
> https://lore.kernel.org/git/CAOAHyQwyXC1Z3v7BZAC+Bq6JBaM7FvBenA-1fcqeDV==apdWDg@mail.gmail.com/
> 
> [2] https://twitter.com/mislav/status/1270388510684598272
> 
> [3] 
> https://www.hanselman.com/blog/EasilyRenameYourGitDefaultBranchFromMasterToMain.aspx
> 
> [4] https://github.com/ethomson/retarget_prs
> 
> By necessity, existing repositories require a lot of manual work to move
> away from that branch name, but it should be much easier for new
> repositories.
> 
> This patch series allows overriding the branch name being used for new
> repositories' main branch. The main way to do this is the new 
> core.defaultBranchName config option. This first patch was contributed by
> newcomer Dan Goodman-Wilson. Thanks for the contribution!
> 
> The other patches follow other places where "master" is hard-coded and use
> the new git_default_branch_name() method to consume the config option before
> falling back to "master".
> 
> The last patch updates documentation only after the config option is ready
> to apply to all of these scenarios.
> 
> This series DOES NOT change the default automatically, but only provides an
> opt-in mechanism for interested users. It also presents a way forward for
> such a transition, if and when we decide to do so. Specifically, the new
> GIT_TEST_DEFAULT_BRANCH_NAME environment variable could be used to update
> test scripts on an individual basis instead of all-at-once.

Many people have expressed reservations against this change. Some on the list here, others in private conversation. I personally don't have a strong opinion on either side. So I'll refrain from saying too much on the issue. Reading through the list, I sense that the Git maintainer has already decided it is something good for the project. And so I think this change has a high chance of making it in a near future Git release.

One argument from those in favor of this change is that it doesn't affect you if you don't care about the default branch name. You can just go on using 'master' for all _your_ repos. I'd like to highlight the "your" here. Sure, I can keep on using 'master' if I so prefer, but I don't just use my repos. I also pull repos from other people, and I have no control over what they call their main/primary/master branch (I'll use "main" for the rest of the email). The cost here is that people now need to update their scripts and workflow to account for other people's naming preferences.

For example, my vim plugins are submodules in the '~/.vim/bundle' directory. When I want to update them, I run:

  git submodule foreach 'git remote update && git reset --hard origin/master'

With this change hitting a Git release, more and more people would call their main branch different names they like. So what is the recommended way to do something like this now? How do I checkout the tip of the main branch? How do I push to the main branch? How do I pull from the main branch? And so on...

-- 
Regards,
Pratyush Yadav
Johannes Schindelin· Jun 14, 2020, 22:26 UTC · re: Pratyush Yadav · lore

Re: [PATCH 0/9] Allow overriding the default name of the default branch

Hi Pratyush,
On Mon, 15 Jun 2020, Pratyush Yadav wrote:
Show 9 quoted lines
> On 10/06/20 09:19PM, Johannes Schindelin via GitGitGadget wrote:
>
> > This series DOES NOT change the default automatically, but only provides an
> > opt-in mechanism for interested users. It also presents a way forward for
> > such a transition, if and when we decide to do so. Specifically, the new
> > GIT_TEST_DEFAULT_BRANCH_NAME environment variable could be used to update
> > test scripts on an individual basis instead of all-at-once.
>
> Many people have expressed reservations against this change.

From what you wrote below, I take it that you are not talking about this patch series, nor the follow-up one(s) to change the default main branch name for new repositories.

Show 9 quoted lines
> One argument from those in favor of this change is that it doesn't
> affect you if you don't care about the default branch name. You can just
> go on using 'master' for all _your_ repos. I'd like to highlight the
> "your" here. Sure, I can keep on using 'master' if I so prefer, but I
> don't just use my repos. I also pull repos from other people, and I have
> no control over what they call their main/primary/master branch (I'll
> use "main" for the rest of the email). The cost here is that people now
> need to update their scripts and workflow to account for other people's
> naming preferences.

This talks about the scenario where a project you use decides to change their main branch name.

While this is a scenario that my patch series tries to support (by introducing the concept of `core.mainBranch`), it is not something my patch series _causes_.

All _this_ patch series does is to _allow_ changing the main branch name (manually) in an existing repository, and to change the default main branch name to use in new repositories.

Even the follow-up patch series I plan on contributing that changes the hard-coded default for the default main branch name to use in new repositories won't affect any existing repository.

So I think this example...
Show 10 quoted lines
> For example, my vim plugins are submodules in the '~/.vim/bundle'
> directory. When I want to update them, I run:
>
>   git submodule foreach 'git remote update && git reset --hard origin/master'
>
> With this change hitting a Git release, more and more people would call
> their main branch different names they like. So what is the recommended
> way to do something like this now? How do I checkout the tip of the main
> branch? How do I push to the main branch? How do I pull from the main
> branch? And so on...

... has less to do with a new Git release, but more with the decision of an existing project to change their main branch name.

That's something users already had to deal with, of course. For example, projects switching to the Git Flow model will start to use the main branch name `development`.

GitHub Desktop changed their main branch name to `development`, and it did not require any new Git release.

GitHub CLI changed their main branch name to `trunk`.

Chrome and node.js stated their intention to change their main branch name to `main`.

And https://github.com/microsoft/git uses `vfs-<version>` where `<version>` corresponds to the Git (for Windows) version on which it is based, therefore the main branch name changes whenever there is a new Git version.

These challenges have existed for every project that chooses to change their main branch name, for whatever reason.

In other words, I think you are talking about a challenge that is orthogonal (if related, on a high level) to the subject this patch series tries to address.

Ciao, Johannes

Denton Liu· Jun 16, 2020, 00:19 UTC · re: Johannes Schindelin · lore

Re: [PATCH 0/9] Allow overriding the default name of the default branch

Hi Dscho,
On Mon, Jun 15, 2020 at 12:26:03AM +0200, Johannes Schindelin wrote:
Show 17 quoted lines
> > For example, my vim plugins are submodules in the '~/.vim/bundle'
> > directory. When I want to update them, I run:
> >
> >   git submodule foreach 'git remote update && git reset --hard origin/master'
> >
> > With this change hitting a Git release, more and more people would call
> > their main branch different names they like. So what is the recommended
> > way to do something like this now? How do I checkout the tip of the main
> > branch? How do I push to the main branch? How do I pull from the main
> > branch? And so on...
> 
> ... has less to do with a new Git release, but more with the decision of
> an existing project to change their main branch name.
> 
> That's something users already had to deal with, of course. For example,
> projects switching to the Git Flow model will start to use the main branch
> name `development`.

I brought this concern up in a parallel thread but I'll bring it up here too since it's relevant. Currently, in the .gitmodules file, if the branch is not specified, it defaults to 'master'.

When I want to update my vim plugins, I run `git submodule update --remote` which pulls in all of my submodules' 'master' branches. By convention, a lack of `branch` key in .gitmodules conventionally means 'master'.

With your change, it becomes the value of git_main_branch_name(), which is fine for now. However, if this value changes to something else, then when I update my Git, suddenly `git submodule update --remote` will be broken for me as all of the new repositories that I pull will be for an incorrect (and possibly missing) branch.

This leaves us in a scenario where one developer running an older version of Git would have submodule updates work perfectly fine while a developer with a newer version would have it suddenly broken. This might be hard to debug, especially for someone who doesn't follow the release notes around Git and doesn't realise why the default has suddenly changed.

This problem gets much worse if we allow the main branch name to be configurable as then the *private* configurations that a developer has may have an effect on the *publicly visible* behaviour of a repository.

I think I see three possible solutions to this:
	1. Special case 'master' in submodules to retain backwards
	compatibility.
	I don't think this is very appealing as if the change is made to
	use another default branch name, then the "default" branch for
	submodules would be "master" even though the new default
	everywhere else would be different. And in the future, someone
	who doesn't know the context behind all of this would be very
	confused where there are two different default branch names.
	2. Disable 'update --remote' support for submodules that don't
	specify a branch.
	If Git detects that a branch key is missing when trying to do an
	'update --remote', it should just quit out and refuse to do
	anything. Of course, this a very backwards incompatible change
	and it would require several release cycles to implement where
	we warn users about this impending change before we actually
	make it happen.
	3. Make 'update --remote' get HEAD.
	I argue that this is how it always should've been implemented
	but, alas, I can't go back in time and fix it. Regardless, it
	might be good to flip this to be the default if we're going to
	be making the change anyway.
	Unfortunately, this suffers from both the problems of 1 and 2.
	As with 1, we'll end up in a situation where users with
	different versions of Git may experience different behaviours
	given the same public repository and I think this is definitely
	undesirable. With 2, this change will also require a long
	deprecation period which I don't think it compatible with how
	people seem to want the default branch switch to happen this
	release.

So I dunno. I think my opinion leans on not changing the default branch at all. Since it seems like the consensus is generally that it _will_ change, I think I would prefer options 3, 2 and 1 in that order.

Thoughts?
Johannes Schindelin· Jun 23, 2020, 20:10 UTC · re: Denton Liu · lore

Re: [PATCH 0/9] Allow overriding the default name of the default branch

Hi Denton,
On Mon, 15 Jun 2020, Denton Liu wrote:
Show 88 quoted lines
> On Mon, Jun 15, 2020 at 12:26:03AM +0200, Johannes Schindelin wrote:
> > > For example, my vim plugins are submodules in the '~/.vim/bundle'
> > > directory. When I want to update them, I run:
> > >
> > >   git submodule foreach 'git remote update && git reset --hard origin/master'
> > >
> > > With this change hitting a Git release, more and more people would call
> > > their main branch different names they like. So what is the recommended
> > > way to do something like this now? How do I checkout the tip of the main
> > > branch? How do I push to the main branch? How do I pull from the main
> > > branch? And so on...
> >
> > ... has less to do with a new Git release, but more with the decision of
> > an existing project to change their main branch name.
> >
> > That's something users already had to deal with, of course. For example,
> > projects switching to the Git Flow model will start to use the main branch
> > name `development`.
>
> I brought this concern up in a parallel thread but I'll bring it up here
> too since it's relevant. Currently, in the .gitmodules file, if the
> branch is not specified, it defaults to 'master'.
>
> When I want to update my vim plugins, I run
> `git submodule update --remote` which pulls in all of my submodules'
> 'master' branches. By convention, a lack of `branch` key in .gitmodules
> conventionally means 'master'.
>
> With your change, it becomes the value of git_main_branch_name(), which
> is fine for now. However, if this value changes to something else, then
> when I update my Git, suddenly `git submodule update --remote` will be
> broken for me as all of the new repositories that I pull will be for an
> incorrect (and possibly missing) branch.
>
> This leaves us in a scenario where one developer running an older
> version of Git would have submodule updates work perfectly fine while a
> developer with a newer version would have it suddenly broken. This might
> be hard to debug, especially for someone who doesn't follow the release
> notes around Git and doesn't realise why the default has suddenly
> changed.
>
> This problem gets much worse if we allow the main branch name to be
> configurable as then the *private* configurations that a developer has
> may have an effect on the *publicly visible* behaviour of a repository.
>
> I think I see three possible solutions to this:
>
> 	1. Special case 'master' in submodules to retain backwards
> 	compatibility.
>
> 	I don't think this is very appealing as if the change is made to
> 	use another default branch name, then the "default" branch for
> 	submodules would be "master" even though the new default
> 	everywhere else would be different. And in the future, someone
> 	who doesn't know the context behind all of this would be very
> 	confused where there are two different default branch names.
>
> 	2. Disable 'update --remote' support for submodules that don't
> 	specify a branch.
>
> 	If Git detects that a branch key is missing when trying to do an
> 	'update --remote', it should just quit out and refuse to do
> 	anything. Of course, this a very backwards incompatible change
> 	and it would require several release cycles to implement where
> 	we warn users about this impending change before we actually
> 	make it happen.
>
> 	3. Make 'update --remote' get HEAD.
>
> 	I argue that this is how it always should've been implemented
> 	but, alas, I can't go back in time and fix it. Regardless, it
> 	might be good to flip this to be the default if we're going to
> 	be making the change anyway.
>
> 	Unfortunately, this suffers from both the problems of 1 and 2.
> 	As with 1, we'll end up in a situation where users with
> 	different versions of Git may experience different behaviours
> 	given the same public repository and I think this is definitely
> 	undesirable. With 2, this change will also require a long
> 	deprecation period which I don't think it compatible with how
> 	people seem to want the default branch switch to happen this
> 	release.
>
> So I dunno. I think my opinion leans on not changing the default branch
> at all. Since it seems like the consensus is generally that it _will_
> change, I think I would prefer options 3, 2 and 1 in that order.
>
> Thoughts?

My intuition matches your preference, and I have a strong preference for 3.

It took some banging my head (not my HEAD...) against the code to convince myself that the patch I prepared for v3 is good: I managed to confuse myself what with all those submodules and clones in t7406.

Ciao, Dscho

brian m. carlson· Jun 15, 2020, 23:10 UTC · re: Pratyush Yadav · lore

Re: [PATCH 0/9] Allow overriding the default name of the default branch

On 2020-06-15 at 10:03:27, Pratyush Yadav wrote:
Show 10 quoted lines
> For example, my vim plugins are submodules in the '~/.vim/bundle'
> directory. When I want to update them, I run:
> 
>   git submodule foreach 'git remote update && git reset --hard origin/master'
> 
> With this change hitting a Git release, more and more people would call
> their main branch different names they like. So what is the recommended
> way to do something like this now? How do I checkout the tip of the main
> branch? How do I push to the main branch? How do I pull from the main
> branch? And so on...

This is a common issue that's long existed but may become more common as people change their branches. I believe when you clone that it by default pulls down a HEAD reference for the remote. So you can use origin/HEAD (a symref) in this case to use the correct default branch, whatever it may be called. Then your code doesn't have to care about the actual name, which is probably better anyway.

If you want to know the actual name, you can use this: git rev-parse --abbrev-ref origin/HEAD.

If the owner of the repository chooses to change that name or if you lack the HEAD reference for a remote, you can fix it with "git remote set-head origin -a".

I'll see if I can find time this week to work up a FAQ entry about how to do this, since it seems to be a common question folks have. I myself wasn't aware of "git remote set-head" until the other day, so I don't expect others to be familiar with it, either.

-- 
brian m. carlson: Houston, Texas, US
OpenPGP: https://keybase.io/bk2204
Johannes Schindelin via GitGitGadget· Jun 15, 2020, 12:50 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v2 00/12] Allow overriding the default name of the default branch

A growing number of open source projects aims to avoid the branch name master due to its negative connotation. See [1] for an existing discussion on this. The links [2], [3], and [4] describe community-driven ways for users to rename their default branches or use template edits to set a new default branch name.

[1] https://lore.kernel.org/git/CAOAHyQwyXC1Z3v7BZAC+Bq6JBaM7FvBenA-1fcqeDV==apdWDg@mail.gmail.com/

[2] https://twitter.com/mislav/status/1270388510684598272

[3] https://www.hanselman.com/blog/EasilyRenameYourGitDefaultBranchFromMasterToMain.aspx

[4] https://github.com/ethomson/retarget_prs

By necessity, existing repositories require a lot of manual work to move away from that branch name, but it should be much easier for new repositories.

This patch series allows overriding the branch name being used for new repositories' main branch, as well as telling Git about a renamed main branch in an already-existing repository. The former would be configured via init.defaultBranch and the latter via core.mainBranch (which is now automatically configured in git init).

Shell scripts can find out what the current repository's main branch name is called via

main_branch=$(git config core.mainBranch || echo master)

This is even future proof because all future git init invocations will configure that setting.

The initial patch was started by newcomer Don Goodman-Wilson, as well as the bigger change that morphed into #655, where we demonstrate how to change Git's hard-coded default main branch name to main based on this here patch series, verifying the approach. Thanks for the contribution!

This series DOES NOT change the default automatically, but only provides an opt-in mechanism for interested users. The plan for that is to convert the test scripts incrementally (by introducing GIT_TEST_DEFAULT_MAIN_BRANCH_NAME , which overrides init.defaultBranch, and then converting the tricky test scripts first, one by one, using that environment variable).

Changes since v1:
 * The modifications to respect GIT_TEST_DEFAULT_BRANCH_NAME have been
   backed out from this patch series, as they are only relevant once we
   start converting the test suite to accommodate for a new default main
   branch name.
   
   
 * An error message that started with an upper-case letter was downcased.
   
   
 * git_default_branch_name()'s logic was simplified by replacing an if ...
   else ... by a ternary assignment.
   
   
 * The git_default_branch_name() function was renamed to 
   git_main_branch_name() and a corresponding repo_main_branch_name() was
   introduced.
   
   
 * The "init" commit message's first paragraph now elaborates a little bit
   on the reasoning why projects want to move away from the current default
   branch name.
   
   
 * The "init" commit was split into two.
   
   
 * There are now two config settings: init.defaultBranch (defining the
   branch name to use when initializing new repositories) and 
   core.mainBranch (which is now configured by init_db(), declaring what the
   name of the main branch is in this repository).
   
   
 * The commits were re-ordered to introduce the concept of core.mainBranch 
   first because technically, this is something that we could do even
   without changing git init at all.
   
   
 * git fast-export --anonymize now always uses the ref name ref0 for the
   main branch, no matter whether it was overridden or whether the fall-back
   is in effect.
   
   
 * The code comment regarding anonymizing the main branch to ref0 in git
   fast-export --anonymize was enhanced.
   
   
 * A new patch was added to rename core.mainBranch if the main branch is
   renamed via git branch -m.
   
   
 * Added a patch that introduces support for git init
   --main-branch=<branch-name>.
   
   
 * Where possible, I added tests (although I did not try to extend test
   coverage to all changes: the send-pack.c/transport-helper.c patch only
   adds a test for the send-pack.c adjustment, for example).
Don Goodman-Wilson (1):
  init: allow overriding the default main branch name via the config
Johannes Schindelin (10):
  fmt-merge-msg: introduce a way to override the main branch name
  send-pack/transport-helper: respect `core.mainBranch`
  git_main_branch_name(): optionally report the full ref name
  fast-export: handle overridden main branch names correctly
  branch -m: adjust `core.mainBranch` if necessary
  init: allow specifying the main branch name for the new repository
  clone: handle overridden main branch names
  remote: learn about the possibly-overridden default main branch name
  submodule: use the correct default for the main branch name
  testsvn: respect `init.defaultBranch`
Junio C Hamano (1):
  fast-export: do anonymize the primary branch name
 Documentation/config/core.txt    |  5 +++++
 Documentation/config/init.txt    |  4 ++++
 Documentation/git-init.txt       |  7 +++++++
 builtin/branch.c                 |  9 ++++++++
 builtin/clone.c                  | 19 +++++++++++++----
 builtin/fast-export.c            | 20 +++++++++++++-----
 builtin/init-db.c                | 36 +++++++++++++++++++++++++-------
 builtin/submodule--helper.c      | 10 +++++++--
 cache.h                          |  2 +-
 fmt-merge-msg.c                  |  6 ++++--
 refs.c                           | 34 ++++++++++++++++++++++++++++++
 refs.h                           | 15 +++++++++++++
 remote-testsvn.c                 | 12 ++++++++---
 remote.c                         | 15 ++++++++-----
 send-pack.c                      |  6 +++++-
 t/t0001-init.sh                  | 31 +++++++++++++++++++++++++++
 t/t3200-branch.sh                |  9 ++++++++
 t/t5528-push-default.sh          |  7 +++++++
 t/t5606-clone-options.sh         | 26 +++++++++++++++++++++++
 t/t6200-fmt-merge-msg.sh         |  7 +++++++
 t/t7406-submodule-update.sh      |  7 +++++++
 t/t9020-remote-svn.sh            |  6 ++++++
 t/t9351-fast-export-anonymize.sh | 15 +++++++++----
 transport-helper.c               |  6 +++++-
 24 files changed, 279 insertions(+), 35 deletions(-)
base-commit: 0313f36c6ebecb3bffe6f15cf25a4883100f0214
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-656%2Fdscho%2Fdefault-branch-name-option-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-656/dscho/default-branch-name-option-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/656
Range-diff vs v1:
  -:  ----------- >  1:  ebd10f73cd7 fast-export: do anonymize the primary branch name
  7:  e849def4a8c !  2:  f4d54739153 fmt-merge-msg: learn about the possibly-configured default branch name
     @@ Metadata
      Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
      
       ## Commit message ##
     -    fmt-merge-msg: learn about the possibly-configured default branch name
     +    fmt-merge-msg: introduce a way to override the main branch name
      
     -    When formatting the commit message for merge commits, Git appends "into
     -    <branch-name>" unless the current branch is the default branch.
     +    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).
      
     -    Now that we can configure what the default branch name should be, we
     -    will want to respect that setting in that scenario rather than using the
     -    compiled-in default branch name.
     +    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 (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 <johannes.schindelin@gmx.de>
      
     + ## Documentation/config/core.txt ##
     +@@ Documentation/config/core.txt: 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.
     +
       ## fmt-merge-msg.c ##
      @@ fmt-merge-msg.c: static void fmt_merge_msg_title(struct strbuf *out,
       				const char *current_branch)
       {
       	int i = 0;
      -	char *sep = "";
     -+	char *sep = "", *default_branch_name;
     ++	char *sep = "", *main_branch;
       
       	strbuf_addstr(out, "Merge ");
       	for (i = 0; i < srcs.nr; i++) {
     @@ fmt-merge-msg.c: static void fmt_merge_msg_title(struct strbuf *out,
       	}
       
      -	if (!strcmp("master", current_branch))
     -+	default_branch_name = git_default_branch_name(1);
     -+	if (!strcmp(default_branch_name, 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(default_branch_name);
     ++	free(main_branch);
       }
       
       static void fmt_tag_signature(struct strbuf *tagbuf,
      
     + ## refs.c ##
     +@@ refs.c: 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);
     ++
     ++	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
     +
     + ## refs.h ##
     +@@ refs.h: 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
     ++ * 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.
     +
       ## t/t6200-fmt-merge-msg.sh ##
      @@ t/t6200-fmt-merge-msg.sh: test_expect_success 'setup FETCH_HEAD' '
       	git fetch . left
       '
       
      +test_expect_success 'with overridden default branch name' '
     -+	test_config core.defaultBranchName default &&
      +	test_when_finished "git switch master" &&
      +	git switch -c default &&
     -+	git fmt-merge-msg <.git/FETCH_HEAD >actual &&
     ++	git -c core.mainBranch=default fmt-merge-msg <.git/FETCH_HEAD >actual &&
      +	! grep "into default" actual
      +'
      +
  3:  c9c9c81068e !  3:  bd8af3755ad send-pack/transport-helper: respect `core.defaultBranchName`
     @@ Metadata
      Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
      
       ## Commit message ##
     -    send-pack/transport-helper: respect `core.defaultBranchName`
     +    send-pack/transport-helper: respect `core.mainBranch`
      
     -    When mentioning the default branch name in an error message, we want to
     -    go with the preference specified by the user.
     +    When mentioning the main branch name in an error message, we want to go
     +    with the preference specified by the user, only falling back to Git's
     +    own, hard-coded default when none was configured explicitly.
      
          Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
      
     @@ send-pack.c: int send_pack(struct send_pack_args *args,
       	}
       
       	if (!remote_refs) {
     -+		char *branch_name = git_default_branch_name(1);
     ++		char *branch_name = git_main_branch_name();
      +
       		fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
      -			"Perhaps you should specify a branch such as 'master'.\n");
     @@ send-pack.c: int send_pack(struct send_pack_args *args,
       	}
       	if (args->atomic && !atomic_supported)
      
     + ## t/t5528-push-default.sh ##
     +@@ t/t5528-push-default.sh: test_expect_success 'push from/to new branch with upstream, matching and simple'
     + 	test_push_failure upstream
     + '
     + 
     ++test_expect_success '"matching" fails if none match' '
     ++	git init --bare empty &&
     ++	test_must_fail git -c core.mainBranch=unmatch push empty : 2>actual &&
     ++	needle="Perhaps you should specify a branch such as '\''unmatch'\''" &&
     ++	test_i18ngrep "$needle" actual
     ++'
     ++
     + test_expect_success 'push ambiguously named branch with upstream, matching and simple' '
     + 	git checkout -b ambiguous &&
     + 	test_config branch.ambiguous.remote parent1 &&
     +
       ## transport-helper.c ##
      @@ transport-helper.c: static int push_refs(struct transport *transport,
       	}
       
       	if (!remote_refs) {
     -+		char *branch_name = git_default_branch_name(1);
     ++		char *branch_name = git_main_branch_name();
      +
       		fprintf(stderr,
       			_("No refs in common and none specified; doing nothing.\n"
  -:  ----------- >  4:  ca1c63c3e01 git_main_branch_name(): optionally report the full ref name
  8:  1efe848f2b0 !  5:  a3be4f39aa2 fast-export: respect the possibly-overridden default branch name
     @@ Metadata
      Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
      
       ## Commit message ##
     -    fast-export: respect the possibly-overridden default branch name
     +    fast-export: handle overridden main branch names correctly
      
     -    When anonymizing commit history, we are careful to leave the branch name
     -    of the default branch alone.
     +    When anonymizing commit history, we are careful to translate the main
     +    branch name to `ref0`.
      
     -    When the default branch name is overridden via the config or via the
     -    environment variable, we will want `git fast-export` to use that
     -    overridden name instead.
     +    When the main branch name is overridden via the config, we will want
     +    `git fast-export` to use that overridden name instead.
      
          Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
      
     @@ builtin/fast-export.c: static const char *anonymize_refname(const char *refname)
       	};
       	static struct hashmap refs;
       	static struct strbuf anon = STRBUF_INIT;
     -+	static char *default_branch_name;
     ++	static char *main_branch;
       	int i;
       
       	/*
     --	 * We also leave "master" as a special case, since it does not reveal
     --	 * anything interesting.
     -+	 * We also leave the default branch name as a special case, since it
     -+	 * does not reveal anything interesting.
     + 	 * In certain circumstances, it might be interesting to be able to
     + 	 * identify the main branch. For that reason, let's force its name to
     + 	 * be anonymized to `ref0`.
     ++	 *
     ++	 * While the main branch name might often be `main` for new
     ++	 * repositories (and `master` for aged ones), and such well-known names
     ++	 * may not necessarily need anonymizing, it could be configured to use
     ++	 * a secret word that the user may not want to reveal.
       	 */
      -	if (!strcmp(refname, "refs/heads/master"))
     -+	if (!default_branch_name)
     -+		default_branch_name = git_default_branch_name(0);
     ++	if (!main_branch)
     ++		main_branch = git_main_branch_name(MAIN_BRANCH_FULL_NAME);
      +
     -+	if (!strcmp(refname, default_branch_name))
     - 		return refname;
     ++	if (!strcmp(refname, main_branch))
     + 		return "refs/heads/ref0";
       
       	strbuf_reset(&anon);
     +
     + ## t/t9351-fast-export-anonymize.sh ##
     +@@ t/t9351-fast-export-anonymize.sh: test_expect_success 'stream translates master to ref0' '
     + 	! grep master stream
     + '
     + 
     ++test_expect_success 'respects configured main branch' '
     ++	git -c core.mainBranch=does-not-exist \
     ++		fast-export --anonymize --all >stream-without-ref0 &&
     ++	! grep ref0 stream-without-ref0
     ++'
     ++
     + test_expect_success 'stream omits other refnames' '
     + 	! grep other stream &&
     + 	! grep mytag stream
  -:  ----------- >  6:  933e314813d branch -m: adjust `core.mainBranch` if necessary
  1:  90912e32da1 !  7:  0ec04b2086e init: allow overriding the default branch name for new repositories
     @@
       ## Metadata ##
     -Author: Don Goodman-Wilson <don@goodman-wilson.com>
     +Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
      
       ## Commit message ##
     -    init: allow overriding the default branch name for new repositories
     +    init: allow specifying the main branch name for the new repository
      
          There is a growing number of projects trying to avoid the non-inclusive
     -    name `master` in their repositories. For existing repositories, this
     -    requires manual work. For new repositories, the only way to do that
     -    automatically is by copying all of Git's template directory, then
     -    hard-coding the desired default branch name into the `.git/HEAD` file,
     -    and then configuring `init.templateDir` to point to those copied
     +    name `master` in their repositories: The `master`/`slave` terminology is
     +    insensitive and perpetuates injustice. This `master`/`slave` idea is
     +    actually where Git's naming comes from, as it was inherited from
     +    BitKeeper which uses the term in exactly this way, see
     +    https://mail.gnome.org/archives/desktop-devel-list/2019-May/msg00066.html
     +
     +    To change that branch name for new repositories, currently the only way
     +    to do that automatically is by copying all of Git's template directory,
     +    then hard-coding the desired default branch name into the `.git/HEAD`
     +    file, and then configuring `init.templateDir` to point to those copied
          template files.
      
     -    To make this process much less cumbersome, let's introduce support for
     -    `core.defaultBranchName`. That way, users won't need to keep their
     -    copied template files up to date, and won't interfere with default hooks
     -    installed by their administrators.
     +    To make this process much less cumbersome, let's introduce a new option:
     +    `--main-branch=<branch-name>`.
      
     -    While at it, also let users set the default branch name via the
     -    environment variable `GIT_TEST_DEFAULT_BRANCH_NAME`, in preparation for
     -    adjusting Git's test suite to a more inclusive default branch name. As
     -    is common in Git, the `GIT_TEST_*` variable takes precedence over the
     -    config setting.
     +    This will not only initialize the repository with the specified initial
     +    branch; It will also record that branch name in `core.mainBranch`.
      
     -    Note: we use the prefix `core.` instead of `init.` because we want to
     -    adjust also `git clone`, `git fmt-merge-msg` and other commands over the
     -    course of the next commits to respect this setting.
     +    Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
      
     -    Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
     -    Helped-by: Derrick Stolee <dstolee@microsoft.com>
     -    Signed-off-by: Don Goodman-Wilson <don@goodman-wilson.com>
     + ## Documentation/git-init.txt ##
     +@@ Documentation/git-init.txt: SYNOPSIS
     + [verse]
     + 'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
     + 	  [--separate-git-dir <git dir>] [--object-format=<format]
     ++	  [-b <branch-name> | --main-branch=<branch-name>]
     + 	  [--shared[=<permissions>]] [directory]
     + 
     + 
     +@@ Documentation/git-init.txt: repository.
     + +
     + If this is reinitialization, the repository will be moved to the specified path.
     + 
     ++-b <branch-name::
     ++--main-branch=<branch-name>::
     ++
     ++Use the specified name for the main (or: initial) branch in the newly created
     ++repository. If not specified, fall back to the default name: `master`.
     ++
     + --shared[=(false|true|umask|group|all|world|everybody|0xxx)]::
     + 
     + Specify that the Git repository is to be shared amongst several users.  This
     +
     + ## builtin/clone.c ##
     +@@ builtin/clone.c: int cmd_clone(int argc, const char **argv, const char *prefix)
     + 		}
     + 	}
     + 
     +-	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, INIT_DB_QUIET);
     ++	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL,
     ++		INIT_DB_QUIET);
     + 
     + 	if (real_git_dir)
     + 		git_dir = real_git_dir;
      
       ## builtin/init-db.c ##
     +@@ builtin/init-db.c: void initialize_repository_version(int hash_algo)
     + 
     + static int create_default_files(const char *template_path,
     + 				const char *original_git_dir,
     ++				const char *main_branch,
     + 				const struct repository_format *fmt)
     + {
     + 	struct stat st1;
      @@ builtin/init-db.c: static int create_default_files(const char *template_path,
       		die("failed to set up refs db: %s", err.buf);
       
     @@ builtin/init-db.c: static int create_default_files(const char *template_path,
       		  || readlink(path, junk, sizeof(junk)-1) != -1);
       	if (!reinit) {
      -		if (create_symref("HEAD", "refs/heads/master", NULL) < 0)
     -+		char *default_ref = git_default_branch_name(0);
     -+		if (create_symref("HEAD", default_ref, NULL) < 0)
     ++		char *ref;
     ++
     ++		if (!main_branch)
     ++			main_branch = "master";
     ++
     ++		ref = xstrfmt("refs/heads/%s", main_branch);
     ++		if (check_refname_format(ref, 0) < 0)
     ++			die(_("invalid main branch name: '%s'"), main_branch);
     ++
     ++		if (create_symref("HEAD", ref, NULL) < 0)
       			exit(1);
     -+		free(default_ref);
     - 	}
     +-	}
     ++		free(ref);
     ++
     ++		git_config_set("core.mainbranch", main_branch);
     ++	} else if (main_branch)
     ++		warning(_("re-init: ignoring --main-branch=%s"), main_branch);
       
       	initialize_repository_version(fmt->hash_algo);
     -
     - ## refs.c ##
     -@@ refs.c: void expand_ref_prefix(struct argv_array *prefixes, const char *prefix)
     - 		argv_array_pushf(prefixes, *p, len, prefix);
     + 
     +@@ builtin/init-db.c: static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash
       }
       
     -+char *git_default_branch_name(int short_name)
     -+{
     -+	const char *branch_name = getenv("GIT_TEST_DEFAULT_BRANCH_NAME");
     -+	char *from_config = NULL, *prefixed;
     -+
     -+	/*
     -+	 * If the default branch name was not specified via the environment
     -+	 * variable GIT_TEST_DEFAULT_BRANCH_NAME, retrieve it from the config
     -+	 * setting core.defaultBranchName. If neither are set, fall back to the
     -+	 * hard-coded default.
     -+	 */
     -+	if (!branch_name || !*branch_name) {
     -+		if (git_config_get_string("core.defaultbranchname",
     -+					  &from_config) < 0)
     -+			die(_("Could not retrieve `core.defaultBranchName`"));
     -+
     -+		if (from_config)
     -+			branch_name = from_config;
     -+		else
     -+			branch_name = "master";
     -+	}
     -+
     -+	if (short_name)
     -+		return from_config ? from_config : xstrdup(branch_name);
     -+
     -+	/* prepend "refs/heads/" to the branch name */
     -+	prefixed = xstrfmt("refs/heads/%s", branch_name);
     -+	if (check_refname_format(prefixed, 0))
     -+		die(_("invalid default branch name: '%s'"), branch_name);
     -+
     -+	free(from_config);
     -+	return prefixed;
     -+}
     -+
     - /*
     -  * *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
     + int init_db(const char *git_dir, const char *real_git_dir,
     +-	    const char *template_dir, int hash, unsigned int flags)
     ++	    const char *template_dir, int hash, const char *main_branch,
     ++	    unsigned int flags)
     + {
     + 	int reinit;
     + 	int exist_ok = flags & INIT_DB_EXIST_OK;
     +@@ builtin/init-db.c: int init_db(const char *git_dir, const char *real_git_dir,
     + 
     + 	validate_hash_algorithm(&repo_fmt, hash);
     + 
     +-	reinit = create_default_files(template_dir, original_git_dir, &repo_fmt);
     ++	reinit = create_default_files(template_dir, original_git_dir,
     ++				      main_branch, &repo_fmt);
     + 
     + 	create_object_directory();
     + 
     +@@ builtin/init-db.c: int cmd_init_db(int argc, const char **argv, const char *prefix)
     + 	const char *template_dir = NULL;
     + 	unsigned int flags = 0;
     + 	const char *object_format = NULL;
     ++	const char *main_branch = NULL;
     + 	int hash_algo = GIT_HASH_UNKNOWN;
     + 	const struct option init_db_options[] = {
     + 		OPT_STRING(0, "template", &template_dir, N_("template-directory"),
     +@@ builtin/init-db.c: int cmd_init_db(int argc, const char **argv, const char *prefix)
     + 		OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET),
     + 		OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
     + 			   N_("separate git dir from working tree")),
     ++		OPT_STRING('b', "main-branch", &main_branch, N_("name"),
     ++			   N_("override the name of the main branch")),
     + 		OPT_STRING(0, "object-format", &object_format, N_("hash"),
     + 			   N_("specify the hash algorithm to use")),
     + 		OPT_END()
     +@@ builtin/init-db.c: int cmd_init_db(int argc, const char **argv, const char *prefix)
     + 	UNLEAK(work_tree);
     + 
     + 	flags |= INIT_DB_EXIST_OK;
     +-	return init_db(git_dir, real_git_dir, template_dir, hash_algo, flags);
     ++	return init_db(git_dir, real_git_dir, template_dir, hash_algo,
     ++		       main_branch, flags);
     + }
      
     - ## refs.h ##
     -@@ refs.h: 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 default branch. If `short_name` is non-zero, the
     -+ * branch name will be prefixed with "refs/heads/".
     -+ */
     -+char *git_default_branch_name(int short_name);
     -+
     - /*
     -  * A ref_transaction represents a collection of reference updates that
     -  * should succeed or fail together.
     + ## cache.h ##
     +@@ cache.h: int path_inside_repo(const char *prefix, const char *path);
     + 
     + int init_db(const char *git_dir, const char *real_git_dir,
     + 	    const char *template_dir, int hash_algo,
     +-	    unsigned int flags);
     ++	    const char *main_branch, unsigned int flags);
     + void initialize_repository_version(int hash_algo);
     + 
     + void sanitize_stdfds(void);
      
       ## t/t0001-init.sh ##
      @@ t/t0001-init.sh: test_expect_success MINGW 'redirect std handles' '
       	grep "Needed a single revision" output.txt
       '
       
     -+test_expect_success 'custom default branch name from config' '
     -+	git config --global core.defaultbranchname nmb &&
     -+	GIT_TEST_DEFAULT_BRANCH_NAME= git init custom-config &&
     -+	git config --global --unset core.defaultbranchname &&
     -+	git -C custom-config symbolic-ref HEAD >actual &&
     -+	grep nmb actual
     -+'
     -+
     -+test_expect_success 'custom default branch name from env' '
     -+	GIT_TEST_DEFAULT_BRANCH_NAME=nmb git init custom-env &&
     -+	git -C custom-env symbolic-ref HEAD >actual &&
     -+	grep nmb actual
     -+'
     ++test_expect_success '--main-branch' '
     ++	git init --main-branch=hello main-branch-option &&
     ++	git -C main-branch-option symbolic-ref HEAD >actual &&
     ++	echo refs/heads/hello >expect &&
     ++	test_cmp expect actual &&
      +
     -+test_expect_success 'invalid custom default branch name' '
     -+	test_must_fail env GIT_TEST_DEFAULT_BRANCH_NAME="with space" \
     -+		git init custom-invalid 2>err &&
     -+	test_i18ngrep "invalid default branch name" err
     ++	: re-initializing should not change the main branch name &&
     ++	git init --main-branch=ignore main-branch-option 2>err &&
     ++	test_i18ngrep "ignoring --main-branch" err &&
     ++	git -C main-branch-option symbolic-ref HEAD >actual &&
     ++	grep hello actual &&
     ++	git -C main-branch-option config core.mainBranch >actual &&
     ++	grep hello actual
      +'
      +
       test_done
  -:  ----------- >  8:  c711eba7e76 init: allow overriding the default main branch name via the config
  6:  cce86c06bbf !  9:  0e59b618169 clone: learn about the possibly-configured default branch name
     @@ Metadata
      Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
      
       ## Commit message ##
     -    clone: learn about the possibly-configured default branch name
     +    clone: handle overridden main branch names
      
          When cloning a repository without any branches, Git chooses a default
          branch name for the as-yet unborn branch.
      
     -    Now that we can configure what the default branch name should be, we
     -    will want `git clone` to respect that setting.
     +    As part of the implicit initialization of the local repository, Git
     +    just learned to respect `init.defaultBranch` to choose a different main
     +    branch name. We now really want that branch name to be used as a
     +    fall-back.
     +
     +    At the same time, we also want to make sure that `core.mainBranch` is
     +    set correctly, reflecting the name of the main branch. In case we detect
     +    a main branch, we do have to do that explicitly, otherwise `init_db()`
     +    will already have done that for us.
      
          Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
      
     + ## Documentation/config/init.txt ##
     +@@ Documentation/config/init.txt: init.templateDir::
     + 	(See the "TEMPLATE DIRECTORY" section of linkgit:git-init[1].)
     + 
     + init.defaultBranch::
     +-	Allows overriding the default branch name when initializing
     +-	a new repository.
     ++	Allows overriding the default branch name e.g. when initializing
     ++	a new repository or when cloning an empty repository.
     +
       ## builtin/clone.c ##
     +@@ builtin/clone.c: static void update_head(const struct ref *our, const struct ref *remote,
     + 		/* Local default branch link */
     + 		if (create_symref("HEAD", our->name, NULL) < 0)
     + 			die(_("unable to update HEAD"));
     ++		git_config_set("core.mainbranch", head);
     + 		if (!option_bare) {
     + 			update_ref(msg, "HEAD", &our->old_oid, NULL, 0,
     + 				   UPDATE_REFS_DIE_ON_ERR);
      @@ builtin/clone.c: int cmd_clone(int argc, const char **argv, const char *prefix)
       		remote_head_points_at = NULL;
       		remote_head = NULL;
     @@ builtin/clone.c: int cmd_clone(int argc, const char **argv, const char *prefix)
      -			install_branch_config(0, "master", option_origin,
      -					      "refs/heads/master");
      +		if (!option_bare) {
     -+			char *default_branch = git_default_branch_name(0);
     ++			char *main_branch =
     ++				git_main_branch_name(MAIN_BRANCH_FULL_NAME);
      +			const char *nick;
      +
     -+			if (!skip_prefix(default_branch, "refs/heads/", &nick))
     ++			if (!skip_prefix(main_branch, "refs/heads/", &nick))
      +				BUG("unexpected default branch '%s'",
     -+				    default_branch);
     ++				    main_branch);
      +			install_branch_config(0, nick, option_origin,
     -+					      default_branch);
     -+			free(default_branch);
     ++					      main_branch);
     ++			free(main_branch);
      +		}
       	}
       
       	write_refspec_config(src_ref_prefix, our_head_points_at,
      
     - ## t/t5609-clone-branch.sh ##
     -@@ t/t5609-clone-branch.sh: test_expect_success 'clone -b not allowed with empty repos' '
     - 	test_must_fail git clone -b branch empty clone-branch-empty
     + ## t/t5606-clone-options.sh ##
     +@@ t/t5606-clone-options.sh: test_expect_success 'redirected clone -v does show progress' '
     + 
       '
       
     -+test_expect_success 'chooses correct default branch name' '
     -+	GIT_TEST_DEFAULT_BRANCH_NAME= \
     -+		git -c core.defaultBranchName=up clone empty whats-up &&
     -+	test_write_lines refs/heads/up refs/heads/up >expect &&
     -+	git -C whats-up symbolic-ref HEAD >actual &&
     -+	git -C whats-up config branch.up.merge >>actual &&
     -+	test_cmp expect actual
     ++test_expect_success 'chooses correct default main branch name' '
     ++	git init --bare empty &&
     ++	git -c init.defaultBranch=up clone empty whats-up &&
     ++	test refs/heads/up = $(git -C whats-up symbolic-ref HEAD) &&
     ++	test up = $(git -C whats-up config core.mainBranch) &&
     ++	test refs/heads/up = $(git -C whats-up config branch.up.merge)
     ++'
     ++
     ++test_expect_success 'guesses main branch name correctly' '
     ++	git init --main-branch=guess main-branch &&
     ++	test_commit -C main-branch no-spoilers &&
     ++	git -C main-branch branch abc guess &&
     ++	git clone main-branch is-it &&
     ++	test guess = $(git -C is-it config core.mainBranch) &&
     ++	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD)
      +'
      +
       test_done
  2:  06a2cea051c ! 10:  59b8f4cfbb2 remote: respect `core.defaultBranchName`
     @@ Metadata
      Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
      
       ## Commit message ##
     -    remote: respect `core.defaultBranchName`
     +    remote: learn about the possibly-overridden default main branch name
      
          When guessing the default branch name of a remote, and there are no refs
          to guess from, we want to go with the preference specified by the user
     -    for the fall-back.
     +    for the fall-back, i.e. the default name to be used for the main branch
     +    of new repositories (because as far as the user is concerned, a remote
     +    that has no branches yet is a new repository).
      
          Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
      
     @@ remote.c: static void read_remotes_file(struct remote *remote)
       static void read_branches_file(struct remote *remote)
       {
      -	char *frag;
     -+	char *frag, *default_branch_name = NULL;
     ++	char *frag, *main_branch = NULL;
       	struct strbuf buf = STRBUF_INIT;
       	FILE *f = fopen_or_warn(git_path("branches/%s", remote->name), "r");
       
     @@ remote.c: static void read_branches_file(struct remote *remote)
       	/*
       	 * The branches file would have URL and optionally
      -	 * #branch specified.  The "master" (or specified) branch is
     -+	 * #branch specified.  The default (or specified) branch is
     ++	 * #branch specified.  The main (or specified) branch is
       	 * fetched and stored in the local branch matching the
       	 * remote name.
       	 */
     @@ remote.c: static void read_branches_file(struct remote *remote)
       		*(frag++) = '\0';
       	else
      -		frag = "master";
     -+		frag = default_branch_name = git_default_branch_name(1);
     ++		frag = main_branch = git_main_branch_name(MAIN_BRANCH_FOR_INIT);
       
       	add_url_alias(remote, strbuf_detach(&buf, NULL));
       	strbuf_addf(&buf, "refs/heads/%s:refs/heads/%s",
     @@ remote.c: static void read_branches_file(struct remote *remote)
       	strbuf_addf(&buf, "HEAD:refs/heads/%s", frag);
       	refspec_append(&remote->push, buf.buf);
       	remote->fetch_tags = 1; /* always auto-follow */
     -+	free(default_branch_name);
     ++	free(main_branch);
       	strbuf_release(&buf);
       }
       
      @@ remote.c: struct ref *guess_remote_head(const struct ref *head,
     + 	if (head->symref)
     + 		return copy_ref(find_ref_by_name(refs, head->symref));
       
     - 	/* If refs/heads/master could be right, it is. */
     +-	/* If refs/heads/master could be right, it is. */
     ++	/* If a remote branch exists with the main branch name, let's use it. */
       	if (!all) {
      -		r = find_ref_by_name(refs, "refs/heads/master");
     -+		char *name = git_default_branch_name(0);
     ++		char *name = git_main_branch_name(MAIN_BRANCH_FULL_NAME |
     ++						  MAIN_BRANCH_FOR_INIT);
      +
      +		r = find_ref_by_name(refs, name);
      +		free(name);
       		if (r && oideq(&r->old_oid, &head->old_oid))
       			return copy_ref(r);
       	}
     +
     + ## t/t5606-clone-options.sh ##
     +@@ t/t5606-clone-options.sh: test_expect_success 'guesses main branch name correctly' '
     + 	git -C main-branch branch abc guess &&
     + 	git clone main-branch is-it &&
     + 	test guess = $(git -C is-it config core.mainBranch) &&
     +-	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD)
     ++	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD) &&
     ++
     ++	git -c init.defaultBranch=none init --bare no-head &&
     ++	git -C main-branch push ../no-head guess abc &&
     ++	git clone no-head is-it2 &&
     ++	test_must_fail git -C is-it2 symbolic-ref refs/remotes/origin/HEAD &&
     ++	git -C no-head update-ref --no-deref HEAD refs/heads/guess &&
     ++	git -c init.defaultBranch=guess clone no-head is-it3 &&
     ++	test refs/remotes/origin/guess = \
     ++		$(git -C is-it3 symbolic-ref refs/remotes/origin/HEAD)
     + '
     + 
     + test_done
  5:  06ef42052d5 ! 11:  59d6267f099 submodule: use the (possibly overridden) default branch name
     @@ Metadata
      Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
      
       ## Commit message ##
     -    submodule: use the (possibly overridden) default branch name
     +    submodule: use the correct default for the main branch name
      
          To allow for overriding the default branch name, we have introduced a
          config setting. With this patch, the `git submodule` command learns
     @@ builtin/submodule--helper.c: static const char *remote_submodule_branch(const ch
      -	if (!branch)
      -		return "master";
      +	if (!branch) {
     -+		static char *default_branch;
     ++		static char *fall_back;
      +
     -+		if (!default_branch)
     -+			default_branch = git_default_branch_name(1);
     ++		if (!fall_back)
     ++			fall_back = git_main_branch_name(MAIN_BRANCH_FOR_INIT);
      +
     -+		return default_branch;
     ++		return fall_back;
      +	}
       
       	if (!strcmp(branch, ".")) {
       		const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
     +
     + ## t/t7406-submodule-update.sh ##
     +@@ t/t7406-submodule-update.sh: test_expect_success 'setup a submodule tree' '
     + 	)
     + '
     + 
     ++test_expect_success 'update --remote uses configured default main branch' '
     ++	git clone super main-branch &&
     ++	test_must_fail git -C main-branch -c init.defaultBranch=hello \
     ++		submodule update --init --remote submodule 2>err &&
     ++	test_i18ngrep origin/hello err
     ++'
     ++
     + test_expect_success 'submodule update detaching the HEAD ' '
     + 	(cd super/submodule &&
     + 	 git reset --hard HEAD~1
  4:  73cb567cd33 ! 12:  e09f857f068 testsvn: respect `core.defaultBranchName`
     @@ Metadata
      Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
      
       ## Commit message ##
     -    testsvn: respect `core.defaultBranchName`
     +    testsvn: respect `init.defaultBranch`
      
     -    Since the default branch name can now be configured, the `testsvn`
     -    remote helper needs to be told about it.
     +    The default name of the main branch in new repositories can now be
     +    configured. The `testsvn` remote helper translates the remote Subversion
     +    repository's branch name `trunk` to the hard-coded name `master`.
     +    Clearly, the intention was to make the name align with Git's detaults.
     +
     +    So while we are not talking about a newly-created repository in the
     +    `testsvn` context, it _still_ makes sense to use the overridden default
     +    name for the main branch whenever users configured it.
      
          Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
      
     @@ remote-testsvn.c: int cmd_main(int argc, const char **argv)
       			notes_ref_sb = STRBUF_INIT;
       	static struct remote *remote;
      -	const char *url_in;
     -+	const char *url_in, *default_branch;
     ++	const char *url_in, *remote_ref_short;
       
       	setup_git_directory();
       	if (argc < 2 || argc > 3) {
     @@ remote-testsvn.c: int cmd_main(int argc, const char **argv)
       		return 1;
       	}
       
     -+	remote_ref = git_default_branch_name(0);
     -+	if (!skip_prefix(remote_ref, "refs/heads/", &default_branch))
     ++	remote_ref = git_main_branch_name(MAIN_BRANCH_FULL_NAME |
     ++					  MAIN_BRANCH_FOR_INIT);
     ++	if (!skip_prefix(remote_ref, "refs/heads/", &remote_ref_short))
      +		BUG("unexpected remote_ref '%s'", remote_ref);
      +
       	remote = remote_get(argv[1]);
     @@ remote-testsvn.c: int cmd_main(int argc, const char **argv)
       
      -	strbuf_addf(&private_ref_sb, "refs/svn/%s/master", remote->name);
      +	strbuf_addf(&private_ref_sb, "refs/svn/%s/%s",
     -+		    remote->name, default_branch);
     ++		    remote->name, remote_ref_short);
       	private_ref = private_ref_sb.buf;
       
       	strbuf_addf(&notes_ref_sb, "refs/notes/%s/revs", remote->name);
     +
     + ## t/t9020-remote-svn.sh ##
     +@@ t/t9020-remote-svn.sh: test_expect_success REMOTE_SVN 'incremental imports must lead to the same head'
     + 	test_cmp master.good .git/refs/remotes/svnsim/master
     + '
     + 
     ++test_expect_success REMOTE_SVN 'respects configured default main branch' '
     ++	git -c init.defaultBranch=trunk remote add -f trunk \
     ++		"testsvn::file://$TEST_DIRECTORY/t9154/svn.dump" &&
     ++	git rev-parse --verify refs/remotes/trunk/trunk
     ++'
     ++
     + test_debug 'git branch -a'
     + 
     + test_done
  9:  f680e66dd6d <  -:  ----------- Document how the default branch name can be overridden
-- 
gitgitgadget
Junio C Hamano via GitGitGadget· Jun 15, 2020, 12:50 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v2 01/12] fast-export: do anonymize the primary branch name

From: Junio C Hamano <gitster@pobox.com>

In a fast-export stream with --anonymize option, all the end-user data including refnames are munged to prevent exposure, but the 'master' branch is left intact.

There is a comment that explains why it is OK to leave 'master' unanonymized (because everybody calls the primary branch 'master' and it is no secret), but that does not justify why it is bad to anonymize 'master' and make it indistinguishable from other branches. Assuming there _is_ a need to allow the readers of the output to tell where the tip of the primary branch is, let's keep the special casing of 'master', but still anonymize it to "ref0". Because all other branches will be given ref+N where N is a positive integer, this will keep the primary branch identifiable in the output stream, without exposing what the name of the primary branch is in the repository the export stream was taken from.

This is in preparation for introducing a mechanism to affect the name of the primary branch used in the repository. Once the mechanism is in use, the name of the primary branch won't be 'master', and may not be allowed to be exposed.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 builtin/fast-export.c            | 9 +++++----
 t/t9351-fast-export-anonymize.sh | 9 +++++----
 2 files changed, 10 insertions(+), 8 deletions(-)
Show changes to 2 files +10 −8

builtin/fast-export.c, t/t9351-fast-export-anonymize.sh

diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 85868162eec..1072bbf041f 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -497,7 +497,7 @@ static void *anonymize_ref_component(const void *old, size_t *len)
 {
 	static int counter;
 	struct strbuf out = STRBUF_INIT;
-	strbuf_addf(&out, "ref%d", counter++);
+	strbuf_addf(&out, "ref%d", ++counter);
 	return strbuf_detach(&out, len);
 }
 
@@ -518,11 +518,12 @@ static const char *anonymize_refname(const char *refname)
 	int i;
 
 	/*
-	 * We also leave "master" as a special case, since it does not reveal
-	 * anything interesting.
+	 * In certain circumstances, it might be interesting to be able to
+	 * identify the main branch. For that reason, let's force its name to
+	 * be anonymized to `ref0`.
 	 */
 	if (!strcmp(refname, "refs/heads/master"))
-		return refname;
+		return "refs/heads/ref0";
 
 	strbuf_reset(&anon);
 	for (i = 0; i < ARRAY_SIZE(prefixes); i++) {
diff --git a/t/t9351-fast-export-anonymize.sh b/t/t9351-fast-export-anonymize.sh
index 897dc509075..2415f0ec213 100755
--- a/t/t9351-fast-export-anonymize.sh
+++ b/t/t9351-fast-export-anonymize.sh
@@ -26,8 +26,9 @@ test_expect_success 'stream omits path names' '
 	! grep xyzzy stream
 '
 
-test_expect_success 'stream allows master as refname' '
-	grep master stream
+test_expect_success 'stream translates master to ref0' '
+	grep refs/heads/ref0 stream &&
+	! grep master stream
 '
 
 test_expect_success 'stream omits other refnames' '
@@ -57,7 +58,7 @@ test_expect_success 'import stream to new repository' '
 test_expect_success 'result has two branches' '
 	git for-each-ref --format="%(refname)" refs/heads >branches &&
 	test_line_count = 2 branches &&
-	other_branch=$(grep -v refs/heads/master branches)
+	other_branch=$(grep -v refs/heads/ref0 branches)
 '
 
 test_expect_success 'repo has original shape and timestamps' '
@@ -65,7 +66,7 @@ test_expect_success 'repo has original shape and timestamps' '
 		git log --format="%m %ct" --left-right --boundary "$@"
 	} &&
 	(cd .. && shape master...other) >expect &&
-	shape master...$other_branch >actual &&
+	shape ref0...$other_branch >actual &&
 	test_cmp expect actual
 '
 
-- 
gitgitgadget
Jeff King· Jun 16, 2020, 12:58 UTC · re: Junio C Hamano via GitGitGadget · lore

Re: [PATCH v2 01/12] fast-export: do anonymize the primary branch name

On Mon, Jun 15, 2020 at 12:50:05PM +0000, Junio C Hamano via GitGitGadget wrote:
Show 11 quoted lines
> There is a comment that explains why it is OK to leave 'master'
> unanonymized (because everybody calls the primary branch 'master'
> and it is no secret), but that does not justify why it is bad to
> anonymize 'master' and make it indistinguishable from other
> branches.  Assuming there _is_ a need to allow the readers of the
> output to tell where the tip of the primary branch is, let's keep
> the special casing of 'master', but still anonymize it to "ref0".
> Because all other branches will be given ref+N where N is a positive
> integer, this will keep the primary branch identifiable in the
> output stream, without exposing what the name of the primary branch
> is in the repository the export stream was taken from.

I think this is fine. The reason I left "master" as-is in the original is that it is potentially helpful to have an idea of its specialness when reproducing a traversal in the anonymized. I.e., if you know that a bug is shown by "git rev-list master~17..master~3", then you can reproduce it with the same command in the anonymized repo. Losing any idea of where the primary branch is would make that impossible. But with this patch, you can swap it out for "ref0~17", etc, which is OK.

Of course that only helps you for _one_ branch. A more generally useful mechanism would be to teach fast-export to write the ref mapping (and perhaps file mappings, etc) to a separate file. Then you could convert any reproduction recipe to use the anonymized names, and share only that recipe along with the anonymized dump. But that's _way_ outside the scope of your series. This seems like a good interim step to retain the status quo.

-Peff
Junio C Hamano· Jun 17, 2020, 18:16 UTC · re: Jeff King · lore

Re: [PATCH v2 01/12] fast-export: do anonymize the primary branch name

Jeff King <peff@peff.net> writes:
Show 7 quoted lines
> Of course that only helps you for _one_ branch. A more generally useful
> mechanism would be to teach fast-export to write the ref mapping (and
> perhaps file mappings, etc) to a separate file. Then you could convert
> any reproduction recipe to use the anonymized names, and share only that
> recipe along with the anonymized dump. But that's _way_ outside the
> scope of your series. This seems like a good interim step to retain the
> status quo.

Actually, dropping this special case, and dropping the other special case with fmt-merge-msg, we can do without the notion of the "primary" branch.

We still need to have the default name, when user does not specify one, given to the first branch "git init" creates and "git clone" that cannot figure out what the HEAD at the origin points at uses, but one less thing to worry about is always better ;-)

Jeff King· Jun 17, 2020, 21:23 UTC · re: Junio C Hamano · lore

Re: [PATCH v2 01/12] fast-export: do anonymize the primary branch name

On Wed, Jun 17, 2020 at 11:16:05AM -0700, Junio C Hamano wrote:
Show 13 quoted lines
> Jeff King <peff@peff.net> writes:
> 
> > Of course that only helps you for _one_ branch. A more generally useful
> > mechanism would be to teach fast-export to write the ref mapping (and
> > perhaps file mappings, etc) to a separate file. Then you could convert
> > any reproduction recipe to use the anonymized names, and share only that
> > recipe along with the anonymized dump. But that's _way_ outside the
> > scope of your series. This seems like a good interim step to retain the
> > status quo.
> 
> Actually, dropping this special case, and dropping the other special
> case with fmt-merge-msg, we can do without the notion of the
> "primary" branch.

That leaves us in the interim with a "fast-export --anonymize" that is a little harder to use (you have no way to know which branch was which).

But I don't mind at all implementing the map-dumping feature to help move this along. As long as both make it into the same release, then fast-export only gets better, and never regresses. :)

-Peff
Elijah Newren· Jun 18, 2020, 02:06 UTC · re: Jeff King · lore

Re: [PATCH v2 01/12] fast-export: do anonymize the primary branch name

On Wed, Jun 17, 2020 at 2:25 PM Jeff King <peff@peff.net> wrote:
Show 19 quoted lines
>
> On Wed, Jun 17, 2020 at 11:16:05AM -0700, Junio C Hamano wrote:
>
> > Jeff King <peff@peff.net> writes:
> >
> > > Of course that only helps you for _one_ branch. A more generally useful
> > > mechanism would be to teach fast-export to write the ref mapping (and
> > > perhaps file mappings, etc) to a separate file. Then you could convert
> > > any reproduction recipe to use the anonymized names, and share only that
> > > recipe along with the anonymized dump. But that's _way_ outside the
> > > scope of your series. This seems like a good interim step to retain the
> > > status quo.
> >
> > Actually, dropping this special case, and dropping the other special
> > case with fmt-merge-msg, we can do without the notion of the
> > "primary" branch.
>
> That leaves us in the interim with a "fast-export --anonymize" that is a
> little harder to use (you have no way to know which branch was which).

Why does fast-export special case on "master" rather than on HEAD? Isn't it more relevant to know the active branch than what _might_ have been the initial branch? It kind of feels like a bug to me that HEAD isn't the special case construct.

(Speaking as someone whose company a number of years ago had most their big repos and lots of little repos switch their main branch to be named "develop", and in some of those repos deleted "master" but didn't in others. If I had needed some steps to reproduce a problem, and hadn't been on the inside, any special casing from fast-export would make more sense to me to apply to "develop" than to "master".)

> But I don't mind at all implementing the map-dumping feature to help
> move this along. As long as both make it into the same release, then
> fast-export only gets better, and never regresses. :)
Junio C Hamano· Jun 18, 2020, 06:30 UTC · re: Elijah Newren · lore

Re: [PATCH v2 01/12] fast-export: do anonymize the primary branch name

Elijah Newren <newren@gmail.com> writes:
Show 7 quoted lines
>> That leaves us in the interim with a "fast-export --anonymize" that is a
>> little harder to use (you have no way to know which branch was which).
>
> Why does fast-export special case on "master" rather than on HEAD?
> Isn't it more relevant to know the active branch than what _might_
> have been the initial branch?  It kind of feels like a bug to me that
> HEAD isn't the special case construct.

I am torn on that one. Surely HEAD is often the branch that has our current attention. It may well be what we are exporting and we may want to see the topology formed by other refs relative to it.

On the other hand, the current branch may not necessarily be what we are exporting. Historically a project has a single branch that is the focus of most users' attention when they talk about the general state of the project's progress, so it is understandable to expect that the topology may want to be seen relative to that one central line of development.

Show 6 quoted lines
> (Speaking as someone whose company a number of years ago had most
> their big repos and lots of little repos switch their main branch to
> be named "develop", and in some of those repos deleted "master" but
> didn't in others.  If I had needed some steps to reproduce a problem,
> and hadn't been on the inside, any special casing from fast-export
> would make more sense to me to apply to "develop" than to "master".)

Yes, absolutely. You either check "develop" out temporarily just to take anonymized export to make "develop" discoverable in the output, or you would have set core.primaryBranch to "develop" once sometime in the past to tell Git that "develop" is that special one, not "master", so you can take such an export from any branch. As the anonymized export is primarily/solely a debugging aid, convenience would not be of much value, but the latter feels more convenient to me.

Elijah Newren· Jun 18, 2020, 07:13 UTC · re: Junio C Hamano · lore

Re: [PATCH v2 01/12] fast-export: do anonymize the primary branch name

Hi Junio,
On Wed, Jun 17, 2020 at 11:30 PM Junio C Hamano <gitster@pobox.com> wrote:
Show 21 quoted lines
>
> Elijah Newren <newren@gmail.com> writes:
>
> >> That leaves us in the interim with a "fast-export --anonymize" that is a
> >> little harder to use (you have no way to know which branch was which).
> >
> > Why does fast-export special case on "master" rather than on HEAD?
> > Isn't it more relevant to know the active branch than what _might_
> > have been the initial branch?  It kind of feels like a bug to me that
> > HEAD isn't the special case construct.
>
> I am torn on that one.  Surely HEAD is often the branch that has our
> current attention.  It may well be what we are exporting and we may
> want to see the topology formed by other refs relative to it.
>
> On the other hand, the current branch may not necessarily be what we
> are exporting.  Historically a project has a single branch that is
> the focus of most users' attention when they talk about the general
> state of the project's progress, so it is understandable to expect
> that the topology may want to be seen relative to that one central
> line of development.

I'm trying to understand here, but I feel like I'm missing something. Let me try to explain what I understand and hopefully you can figure out what I'm not seeing...

Regardless of what is mainline and whether or not it is important, users probably trigger their bug when a certain branch is checked out. Their bug may also trigger on other branches, but it at least triggers on one, and some bugs will only trigger on one branch. It seems logical to me that we would want to have the same branch checked out (it's the one most likely to trigger the same issue), and thus identifying the HEAD branch is generally important. (Mainline may be too, I'm merely asserting that HEAD is important at this point.)

If users trigger their bug by providing various revision specifications on the command line that compare multiple branches or something, then we're already in the situation of needing to know how to map more than one reference to anonymized ones in order to be able to replicate their issue. However, knowing the mainline might not even help in this case; we instead need to know the anonymized form of the references they are using, whatever those are, and mainline is only useful if it happens to be one of them.

So, I think HEAD is always useful. Additional references would sometimes be useful, but it's not clear to me that mainline is one of those additional references. Maybe I'm just being dense, and I apologize if so, but under what circumstances does knowing the mainline help with debugging a user issue where an anonymized fast-export is provided?

Show 9 quoted lines
> > (Speaking as someone whose company a number of years ago had most
> > their big repos and lots of little repos switch their main branch to
> > be named "develop", and in some of those repos deleted "master" but
> > didn't in others.  If I had needed some steps to reproduce a problem,
> > and hadn't been on the inside, any special casing from fast-export
> > would make more sense to me to apply to "develop" than to "master".)
>
> Yes, absolutely.  You either check "develop" out temporarily just to
> take anonymized export to make "develop" discoverable in the output,

That makes sense; if the bug triggers while they are on develop then I'd expect them to be on develop when they export. If it triggers on some other branch, I'd expect them to stay on that other branch when they export even if "develop" is the mainline.

> or you would have set core.primaryBranch to "develop" once sometime
> in the past to tell Git that "develop" is that special one, not
> "master", so you can take such an export from any branch.

This doesn't make sense to me. The person who changed the primary branch to "develop" for some repository did so years ago. That individual might not even still be at the company, and even if they are, may well be working on a totally different project (and repository) today. Perhaps that individual set core.primaryBranch at the time, but git-config settings aren't copied by fetch/clone/push, so I don't see how this one helps at all. We could tell all future developers who clone any of these repositories that they also need to set core.primaryBranch when they clone the repo, but that seems super lame to me especially since the odds that any one of them will ever need or benefit from it are approximately 0. And yet, it'll be one of these developers who joined the project long after the switchover who runs into problems and provides fast-export dumps.

It feels like I'm probably just missing something obvious, but I really don't see how the mainline is special here. Please do point out what I'm missing.

Thanks, Elijah

Jeff King· Jun 18, 2020, 11:45 UTC · re: Elijah Newren · lore

Re: [PATCH v2 01/12] fast-export: do anonymize the primary branch name

On Wed, Jun 17, 2020 at 07:06:26PM -0700, Elijah Newren wrote:
Show 7 quoted lines
> > That leaves us in the interim with a "fast-export --anonymize" that is a
> > little harder to use (you have no way to know which branch was which).
> 
> Why does fast-export special case on "master" rather than on HEAD?
> Isn't it more relevant to know the active branch than what _might_
> have been the initial branch?  It kind of feels like a bug to me that
> HEAD isn't the special case construct.

I don't really remember my exact thought at the time, but it was probably along the lines of: "master" is special not because it's inherently special, but because revealing it doesn't compromise the anonymity, since it's not a user-selected name.

That's not true of other names we might see in HEAD. But if we're turning it into "ref0" or some other special name anyway, then we haven't revealed anything.

That said, I still lean towards just being able to dump the whole mapping by request. That solves this problem and many more.

-Peff
Johannes Schindelin via GitGitGadget· Jun 15, 2020, 12:50 UTC · re: Johannes Schindelin via GitGitGadget · lore

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

From: Johannes Schindelin <johannes.schindelin@gmx.de>

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).

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 (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 <johannes.schindelin@gmx.de>
---
 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(-)
Show changes to 5 files +50 −2

Documentation/config/core.txt, fmt-merge-msg.c, refs.c, refs.h, t/t6200-fmt-merge-msg.sh

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);
+
+	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
+ * 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}
-- 
gitgitgadget
Phillip Wood· Jun 15, 2020, 15:00 UTC · re: Johannes Schindelin via GitGitGadget · lore

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

Hi dscho
On 15/06/2020 13:50, Johannes Schindelin via GitGitGadget wrote:
Show 6 quoted lines
> From: Johannes Schindelin <johannes.schindelin@gmx.de>
> 
> 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
Show 7 quoted lines
> 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/ ?
Show 85 quoted lines
> (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 <johannes.schindelin@gmx.de>
> ---
>   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.

Show 22 quoted lines
> +
> +	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
Show 27 quoted lines
> + * 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}
> 
Johannes Schindelin· Jun 23, 2020, 12:31 UTC · re: Phillip Wood · lore

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

Hi Phillip,
On Mon, 15 Jun 2020, Phillip Wood wrote:
Show 9 quoted lines
> On 15/06/2020 13:50, Johannes Schindelin via GitGitGadget wrote:
> > From: Johannes Schindelin <johannes.schindelin@gmx.de>
> >
> > 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

As I am replacing this patch in v3 with a version that simply drops the special handling of the `master` branch, I moved that rationale into the patch introducing support for `git init --initial-branch=<name>`.

Show 9 quoted lines
> > 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/ ?

Thank you! If I had not dropped that part of the commit message, I would have taken your suggested fix.

Show 88 quoted lines
> > (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 <johannes.schindelin@gmx.de>
> > ---
> >   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.
Right.

But as I am dropping the concept of `core.mainBranch` from v3, this won't apply anymore.

Show 26 quoted lines
>
> > +
> > +	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 ':'
Right, v3 won't have that peculiar construct.

Thank you for your review! Dscho

Show 35 quoted lines
>
> 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}
> >
>
>
Junio C Hamano· Jun 15, 2020, 17:05 UTC · re: Johannes Schindelin via GitGitGadget · lore

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

"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com> writes:

Show 24 quoted lines
> 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);
While you are at it, taking
https://lore.kernel.org/git/20200614211500.GA22505@dcvr/

and the response to it into consideration, I'd suggest we should support the case where the user says "no single branch is special here" by configuring it to an empty string.

> +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.

As to the naming of the configuration variable and the actual fall-back value, I would strongly suggest making them DIFFERNT (i.e. separate the concept from an actual value).

An instruction
    ... oh, if you want to do so, you can set the core.mainBranch
    configuration variable to 'main'
sounds strange than
    ... oh, if you want to do so, you can set the core.primaryBranch
    configuration variable to 'main'

at least to me, and since I am OK with your choice of 'main' as the replacement for 'master', a separate word would be more appropriate for the variable name.

Johannes Schindelin· Jun 23, 2020, 19:19 UTC · re: Junio C Hamano · lore

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

Hi Junio,
On Mon, 15 Jun 2020, Junio C Hamano wrote:
Show 35 quoted lines
> "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
> writes:
>
> > 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);
>
> While you are at it, taking
>
> https://lore.kernel.org/git/20200614211500.GA22505@dcvr/
>
> and the response to it into consideration, I'd suggest we should
> support the case where the user says "no single branch is special
> here" by configuring it to an empty string.

Together with Peff's comments, I think we're even further than that: v3 of this patch series will completely drop `core.mainBranch` and not special-case *any* branch in `fmt-merge-msg`.

There is still merit in Hannes Sixt's wish to be able to turn off the `into <branch>` suffix, but that is orthogonal to the purpose of this here patch series.

Ciao, Dscho

Show 25 quoted lines
>
> > +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.
>
> As to the naming of the configuration variable and the actual
> fall-back value, I would strongly suggest making them DIFFERNT
> (i.e. separate the concept from an actual value).
>
> An instruction
>
>     ... oh, if you want to do so, you can set the core.mainBranch
>     configuration variable to 'main'
>
> sounds strange than
>
>     ... oh, if you want to do so, you can set the core.primaryBranch
>     configuration variable to 'main'
>
> at least to me, and since I am OK with your choice of 'main' as the
> replacement for 'master', a separate word would be more appropriate
> for the variable name.
>
>
Ævar Arnfjörð Bjarmason· Jun 16, 2020, 08:46 UTC · re: Johannes Schindelin via GitGitGadget · lore

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

On Mon, Jun 15 2020, Johannes Schindelin via GitGitGadget wrote:
> From: Johannes Schindelin <johannes.schindelin@gmx.de>
> +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.

Everywhere else in git-config(1) we just say something to the effect of the more brief:

    The name of the main (or: primary) branch in the current repository
    (`master` by default).
I think we should do the same here for consistency & ease of reading.

As you note at the start of this series we're not changing the default yet, so referring to the current default as historical is putting the cart before the horse as far as producing self-contained patch serieses goes.

Junio C Hamano· Jun 17, 2020, 18:21 UTC · re: Ævar Arnfjörð Bjarmason · lore

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

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
Show 21 quoted lines
> On Mon, Jun 15 2020, Johannes Schindelin via GitGitGadget wrote:
>
>> From: Johannes Schindelin <johannes.schindelin@gmx.de>
>
>> +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.
>
> Everywhere else in git-config(1) we just say something to the effect of
> the more brief:
>
>     The name of the main (or: primary) branch in the current repository
>     (`master` by default).
>
> I think we should do the same here for consistency & ease of reading.
>
> As you note at the start of this series we're not changing the default
> yet, so referring to the current default as historical is putting the
> cart before the horse as far as producing self-contained patch serieses
> goes.
Very good point.  

In [*1*], I gave a potential outline of how a transition plan might look like (if we were to transition, that is), but what is written as step 1. in there should be split into two: step 0, in which the mechanisms (1) to change the default name used for the first branch and (2) to specify the primary branch that is special-cased by a few commands are introduced, without any future plan, and step 1, in which warning and/or advice messages knudge the users and hint the future direction.

Thanks.
[Reference]
*1* https://lore.kernel.org/git/xmqqeeqiztpq.fsf@gitster.c.googlers.com
Jeff King· Jun 16, 2020, 13:04 UTC · re: Johannes Schindelin via GitGitGadget · lore

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

On Mon, Jun 15, 2020 at 12:50:06PM +0000, Johannes Schindelin via GitGitGadget wrote:
Show 15 quoted lines
> +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);

Ah, this fixes the "we do not check the format of the short name" issue I pointed out in v1 (sorry, I just realized that v2 existed so I'll resume reviewing from there; I do still think this might make life easier for callers by returning a const pointer).

I'm not sure if this check_refname_format() is valid, though. IIRC we've had issues where "ONELEVEL" was used to check a branch name, but misses some cases. The more full check done by strbuf_check_branch_ref() actually creates the full refname and checks that. It also catches stuff like refs/heads/HEAD.

I doubt that it matters too much for us to be completely thorough here (unlike some other spots, we are not enforcing rules against potentially malicious names, but rather just helping the user realize early that their config is bogus). So I'm not sure how careful we want to be.

-Peff
Junio C Hamano· Jun 17, 2020, 18:23 UTC · re: Jeff King · lore

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

Jeff King <peff@peff.net> writes:
Show 5 quoted lines
> I'm not sure if this check_refname_format() is valid, though. IIRC we've
> had issues where "ONELEVEL" was used to check a branch name, but misses
> some cases. The more full check done by strbuf_check_branch_ref()
> actually creates the full refname and checks that. It also catches stuff
> like refs/heads/HEAD.
Yup.

I actually am in favor of removing special casing of a single branch done by fmt-merge-msg and fast-export --anonymize, so this may not matter.

We still need a mechanism to allow users specify the default name to be given to the first branch "git init" creates and used by "git clone" as a fallback name when it cannot infer what the other side uses, though.

Johannes Schindelin· Jun 18, 2020, 13:15 UTC · re: Junio C Hamano · lore

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

Hi,
On Wed, 17 Jun 2020, Junio C Hamano wrote:
Show 17 quoted lines
> Jeff King <peff@peff.net> writes:
>
> > I'm not sure if this check_refname_format() is valid, though. IIRC we've
> > had issues where "ONELEVEL" was used to check a branch name, but misses
> > some cases. The more full check done by strbuf_check_branch_ref()
> > actually creates the full refname and checks that. It also catches stuff
> > like refs/heads/HEAD.
>
> Yup.
>
> I actually am in favor of removing special casing of a single branch
> done by fmt-merge-msg and fast-export --anonymize, so this may not
> matter.
>
> We still need a mechanism to allow users specify the default name to
> be given to the first branch "git init" creates and used by "git clone"
> as a fallback name when it cannot infer what the other side uses, though.

All right, `core.mainBranch` will go, then, and `init.defaultBranch` will stay and I will check the full ref.

Thank you for your help improving the patch series, Dscho

Johannes Sixt· Jun 17, 2020, 20:56 UTC · re: Johannes Schindelin via GitGitGadget · lore

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

Am 15.06.20 um 14:50 schrieb Johannes Schindelin via GitGitGadget:
Show 12 quoted lines
> @@ -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);
>  }

Now that the removal of this special case is on the plate, I would prefer that the phrase "into foo" is never appended instead of always appended.

For me, it was a always more of a hindrance than a help. The story goes like this: A branch that I'm working on was named "edit-box-fix" yesterday, but today it was renamed to "layout-fix" because the scope changed. I had merged a topic "rename-buttons" yesterday, and now I have to go back and rename that "into edit-box-fix" thing! Argh! And tomorrow I'm going to branch off yet another feature "optional-reset" from today's state that will be merged into upstream soon; "Merge branch 'rename-buttons' into layout-fix" will read strange in a history that ends in "Merge branch 'optional-reset'".

And I haven't even mentioned this horrid "into HEAD", which you get during a rebase operation.

To be clear, the branch name in "Merge branch 'option-reset'" is very important and invaluable. But the "into foo" part is mostly noise.

-- Hannes
Junio C Hamano· Jun 17, 2020, 21:16 UTC · re: Johannes Sixt · lore

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

Johannes Sixt <j6t@kdbg.org> writes:
Show 17 quoted lines
> Am 15.06.20 um 14:50 schrieb Johannes Schindelin via GitGitGadget:
>> @@ -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);
>>  }
>
> Now that the removal of this special case is on the plate, I would
> prefer that the phrase "into foo" is never appended instead of always
> appended.

I do not mind such an optional feature. I always find it useful whenever I read "git log --oneline --first-parent master..pu" (of course I have an alias for that) to see which topics are already in my private "to be used in real life" edition, so I would oppose to an unconditional removal, though.

Johannes Schindelin· Jun 23, 2020, 21:12 UTC · re: Junio C Hamano · lore

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

Hi Junio & Hannes,
On Wed, 17 Jun 2020, Junio C Hamano wrote:
Show 25 quoted lines
> Johannes Sixt <j6t@kdbg.org> writes:
>
> > Am 15.06.20 um 14:50 schrieb Johannes Schindelin via GitGitGadget:
> >> @@ -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);
> >>  }
> >
> > Now that the removal of this special case is on the plate, I would
> > prefer that the phrase "into foo" is never appended instead of always
> > appended.
>
> I do not mind such an optional feature.  I always find it useful
> whenever I read "git log --oneline --first-parent master..pu" (of
> course I have an alias for that) to see which topics are already in
> my private "to be used in real life" edition, so I would oppose to
> an unconditional removal, though.

I concur that this would make for a fine optional feature. Of course, that is an issue that is separate from the goal to make the default branch name used by `git init` configurable, so I will leave that feature to be implemented later (and by somebody else).

Ciao, Dscho

Johannes Schindelin via GitGitGadget· Jun 15, 2020, 12:50 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v2 05/12] fast-export: handle overridden main branch names correctly

From: Johannes Schindelin <johannes.schindelin@gmx.de>

When anonymizing commit history, we are careful to translate the main branch name to `ref0`.

When the main branch name is overridden via the config, we will want `git fast-export` to use that overridden name instead.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 builtin/fast-export.c            | 11 ++++++++++-
 t/t9351-fast-export-anonymize.sh |  6 ++++++
 2 files changed, 16 insertions(+), 1 deletion(-)
Show changes to 2 files +16 −1

builtin/fast-export.c, t/t9351-fast-export-anonymize.sh

diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 1072bbf041f..deeb01b6937 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -515,14 +515,23 @@ static const char *anonymize_refname(const char *refname)
 	};
 	static struct hashmap refs;
 	static struct strbuf anon = STRBUF_INIT;
+	static char *main_branch;
 	int i;
 
 	/*
 	 * In certain circumstances, it might be interesting to be able to
 	 * identify the main branch. For that reason, let's force its name to
 	 * be anonymized to `ref0`.
+	 *
+	 * While the main branch name might often be `main` for new
+	 * repositories (and `master` for aged ones), and such well-known names
+	 * may not necessarily need anonymizing, it could be configured to use
+	 * a secret word that the user may not want to reveal.
 	 */
-	if (!strcmp(refname, "refs/heads/master"))
+	if (!main_branch)
+		main_branch = git_main_branch_name(MAIN_BRANCH_FULL_NAME);
+
+	if (!strcmp(refname, main_branch))
 		return "refs/heads/ref0";
 
 	strbuf_reset(&anon);
diff --git a/t/t9351-fast-export-anonymize.sh b/t/t9351-fast-export-anonymize.sh
index 2415f0ec213..f42be635c2f 100755
--- a/t/t9351-fast-export-anonymize.sh
+++ b/t/t9351-fast-export-anonymize.sh
@@ -31,6 +31,12 @@ test_expect_success 'stream translates master to ref0' '
 	! grep master stream
 '
 
+test_expect_success 'respects configured main branch' '
+	git -c core.mainBranch=does-not-exist \
+		fast-export --anonymize --all >stream-without-ref0 &&
+	! grep ref0 stream-without-ref0
+'
+
 test_expect_success 'stream omits other refnames' '
 	! grep other stream &&
 	! grep mytag stream
-- 
gitgitgadget
Phillip Wood· Jun 15, 2020, 15:05 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH v2 05/12] fast-export: handle overridden main branch names correctly

Hi dscho
On 15/06/2020 13:50, Johannes Schindelin via GitGitGadget wrote:
Show 41 quoted lines
> From: Johannes Schindelin <johannes.schindelin@gmx.de>
> 
> When anonymizing commit history, we are careful to translate the main
> branch name to `ref0`.
> 
> When the main branch name is overridden via the config, we will want
> `git fast-export` to use that overridden name instead.
> 
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> ---
>   builtin/fast-export.c            | 11 ++++++++++-
>   t/t9351-fast-export-anonymize.sh |  6 ++++++
>   2 files changed, 16 insertions(+), 1 deletion(-)
> 
> diff --git a/builtin/fast-export.c b/builtin/fast-export.c
> index 1072bbf041f..deeb01b6937 100644
> --- a/builtin/fast-export.c
> +++ b/builtin/fast-export.c
> @@ -515,14 +515,23 @@ static const char *anonymize_refname(const char *refname)
>   	};
>   	static struct hashmap refs;
>   	static struct strbuf anon = STRBUF_INIT;
> +	static char *main_branch;
>   	int i;
>   
>   	/*
>   	 * In certain circumstances, it might be interesting to be able to
>   	 * identify the main branch. For that reason, let's force its name to
>   	 * be anonymized to `ref0`.
> +	 *
> +	 * While the main branch name might often be `main` for new
> +	 * repositories (and `master` for aged ones), and such well-known names
> +	 * may not necessarily need anonymizing, it could be configured to use
> +	 * a secret word that the user may not want to reveal.
>   	 */
> -	if (!strcmp(refname, "refs/heads/master"))
> +	if (!main_branch)
> +		main_branch = git_main_branch_name(MAIN_BRANCH_FULL_NAME);
> +
> +	if (!strcmp(refname, main_branch))
>   		return "refs/heads/ref0";
This leaks main_branch if it came from git_main_branch_name()
Best Wishes
Phillip
Show 19 quoted lines
>   	strbuf_reset(&anon);
> diff --git a/t/t9351-fast-export-anonymize.sh b/t/t9351-fast-export-anonymize.sh
> index 2415f0ec213..f42be635c2f 100755
> --- a/t/t9351-fast-export-anonymize.sh
> +++ b/t/t9351-fast-export-anonymize.sh
> @@ -31,6 +31,12 @@ test_expect_success 'stream translates master to ref0' '
>   	! grep master stream
>   '
>   
> +test_expect_success 'respects configured main branch' '
> +	git -c core.mainBranch=does-not-exist \
> +		fast-export --anonymize --all >stream-without-ref0 &&
> +	! grep ref0 stream-without-ref0
> +'
> +
>   test_expect_success 'stream omits other refnames' '
>   	! grep other stream &&
>   	! grep mytag stream
> 
Jeff King· Jun 16, 2020, 13:10 UTC · re: Phillip Wood · lore

Re: [PATCH v2 05/12] fast-export: handle overridden main branch names correctly

On Mon, Jun 15, 2020 at 04:05:52PM +0100, Phillip Wood wrote:
Show 14 quoted lines
> > @@ -515,14 +515,23 @@ static const char *anonymize_refname(const char *refname)
> >   	};
> >   	static struct hashmap refs;
> >   	static struct strbuf anon = STRBUF_INIT;
> > +	static char *main_branch;
> [...]
> > -	if (!strcmp(refname, "refs/heads/master"))
> > +	if (!main_branch)
> > +		main_branch = git_main_branch_name(MAIN_BRANCH_FULL_NAME);
> > +
> > +	if (!strcmp(refname, main_branch))
> >   		return "refs/heads/ref0";
> 
> This leaks main_branch if it came from git_main_branch_name()

It's a static that's used over and over, so I think it's intentional to essentially memoize it for the life of the program (at which point we could free it, but don't bother to do so, letting the process exit take care of it, and trusting in leak detectors to be aware that it's still reachable, as we do for lots of other process-lifetime allocations).

-Peff
Phillip Wood· Jun 16, 2020, 15:49 UTC · re: Jeff King · lore

Re: [PATCH v2 05/12] fast-export: handle overridden main branch names correctly

Hi Peff
On 16/06/2020 14:10, Jeff King wrote:
Show 19 quoted lines
> On Mon, Jun 15, 2020 at 04:05:52PM +0100, Phillip Wood wrote:
> 
>>> @@ -515,14 +515,23 @@ static const char *anonymize_refname(const char *refname)
>>>    	};
>>>    	static struct hashmap refs;
>>>    	static struct strbuf anon = STRBUF_INIT;
>>> +	static char *main_branch;
>> [...]
>>> -	if (!strcmp(refname, "refs/heads/master"))
>>> +	if (!main_branch)
>>> +		main_branch = git_main_branch_name(MAIN_BRANCH_FULL_NAME);
>>> +
>>> +	if (!strcmp(refname, main_branch))
>>>    		return "refs/heads/ref0";
>>
>> This leaks main_branch if it came from git_main_branch_name()
> 
> It's a static that's used over and over, so I think it's intentional to
> essentially memoize it for the life of the program 
Oh you're right, I completely misread the patch
Thanks
Phillip
Show 7 quoted lines
> (at which point we
> could free it, but don't bother to do so, letting the process exit take
> care of it, and trusting in leak detectors to be aware that it's still
> reachable, as we do for lots of other process-lifetime allocations).
> 
> -Peff
> 
Johannes Schindelin· Jun 18, 2020, 10:08 UTC · re: Jeff King · lore

Re: [PATCH v2 05/12] fast-export: handle overridden main branch names correctly

Hi Peff,
On Tue, 16 Jun 2020, Jeff King wrote:
Show 22 quoted lines
> On Mon, Jun 15, 2020 at 04:05:52PM +0100, Phillip Wood wrote:
>
> > > @@ -515,14 +515,23 @@ static const char *anonymize_refname(const char *refname)
> > >   	};
> > >   	static struct hashmap refs;
> > >   	static struct strbuf anon = STRBUF_INIT;
> > > +	static char *main_branch;
> > [...]
> > > -	if (!strcmp(refname, "refs/heads/master"))
> > > +	if (!main_branch)
> > > +		main_branch = git_main_branch_name(MAIN_BRANCH_FULL_NAME);
> > > +
> > > +	if (!strcmp(refname, main_branch))
> > >   		return "refs/heads/ref0";
> >
> > This leaks main_branch if it came from git_main_branch_name()
>
> It's a static that's used over and over, so I think it's intentional to
> essentially memoize it for the life of the program (at which point we
> could free it, but don't bother to do so, letting the process exit take
> care of it, and trusting in leak detectors to be aware that it's still
> reachable, as we do for lots of other process-lifetime allocations).

That is indeed the intention, and I will edit the commit message accordingly.

Thanks, Dscho

Junio C Hamano· Jun 15, 2020, 17:09 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH v2 05/12] fast-export: handle overridden main branch names correctly

"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com> writes:

> +	 * While the main branch name might often be `main` for new
> +	 * repositories (and `master` for aged ones), and such well-known names

As I said, if you used a different word for the first 'main' in the sentence, it reads much better.

Show 9 quoted lines
> +	 * may not necessarily need anonymizing, it could be configured to use
> +	 * a secret word that the user may not want to reveal.
>  	 */
> -	if (!strcmp(refname, "refs/heads/master"))
> +	if (!main_branch)
> +		main_branch = git_main_branch_name(MAIN_BRANCH_FULL_NAME);
> +
> +	if (!strcmp(refname, main_branch))
>  		return "refs/heads/ref0";

The same comment as 02/12 applies here. If the helper function returns "" when the user says that no branch is more special than others in the repository, the code would automatically do the right thing.

In any case, thanks for working on it. I am on "vacation" so will be commenting on the rest of the series later in the week.

Johannes Schindelin· Jun 23, 2020, 19:22 UTC · re: Junio C Hamano · lore

Re: [PATCH v2 05/12] fast-export: handle overridden main branch names correctly

Hi Junio,
On Mon, 15 Jun 2020, Junio C Hamano wrote:
Show 23 quoted lines
> "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
> writes:
>
> > +	 * While the main branch name might often be `main` for new
> > +	 * repositories (and `master` for aged ones), and such well-known names
>
> As I said, if you used a different word for the first 'main' in the
> sentence, it reads much better.
>
> > +	 * may not necessarily need anonymizing, it could be configured to use
> > +	 * a secret word that the user may not want to reveal.
> >  	 */
> > -	if (!strcmp(refname, "refs/heads/master"))
> > +	if (!main_branch)
> > +		main_branch = git_main_branch_name(MAIN_BRANCH_FULL_NAME);
> > +
> > +	if (!strcmp(refname, main_branch))
> >  		return "refs/heads/ref0";
>
> The same comment as 02/12 applies here.  If the helper function
> returns "" when the user says that no branch is more special than
> others in the repository, the code would automatically do the right
> thing.

Seeing as the `fast-export` patches in this here patch series will be dropped from v3, in favor of Peff's patches, this does no longer need to be addressed.

> In any case, thanks for working on it.  I am on "vacation" so will
> be commenting on the rest of the series later in the week.
Welcome back! I hope you were able to rest.

Ciao, Dscho

Johannes Schindelin via GitGitGadget· Jun 15, 2020, 12:50 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v2 04/12] git_main_branch_name(): optionally report the full ref name

From: Johannes Schindelin <johannes.schindelin@gmx.de>

We are about to introduce the first caller of that function (`git fast-export`) that wants a full ref name instead of the short branch name.

To make this change easier to review, let's refactor the function accordingly without mixing in the actual first call using the new flag.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 fmt-merge-msg.c    |  2 +-
 refs.c             | 12 ++++++++----
 refs.h             |  8 ++++++--
 send-pack.c        |  2 +-
 transport-helper.c |  2 +-
 5 files changed, 17 insertions(+), 9 deletions(-)
Show changes to 5 files +17 −9

fmt-merge-msg.c, refs.c, refs.h, send-pack.c, transport-helper.c

diff --git a/fmt-merge-msg.c b/fmt-merge-msg.c
index 43f4f829242..03dba905643 100644
--- a/fmt-merge-msg.c
+++ b/fmt-merge-msg.c
@@ -451,7 +451,7 @@ static void fmt_merge_msg_title(struct strbuf *out,
 			strbuf_addf(out, " of %s", srcs.items[i].string);
 	}
 
-	main_branch = git_main_branch_name();
+	main_branch = git_main_branch_name(0);
 	if (!strcmp(main_branch, current_branch))
 		strbuf_addch(out, '\n');
 	else
diff --git a/refs.c b/refs.c
index f1854cffa2f..7da3ac178c4 100644
--- a/refs.c
+++ b/refs.c
@@ -560,8 +560,9 @@ 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)
+char *repo_main_branch_name(struct repository *r, int flags)
 {
+	int full_name = flags & MAIN_BRANCH_FULL_NAME;
 	const char *config_key = "core.mainbranch";
 	const char *config_display_key = "core.mainBranch";
 	const char *fall_back = "master";
@@ -570,7 +571,10 @@ char *repo_main_branch_name(struct repository *r)
 	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 (full_name)
+		ret = xstrfmt("refs/heads/%s", name ? name : fall_back);
+	else
+		ret = name ? name : xstrdup(fall_back);
 
 	if (check_refname_format(ret, REFNAME_ALLOW_ONELEVEL))
 		die(_("invalid branch name: %s = %s"),
@@ -582,9 +586,9 @@ char *repo_main_branch_name(struct repository *r)
 	return ret;
 }
 
-char *git_main_branch_name(void)
+char *git_main_branch_name(int flags)
 {
-	return repo_main_branch_name(the_repository);
+	return repo_main_branch_name(the_repository, flags);
 }
 
 /*
diff --git a/refs.h b/refs.h
index a207ef01348..96472f9a9f5 100644
--- a/refs.h
+++ b/refs.h
@@ -157,9 +157,13 @@ 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
  * repository.
+ *
+ * The result is an allocated string. Unless the flags ask for a short name, it
+ * will be prefixed with "refs/heads/".
  */
-char *git_main_branch_name(void);
-char *repo_main_branch_name(struct repository *r);
+#define MAIN_BRANCH_FULL_NAME (1<<0)
+char *git_main_branch_name(int flags);
+char *repo_main_branch_name(struct repository *r, int flags);
 
 /*
  * A ref_transaction represents a collection of reference updates that
diff --git a/send-pack.c b/send-pack.c
index 2532864c812..898720511d0 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -405,7 +405,7 @@ int send_pack(struct send_pack_args *args,
 	}
 
 	if (!remote_refs) {
-		char *branch_name = git_main_branch_name();
+		char *branch_name = git_main_branch_name(0);
 
 		fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
 			"Perhaps you should specify a branch such as '%s'.\n",
diff --git a/transport-helper.c b/transport-helper.c
index 8c8f40e322d..7a54e5b2fb2 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -1044,7 +1044,7 @@ static int push_refs(struct transport *transport,
 	}
 
 	if (!remote_refs) {
-		char *branch_name = git_main_branch_name();
+		char *branch_name = git_main_branch_name(0);
 
 		fprintf(stderr,
 			_("No refs in common and none specified; doing nothing.\n"
-- 
gitgitgadget
Phillip Wood· Jun 15, 2020, 15:04 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH v2 04/12] git_main_branch_name(): optionally report the full ref name

Hi dscho
On 15/06/2020 13:50, Johannes Schindelin via GitGitGadget wrote:
Show 55 quoted lines
> From: Johannes Schindelin <johannes.schindelin@gmx.de>
> 
> We are about to introduce the first caller of that function (`git
> fast-export`) that wants a full ref name instead of the short branch
> name.
> 
> To make this change easier to review, let's refactor the function
> accordingly without mixing in the actual first call using the new flag.
> 
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> ---
>   fmt-merge-msg.c    |  2 +-
>   refs.c             | 12 ++++++++----
>   refs.h             |  8 ++++++--
>   send-pack.c        |  2 +-
>   transport-helper.c |  2 +-
>   5 files changed, 17 insertions(+), 9 deletions(-)
> 
> diff --git a/fmt-merge-msg.c b/fmt-merge-msg.c
> index 43f4f829242..03dba905643 100644
> --- a/fmt-merge-msg.c
> +++ b/fmt-merge-msg.c
> @@ -451,7 +451,7 @@ static void fmt_merge_msg_title(struct strbuf *out,
>   			strbuf_addf(out, " of %s", srcs.items[i].string);
>   	}
>   
> -	main_branch = git_main_branch_name();
> +	main_branch = git_main_branch_name(0);
>   	if (!strcmp(main_branch, current_branch))
>   		strbuf_addch(out, '\n');
>   	else
> diff --git a/refs.c b/refs.c
> index f1854cffa2f..7da3ac178c4 100644
> --- a/refs.c
> +++ b/refs.c
> @@ -560,8 +560,9 @@ 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)
> +char *repo_main_branch_name(struct repository *r, int flags)
>   {
> +	int full_name = flags & MAIN_BRANCH_FULL_NAME;
>   	const char *config_key = "core.mainbranch";
>   	const char *config_display_key = "core.mainBranch";
>   	const char *fall_back = "master";
> @@ -570,7 +571,10 @@ char *repo_main_branch_name(struct repository *r)
>   	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 (full_name)
> +		ret = xstrfmt("refs/heads/%s", name ? name : fall_back);
> +	else
> +		ret = name ? name : xstrdup(fall_back);

This looks good, we always check the name before returning it and free name if we're returning refs/heads/<name>

Show 26 quoted lines
>   	if (check_refname_format(ret, REFNAME_ALLOW_ONELEVEL))
>   		die(_("invalid branch name: %s = %s"),
> @@ -582,9 +586,9 @@ char *repo_main_branch_name(struct repository *r)
>   	return ret;
>   }
>   
> -char *git_main_branch_name(void)
> +char *git_main_branch_name(int flags)
>   {
> -	return repo_main_branch_name(the_repository);
> +	return repo_main_branch_name(the_repository, flags);
>   }
>   
>   /*
> diff --git a/refs.h b/refs.h
> index a207ef01348..96472f9a9f5 100644
> --- a/refs.h
> +++ b/refs.h
> @@ -157,9 +157,13 @@ 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
>    * repository.
> + *
> + * The result is an allocated string. Unless the flags ask for a short name, it
> + * will be prefixed with "refs/heads/".
>    */

nit pick: the flag is defined to give the fullname, to get the short name you just pass 0.

Best Wishes
Phillip
Show 35 quoted lines
> -char *git_main_branch_name(void);
> -char *repo_main_branch_name(struct repository *r);
> +#define MAIN_BRANCH_FULL_NAME (1<<0)
> +char *git_main_branch_name(int flags);
> +char *repo_main_branch_name(struct repository *r, int flags);
>   
>   /*
>    * A ref_transaction represents a collection of reference updates that
> diff --git a/send-pack.c b/send-pack.c
> index 2532864c812..898720511d0 100644
> --- a/send-pack.c
> +++ b/send-pack.c
> @@ -405,7 +405,7 @@ int send_pack(struct send_pack_args *args,
>   	}
>   
>   	if (!remote_refs) {
> -		char *branch_name = git_main_branch_name();
> +		char *branch_name = git_main_branch_name(0);
>   
>   		fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
>   			"Perhaps you should specify a branch such as '%s'.\n",
> diff --git a/transport-helper.c b/transport-helper.c
> index 8c8f40e322d..7a54e5b2fb2 100644
> --- a/transport-helper.c
> +++ b/transport-helper.c
> @@ -1044,7 +1044,7 @@ static int push_refs(struct transport *transport,
>   	}
>   
>   	if (!remote_refs) {
> -		char *branch_name = git_main_branch_name();
> +		char *branch_name = git_main_branch_name(0);
>   
>   		fprintf(stderr,
>   			_("No refs in common and none specified; doing nothing.\n"
> 
Johannes Schindelin· Jun 23, 2020, 19:17 UTC · re: Phillip Wood · lore

Re: [PATCH v2 04/12] git_main_branch_name(): optionally report the full ref name

Hi Phillip,
On Mon, 15 Jun 2020, Phillip Wood wrote:
Show 90 quoted lines
> On 15/06/2020 13:50, Johannes Schindelin via GitGitGadget wrote:
> > From: Johannes Schindelin <johannes.schindelin@gmx.de>
> >
> > We are about to introduce the first caller of that function (`git
> > fast-export`) that wants a full ref name instead of the short branch
> > name.
> >
> > To make this change easier to review, let's refactor the function
> > accordingly without mixing in the actual first call using the new flag.
> >
> > Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> > ---
> >   fmt-merge-msg.c    |  2 +-
> >   refs.c             | 12 ++++++++----
> >   refs.h             |  8 ++++++--
> >   send-pack.c        |  2 +-
> >   transport-helper.c |  2 +-
> >   5 files changed, 17 insertions(+), 9 deletions(-)
> >
> > diff --git a/fmt-merge-msg.c b/fmt-merge-msg.c
> > index 43f4f829242..03dba905643 100644
> > --- a/fmt-merge-msg.c
> > +++ b/fmt-merge-msg.c
> > @@ -451,7 +451,7 @@ static void fmt_merge_msg_title(struct strbuf *out,
> >    		strbuf_addf(out, " of %s", srcs.items[i].string);
> >    }
> >   -	main_branch = git_main_branch_name();
> > +	main_branch = git_main_branch_name(0);
> >    if (!strcmp(main_branch, current_branch))
> >    	strbuf_addch(out, '\n');
> >   	else
> > diff --git a/refs.c b/refs.c
> > index f1854cffa2f..7da3ac178c4 100644
> > --- a/refs.c
> > +++ b/refs.c
> > @@ -560,8 +560,9 @@ 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)
> > +char *repo_main_branch_name(struct repository *r, int flags)
> >   {
> > +	int full_name = flags & MAIN_BRANCH_FULL_NAME;
> >    const char *config_key = "core.mainbranch";
> >    const char *config_display_key = "core.mainBranch";
> >    const char *fall_back = "master";
> > @@ -570,7 +571,10 @@ char *repo_main_branch_name(struct repository *r)
> >    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 (full_name)
> > +		ret = xstrfmt("refs/heads/%s", name ? name : fall_back);
> > +	else
> > +		ret = name ? name : xstrdup(fall_back);
>
> This looks good, we always check the name before returning it and free name if
> we're returning refs/heads/<name>
>
> >    if (check_refname_format(ret, REFNAME_ALLOW_ONELEVEL))
> >   		die(_("invalid branch name: %s = %s"),
> > @@ -582,9 +586,9 @@ char *repo_main_branch_name(struct repository *r)
> >   	return ret;
> >   }
> >
> > -char *git_main_branch_name(void)
> > +char *git_main_branch_name(int flags)
> >   {
> > -	return repo_main_branch_name(the_repository);
> > +	return repo_main_branch_name(the_repository, flags);
> >   }
> >
> >   /*
> > diff --git a/refs.h b/refs.h
> > index a207ef01348..96472f9a9f5 100644
> > --- a/refs.h
> > +++ b/refs.h
> > @@ -157,9 +157,13 @@ 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
> >    * repository.
> > + *
> > + * The result is an allocated string. Unless the flags ask for a short
> > name, it
> > + * will be prefixed with "refs/heads/".
> >    */
>
> nit pick: the flag is defined to give the fullname, to get the short name you
> just pass 0.

I decided to drop the flag and always return the name, not the full ref. It makes the code _slightly_ less efficient, but easier to follow.

Ciao, Dscho

Show 41 quoted lines
>
> Best Wishes
>
> Phillip
>
> > -char *git_main_branch_name(void);
> > -char *repo_main_branch_name(struct repository *r);
> > +#define MAIN_BRANCH_FULL_NAME (1<<0)
> > +char *git_main_branch_name(int flags);
> > +char *repo_main_branch_name(struct repository *r, int flags);
> >
> >   /*
> >    * A ref_transaction represents a collection of reference updates that
> > diff --git a/send-pack.c b/send-pack.c
> > index 2532864c812..898720511d0 100644
> > --- a/send-pack.c
> > +++ b/send-pack.c
> > @@ -405,7 +405,7 @@ int send_pack(struct send_pack_args *args,
> >    }
> >
> >   	if (!remote_refs) {
> > -		char *branch_name = git_main_branch_name();
> > +		char *branch_name = git_main_branch_name(0);
> >
> >     fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
> >   			"Perhaps you should specify a branch such as '%s'.\n",
> > diff --git a/transport-helper.c b/transport-helper.c
> > index 8c8f40e322d..7a54e5b2fb2 100644
> > --- a/transport-helper.c
> > +++ b/transport-helper.c
> > @@ -1044,7 +1044,7 @@ static int push_refs(struct transport *transport,
> >    }
> >
> >   	if (!remote_refs) {
> > -		char *branch_name = git_main_branch_name();
> > +		char *branch_name = git_main_branch_name(0);
> >
> >     fprintf(stderr,
> >      _("No refs in common and none specified; doing nothing.\n"
> >
>
Johannes Schindelin via GitGitGadget· Jun 15, 2020, 12:50 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v2 03/12] send-pack/transport-helper: respect `core.mainBranch`

From: Johannes Schindelin <johannes.schindelin@gmx.de>

When mentioning the main branch name in an error message, we want to go with the preference specified by the user, only falling back to Git's own, hard-coded default when none was configured explicitly.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 send-pack.c             | 6 +++++-
 t/t5528-push-default.sh | 7 +++++++
 transport-helper.c      | 6 +++++-
 3 files changed, 17 insertions(+), 2 deletions(-)
Show changes to 3 files +17 −2

send-pack.c, t/t5528-push-default.sh, transport-helper.c

diff --git a/send-pack.c b/send-pack.c
index 0abee22283d..2532864c812 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -405,8 +405,12 @@ int send_pack(struct send_pack_args *args,
 	}
 
 	if (!remote_refs) {
+		char *branch_name = git_main_branch_name();
+
 		fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
-			"Perhaps you should specify a branch such as 'master'.\n");
+			"Perhaps you should specify a branch such as '%s'.\n",
+			branch_name);
+		free(branch_name);
 		return 0;
 	}
 	if (args->atomic && !atomic_supported)
diff --git a/t/t5528-push-default.sh b/t/t5528-push-default.sh
index 4d1e0c363ea..f7583b20f87 100755
--- a/t/t5528-push-default.sh
+++ b/t/t5528-push-default.sh
@@ -98,6 +98,13 @@ test_expect_success 'push from/to new branch with upstream, matching and simple'
 	test_push_failure upstream
 '
 
+test_expect_success '"matching" fails if none match' '
+	git init --bare empty &&
+	test_must_fail git -c core.mainBranch=unmatch push empty : 2>actual &&
+	needle="Perhaps you should specify a branch such as '\''unmatch'\''" &&
+	test_i18ngrep "$needle" actual
+'
+
 test_expect_success 'push ambiguously named branch with upstream, matching and simple' '
 	git checkout -b ambiguous &&
 	test_config branch.ambiguous.remote parent1 &&
diff --git a/transport-helper.c b/transport-helper.c
index a46afcb69db..8c8f40e322d 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -1044,9 +1044,13 @@ static int push_refs(struct transport *transport,
 	}
 
 	if (!remote_refs) {
+		char *branch_name = git_main_branch_name();
+
 		fprintf(stderr,
 			_("No refs in common and none specified; doing nothing.\n"
-			  "Perhaps you should specify a branch such as 'master'.\n"));
+			  "Perhaps you should specify a branch such as '%s'.\n"),
+			branch_name);
+		free(branch_name);
 		return 0;
 	}
 
-- 
gitgitgadget
Johannes Schindelin via GitGitGadget· Jun 15, 2020, 12:50 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v2 06/12] branch -m: adjust `core.mainBranch` if necessary

From: Johannes Schindelin <johannes.schindelin@gmx.de>

When renaming the main branch (as possibly identified by the `core.mainBranch` setting), we will want to record that the main branch now has a different name.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 builtin/branch.c  | 9 +++++++++
 t/t3200-branch.sh | 9 +++++++++
 2 files changed, 18 insertions(+)
Show changes to 2 files +18 −0

builtin/branch.c, t/t3200-branch.sh

diff --git a/builtin/branch.c b/builtin/branch.c
index accb61b1aae..62f8db5fb05 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -556,6 +556,15 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
 	    replace_each_worktree_head_symref(oldref.buf, newref.buf, logmsg.buf))
 		die(_("Branch renamed to %s, but HEAD is not updated!"), newname);
 
+	if (!copy) {
+		char *main_branch = git_main_branch_name(0);
+
+		if (!strcmp(interpreted_oldname, main_branch))
+		    git_config_set("core.mainbranch", interpreted_newname);
+
+		free(main_branch);
+	}
+
 	strbuf_release(&logmsg);
 
 	strbuf_addf(&oldsection, "branch.%s", interpreted_oldname);
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 411a70b0ce9..328544f2736 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -467,6 +467,15 @@ EOF
 	test_cmp expect actual
 '
 
+test_expect_success 'renaming the main branch modifies core.mainBranch' '
+	git init rename-main &&
+	test_commit -C rename-main initial &&
+	git -C rename-main branch -m trunk &&
+	git -C rename-main config core.mainBranch >actual &&
+	echo trunk >expect &&
+	test_cmp expect actual
+'
+
 test_expect_success 'git branch -c dumps usage' '
 	test_expect_code 128 git branch -c 2>err &&
 	test_i18ngrep "branch name required" err
-- 
gitgitgadget
Johannes Schindelin via GitGitGadget· Jun 15, 2020, 12:50 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v2 12/12] testsvn: respect `init.defaultBranch`

From: Johannes Schindelin <johannes.schindelin@gmx.de>

The default name of the main branch in new repositories can now be configured. The `testsvn` remote helper translates the remote Subversion repository's branch name `trunk` to the hard-coded name `master`. Clearly, the intention was to make the name align with Git's detaults.

So while we are not talking about a newly-created repository in the `testsvn` context, it _still_ makes sense to use the overridden default name for the main branch whenever users configured it.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 remote-testsvn.c      | 12 +++++++++---
 t/t9020-remote-svn.sh |  6 ++++++
 2 files changed, 15 insertions(+), 3 deletions(-)
Show changes to 2 files +15 −3

remote-testsvn.c, t/t9020-remote-svn.sh

diff --git a/remote-testsvn.c b/remote-testsvn.c
index 3af708c5b67..6ec300bf6c3 100644
--- a/remote-testsvn.c
+++ b/remote-testsvn.c
@@ -13,7 +13,7 @@
 static const char *url;
 static int dump_from_file;
 static const char *private_ref;
-static const char *remote_ref = "refs/heads/master";
+static char *remote_ref;
 static const char *marksfilename, *notes_ref;
 struct rev_note { unsigned int rev_nr; };
 
@@ -286,7 +286,7 @@ int cmd_main(int argc, const char **argv)
 			private_ref_sb = STRBUF_INIT, marksfilename_sb = STRBUF_INIT,
 			notes_ref_sb = STRBUF_INIT;
 	static struct remote *remote;
-	const char *url_in;
+	const char *url_in, *remote_ref_short;
 
 	setup_git_directory();
 	if (argc < 2 || argc > 3) {
@@ -294,6 +294,11 @@ int cmd_main(int argc, const char **argv)
 		return 1;
 	}
 
+	remote_ref = git_main_branch_name(MAIN_BRANCH_FULL_NAME |
+					  MAIN_BRANCH_FOR_INIT);
+	if (!skip_prefix(remote_ref, "refs/heads/", &remote_ref_short))
+		BUG("unexpected remote_ref '%s'", remote_ref);
+
 	remote = remote_get(argv[1]);
 	url_in = (argc == 3) ? argv[2] : remote->url[0];
 
@@ -306,7 +311,8 @@ int cmd_main(int argc, const char **argv)
 		url = url_sb.buf;
 	}
 
-	strbuf_addf(&private_ref_sb, "refs/svn/%s/master", remote->name);
+	strbuf_addf(&private_ref_sb, "refs/svn/%s/%s",
+		    remote->name, remote_ref_short);
 	private_ref = private_ref_sb.buf;
 
 	strbuf_addf(&notes_ref_sb, "refs/notes/%s/revs", remote->name);
diff --git a/t/t9020-remote-svn.sh b/t/t9020-remote-svn.sh
index 6fca08e5e35..c931193f013 100755
--- a/t/t9020-remote-svn.sh
+++ b/t/t9020-remote-svn.sh
@@ -84,6 +84,12 @@ test_expect_success REMOTE_SVN 'incremental imports must lead to the same head'
 	test_cmp master.good .git/refs/remotes/svnsim/master
 '
 
+test_expect_success REMOTE_SVN 'respects configured default main branch' '
+	git -c init.defaultBranch=trunk remote add -f trunk \
+		"testsvn::file://$TEST_DIRECTORY/t9154/svn.dump" &&
+	git rev-parse --verify refs/remotes/trunk/trunk
+'
+
 test_debug 'git branch -a'
 
 test_done
-- 
gitgitgadget
Jeff King· Jun 16, 2020, 13:51 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH v2 12/12] testsvn: respect `init.defaultBranch`

On Mon, Jun 15, 2020 at 12:50:16PM +0000, Johannes Schindelin via GitGitGadget wrote:
Show 6 quoted lines
> From: Johannes Schindelin <johannes.schindelin@gmx.de>
> 
> The default name of the main branch in new repositories can now be
> configured. The `testsvn` remote helper translates the remote Subversion
> repository's branch name `trunk` to the hard-coded name `master`.
> Clearly, the intention was to make the name align with Git's detaults.
s/detaults/defaults/ :)
I'd agree that moving this to Git's default name makes sense.

Though my overall preference is still to delete this whole testsvn thing entirely (I have some other pending tree-wide changes that are being held up by it, too). After getting "would you mind holding off until..." from Jonathan in [1], I've been waiting almost 2 years. Maybe now is the time?

-Peff
[1] https://lore.kernel.org/git/20180818052605.GA241538@aiede.svl.corp.google.com/
Johannes Schindelin· Jun 23, 2020, 21:07 UTC · re: Jeff King · lore

Re: [PATCH v2 12/12] testsvn: respect `init.defaultBranch`

Hi Peff,
On Tue, 16 Jun 2020, Jeff King wrote:
Show 10 quoted lines
> On Mon, Jun 15, 2020 at 12:50:16PM +0000, Johannes Schindelin via GitGitGadget wrote:
>
> > From: Johannes Schindelin <johannes.schindelin@gmx.de>
> >
> > The default name of the main branch in new repositories can now be
> > configured. The `testsvn` remote helper translates the remote Subversion
> > repository's branch name `trunk` to the hard-coded name `master`.
> > Clearly, the intention was to make the name align with Git's detaults.
>
> s/detaults/defaults/ :)
:-)
Will fix.
> I'd agree that moving this to Git's default name makes sense.
Okay.
Show 5 quoted lines
> Though my overall preference is still to delete this whole testsvn thing
> entirely (I have some other pending tree-wide changes that are being
> held up by it, too). After getting "would you mind holding off until..."
> from Jonathan in [1], I've been waiting almost 2 years. Maybe now is the
> time?

I wouldn't mind dropping `testsvn`, seeing as there are fewer and fewer users of `git svn` (and even those are unlikely to switch to `testsvn`, should that ever become production-ready).

Having said that, this is an orthogonal issue to the purpose of this patch series. And I would really like to get this patch series into a shape that can be merged down to `next` soon.

Thank you, Dscho

Show 5 quoted lines
>
> -Peff
>
> [1] https://lore.kernel.org/git/20180818052605.GA241538@aiede.svl.corp.google.com/
>
Johannes Schindelin via GitGitGadget· Jun 15, 2020, 12:50 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v2 10/12] remote: learn about the possibly-overridden default main branch name

From: Johannes Schindelin <johannes.schindelin@gmx.de>

When guessing the default branch name of a remote, and there are no refs to guess from, we want to go with the preference specified by the user for the fall-back, i.e. the default name to be used for the main branch of new repositories (because as far as the user is concerned, a remote that has no branches yet is a new repository).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 remote.c                 | 15 ++++++++++-----
 t/t5606-clone-options.sh | 11 ++++++++++-
 2 files changed, 20 insertions(+), 6 deletions(-)
Show changes to 2 files +20 −6

remote.c, t/t5606-clone-options.sh

diff --git a/remote.c b/remote.c
index 534c6426f1e..2dcf4ac6d15 100644
--- a/remote.c
+++ b/remote.c
@@ -256,7 +256,7 @@ static void read_remotes_file(struct remote *remote)
 
 static void read_branches_file(struct remote *remote)
 {
-	char *frag;
+	char *frag, *main_branch = NULL;
 	struct strbuf buf = STRBUF_INIT;
 	FILE *f = fopen_or_warn(git_path("branches/%s", remote->name), "r");
 
@@ -276,7 +276,7 @@ static void read_branches_file(struct remote *remote)
 
 	/*
 	 * The branches file would have URL and optionally
-	 * #branch specified.  The "master" (or specified) branch is
+	 * #branch specified.  The main (or specified) branch is
 	 * fetched and stored in the local branch matching the
 	 * remote name.
 	 */
@@ -284,7 +284,7 @@ static void read_branches_file(struct remote *remote)
 	if (frag)
 		*(frag++) = '\0';
 	else
-		frag = "master";
+		frag = main_branch = git_main_branch_name(MAIN_BRANCH_FOR_INIT);
 
 	add_url_alias(remote, strbuf_detach(&buf, NULL));
 	strbuf_addf(&buf, "refs/heads/%s:refs/heads/%s",
@@ -299,6 +299,7 @@ static void read_branches_file(struct remote *remote)
 	strbuf_addf(&buf, "HEAD:refs/heads/%s", frag);
 	refspec_append(&remote->push, buf.buf);
 	remote->fetch_tags = 1; /* always auto-follow */
+	free(main_branch);
 	strbuf_release(&buf);
 }
 
@@ -2097,9 +2098,13 @@ struct ref *guess_remote_head(const struct ref *head,
 	if (head->symref)
 		return copy_ref(find_ref_by_name(refs, head->symref));
 
-	/* If refs/heads/master could be right, it is. */
+	/* If a remote branch exists with the main branch name, let's use it. */
 	if (!all) {
-		r = find_ref_by_name(refs, "refs/heads/master");
+		char *name = git_main_branch_name(MAIN_BRANCH_FULL_NAME |
+						  MAIN_BRANCH_FOR_INIT);
+
+		r = find_ref_by_name(refs, name);
+		free(name);
 		if (r && oideq(&r->old_oid, &head->old_oid))
 			return copy_ref(r);
 	}
diff --git a/t/t5606-clone-options.sh b/t/t5606-clone-options.sh
index 98b2d8527f6..61ce9c09920 100755
--- a/t/t5606-clone-options.sh
+++ b/t/t5606-clone-options.sh
@@ -49,7 +49,16 @@ test_expect_success 'guesses main branch name correctly' '
 	git -C main-branch branch abc guess &&
 	git clone main-branch is-it &&
 	test guess = $(git -C is-it config core.mainBranch) &&
-	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD)
+	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD) &&
+
+	git -c init.defaultBranch=none init --bare no-head &&
+	git -C main-branch push ../no-head guess abc &&
+	git clone no-head is-it2 &&
+	test_must_fail git -C is-it2 symbolic-ref refs/remotes/origin/HEAD &&
+	git -C no-head update-ref --no-deref HEAD refs/heads/guess &&
+	git -c init.defaultBranch=guess clone no-head is-it3 &&
+	test refs/remotes/origin/guess = \
+		$(git -C is-it3 symbolic-ref refs/remotes/origin/HEAD)
 '
 
 test_done
-- 
gitgitgadget
Johannes Schindelin via GitGitGadget· Jun 15, 2020, 12:50 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v2 11/12] submodule: use the correct default for the main branch name

From: Johannes Schindelin <johannes.schindelin@gmx.de>

To allow for overriding the default branch name, we have introduced a config setting. With this patch, the `git submodule` command learns about this, too.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 builtin/submodule--helper.c | 10 ++++++++--
 t/t7406-submodule-update.sh |  7 +++++++
 2 files changed, 15 insertions(+), 2 deletions(-)
Show changes to 2 files +15 −2

builtin/submodule--helper.c, t/t7406-submodule-update.sh

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 46c03d2a126..48d73e8d9cb 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1980,8 +1980,14 @@ static const char *remote_submodule_branch(const char *path)
 		branch = sub->branch;
 	free(key);
 
-	if (!branch)
-		return "master";
+	if (!branch) {
+		static char *fall_back;
+
+		if (!fall_back)
+			fall_back = git_main_branch_name(MAIN_BRANCH_FOR_INIT);
+
+		return fall_back;
+	}
 
 	if (!strcmp(branch, ".")) {
 		const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index 4fb447a143e..641113afef4 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -70,6 +70,13 @@ test_expect_success 'setup a submodule tree' '
 	)
 '
 
+test_expect_success 'update --remote uses configured default main branch' '
+	git clone super main-branch &&
+	test_must_fail git -C main-branch -c init.defaultBranch=hello \
+		submodule update --init --remote submodule 2>err &&
+	test_i18ngrep origin/hello err
+'
+
 test_expect_success 'submodule update detaching the HEAD ' '
 	(cd super/submodule &&
 	 git reset --hard HEAD~1
-- 
gitgitgadget
Jeff King· Jun 16, 2020, 13:46 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH v2 11/12] submodule: use the correct default for the main branch name

On Mon, Jun 15, 2020 at 12:50:15PM +0000, Johannes Schindelin via GitGitGadget wrote:
Show 5 quoted lines
> From: Johannes Schindelin <johannes.schindelin@gmx.de>
> 
> To allow for overriding the default branch name, we have introduced a
> config setting. With this patch, the `git submodule` command learns
> about this, too.

This was the other reading case (besides guess_remote_head()) that I'm most concerned with causing regressions in a world where some repos are on "master" and some are on "main".

This value ends up as the output of "submodule--helper remote-branch".

I was initially worried that we used this branch name for the fallback when the server doesn't allow us to fetch the sha1 directly, but it doesn't look like it. That's good, because handling fallbacks there would be tricky.

Instead, we seem to use this only after fetching all of the refs for a submodule:

  $ git grep -h -B2 -A11 remote-branch git-submodule.sh
  		if test -n "$remote"
  		then
  			branch=$(git submodule--helper remote-branch "$sm_path")
  			if test -z "$nofetch"
  			then
  				# Fetch remote before determining tracking $sha1
  				fetch_in_submodule "$sm_path" $depth ||
  				die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
  			fi
  			remote_name=$(sanitize_submodule_env; cd "$sm_path" && get_default_remote)
  			sha1=$(sanitize_submodule_env; cd "$sm_path" &&
  				git rev-parse --verify "${remote_name}/${branch}") ||
  			die "$(eval_gettext "Unable to find current \${remote_name}/\${branch} revision in submodule path '\$sm_path'")"
  		fi

and then we just use that branch name to resolve a sha1. So this will break cases where you've set init.mainBranch, the submodule repo is still on "master", and you haven't configured a branch in .gitmodules.

It seems like, independent of any change in the default branch names, we ought to be using $remote_name/HEAD for this case anyway. I suspect that would be a behavior improvement by itself, as it means more cases could avoid having to specify the branch name in .gitmodules manually. Probably nobody noticed so far because "HEAD" is almost always "master" in the current world. It technically breaks the case that you truly did want to use "master" in the submodule, but they set HEAD to something else, and you couldn't be bothered to put it into your .gitmodules file. That seems rather unlikely to me.

And then everything would Just Work without having to worry about the local mainbranch value at all.

Alternatively, submodule--helper could pass back the empty string for "no, we don't have a configured branch name" and this shell code could actually try a sequence of reasonable guesses: init.mainbranch, then "master" (and between the two, "main" if that later becomes the default).

-Peff
Johannes Schindelin· Jun 23, 2020, 21:03 UTC · re: Jeff King · lore

Re: [PATCH v2 11/12] submodule: use the correct default for the main branch name

Hi Peff,
On Tue, 16 Jun 2020, Jeff King wrote:
Show 54 quoted lines
> On Mon, Jun 15, 2020 at 12:50:15PM +0000, Johannes Schindelin via GitGitGadget wrote:
>
> > From: Johannes Schindelin <johannes.schindelin@gmx.de>
> >
> > To allow for overriding the default branch name, we have introduced a
> > config setting. With this patch, the `git submodule` command learns
> > about this, too.
>
> This was the other reading case (besides guess_remote_head()) that I'm
> most concerned with causing regressions in a world where some repos are
> on "master" and some are on "main".
>
> This value ends up as the output of "submodule--helper remote-branch".
>
> I was initially worried that we used this branch name for the fallback
> when the server doesn't allow us to fetch the sha1 directly, but it
> doesn't look like it. That's good, because handling fallbacks there
> would be tricky.
>
> Instead, we seem to use this only after fetching all of the refs for a
> submodule:
>
>   $ git grep -h -B2 -A11 remote-branch git-submodule.sh
>   		if test -n "$remote"
>   		then
>   			branch=$(git submodule--helper remote-branch "$sm_path")
>   			if test -z "$nofetch"
>   			then
>   				# Fetch remote before determining tracking $sha1
>   				fetch_in_submodule "$sm_path" $depth ||
>   				die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
>   			fi
>   			remote_name=$(sanitize_submodule_env; cd "$sm_path" && get_default_remote)
>   			sha1=$(sanitize_submodule_env; cd "$sm_path" &&
>   				git rev-parse --verify "${remote_name}/${branch}") ||
>   			die "$(eval_gettext "Unable to find current \${remote_name}/\${branch} revision in submodule path '\$sm_path'")"
>   		fi
>
> and then we just use that branch name to resolve a sha1. So this will
> break cases where you've set init.mainBranch, the submodule repo is
> still on "master", and you haven't configured a branch in .gitmodules.
>
> It seems like, independent of any change in the default branch names, we
> ought to be using $remote_name/HEAD for this case anyway. I suspect that
> would be a behavior improvement by itself, as it means more cases could
> avoid having to specify the branch name in .gitmodules manually.
> Probably nobody noticed so far because "HEAD" is almost always "master"
> in the current world. It technically breaks the case that you truly did
> want to use "master" in the submodule, but they set HEAD to something
> else, and you couldn't be bothered to put it into your .gitmodules file.
> That seems rather unlikely to me.
>
> And then everything would Just Work without having to worry about the
> local mainbranch value at all.
This is the route that I am taking.

Please note that t7519 contains a few test cases that rely on the current confusing behavior where `git submodule update --remote` fetches the remote `master` even if that is not the remote repository's current branch!

I did adjust t7519 to stop verifying this confusing behavior, and to verify the saner behavior instead.

This is of course a bit worrisome, as there might actually be users out there relying on the confusing behavior.

However, I think it is okay to fix this:
- The `git submodule update --remote` command does not strike me as
  awfully common. In fact, I had never heard of it before I worked on this
  here patch.
- Current Git's behavior when running this command is outright confusing,
  unless the remote repository's current branch _is_ `master` (in which
  case the proposed behavior matches the old behavior).
- It is actually easily fixed by setting `submodule.<name>.branch` to
  `master` _iff_ users want to reinstate the old behavior.
Show 5 quoted lines
> Alternatively, submodule--helper could pass back the empty string for
> "no, we don't have a configured branch name" and this shell code could
> actually try a sequence of reasonable guesses: init.mainbranch, then
> "master" (and between the two, "main" if that later becomes the
> default).
Quite honestly: I'd rather not.

Thank you, Dscho

Jeff King· Jun 23, 2020, 21:14 UTC · re: Johannes Schindelin · lore

Re: [PATCH v2 11/12] submodule: use the correct default for the main branch name

On Tue, Jun 23, 2020 at 11:03:57PM +0200, Johannes Schindelin wrote:
Show 18 quoted lines
> > [use HEAD instead of master]
> This is the route that I am taking.
> [...]
> This is of course a bit worrisome, as there might actually be users out
> there relying on the confusing behavior.
> 
> However, I think it is okay to fix this:
> 
> - The `git submodule update --remote` command does not strike me as
>   awfully common. In fact, I had never heard of it before I worked on this
>   here patch.
> 
> - Current Git's behavior when running this command is outright confusing,
>   unless the remote repository's current branch _is_ `master` (in which
>   case the proposed behavior matches the old behavior).
> 
> - It is actually easily fixed by setting `submodule.<name>.branch` to
>   `master` _iff_ users want to reinstate the old behavior.

Thanks, I agree that this is the best way forward, and that the current confusing behavior is as likely to be doing the wrong thing as the right (when it even differs).

-Peff
Johannes Schindelin via GitGitGadget· Jun 15, 2020, 12:50 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v2 09/12] clone: handle overridden main branch names

From: Johannes Schindelin <johannes.schindelin@gmx.de>

When cloning a repository without any branches, Git chooses a default branch name for the as-yet unborn branch.

As part of the implicit initialization of the local repository, Git just learned to respect `init.defaultBranch` to choose a different main branch name. We now really want that branch name to be used as a fall-back.

At the same time, we also want to make sure that `core.mainBranch` is set correctly, reflecting the name of the main branch. In case we detect a main branch, we do have to do that explicitly, otherwise `init_db()` will already have done that for us.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 Documentation/config/init.txt |  4 ++--
 builtin/clone.c               | 16 +++++++++++++---
 t/t5606-clone-options.sh      | 17 +++++++++++++++++
 3 files changed, 32 insertions(+), 5 deletions(-)
Show changes to 3 files +32 −5

Documentation/config/init.txt, builtin/clone.c, t/t5606-clone-options.sh

diff --git a/Documentation/config/init.txt b/Documentation/config/init.txt
index 6ae4a38416e..dc77f8c8446 100644
--- a/Documentation/config/init.txt
+++ b/Documentation/config/init.txt
@@ -3,5 +3,5 @@ init.templateDir::
 	(See the "TEMPLATE DIRECTORY" section of linkgit:git-init[1].)
 
 init.defaultBranch::
-	Allows overriding the default branch name when initializing
-	a new repository.
+	Allows overriding the default branch name e.g. when initializing
+	a new repository or when cloning an empty repository.
diff --git a/builtin/clone.c b/builtin/clone.c
index 487b0a42d75..755fcaeb0ba 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -718,6 +718,7 @@ static void update_head(const struct ref *our, const struct ref *remote,
 		/* Local default branch link */
 		if (create_symref("HEAD", our->name, NULL) < 0)
 			die(_("unable to update HEAD"));
+		git_config_set("core.mainbranch", head);
 		if (!option_bare) {
 			update_ref(msg, "HEAD", &our->old_oid, NULL, 0,
 				   UPDATE_REFS_DIE_ON_ERR);
@@ -1264,9 +1265,18 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		remote_head_points_at = NULL;
 		remote_head = NULL;
 		option_no_checkout = 1;
-		if (!option_bare)
-			install_branch_config(0, "master", option_origin,
-					      "refs/heads/master");
+		if (!option_bare) {
+			char *main_branch =
+				git_main_branch_name(MAIN_BRANCH_FULL_NAME);
+			const char *nick;
+
+			if (!skip_prefix(main_branch, "refs/heads/", &nick))
+				BUG("unexpected default branch '%s'",
+				    main_branch);
+			install_branch_config(0, nick, option_origin,
+					      main_branch);
+			free(main_branch);
+		}
 	}
 
 	write_refspec_config(src_ref_prefix, our_head_points_at,
diff --git a/t/t5606-clone-options.sh b/t/t5606-clone-options.sh
index 9e24ec88e67..98b2d8527f6 100755
--- a/t/t5606-clone-options.sh
+++ b/t/t5606-clone-options.sh
@@ -35,4 +35,21 @@ test_expect_success 'redirected clone -v does show progress' '
 
 '
 
+test_expect_success 'chooses correct default main branch name' '
+	git init --bare empty &&
+	git -c init.defaultBranch=up clone empty whats-up &&
+	test refs/heads/up = $(git -C whats-up symbolic-ref HEAD) &&
+	test up = $(git -C whats-up config core.mainBranch) &&
+	test refs/heads/up = $(git -C whats-up config branch.up.merge)
+'
+
+test_expect_success 'guesses main branch name correctly' '
+	git init --main-branch=guess main-branch &&
+	test_commit -C main-branch no-spoilers &&
+	git -C main-branch branch abc guess &&
+	git clone main-branch is-it &&
+	test guess = $(git -C is-it config core.mainBranch) &&
+	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD)
+'
+
 test_done
-- 
gitgitgadget
Jeff King· Jun 16, 2020, 13:22 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH v2 09/12] clone: handle overridden main branch names

On Mon, Jun 15, 2020 at 12:50:13PM +0000, Johannes Schindelin via GitGitGadget wrote:
Show 12 quoted lines
> diff --git a/builtin/clone.c b/builtin/clone.c
> index 487b0a42d75..755fcaeb0ba 100644
> --- a/builtin/clone.c
> +++ b/builtin/clone.c
> @@ -718,6 +718,7 @@ static void update_head(const struct ref *our, const struct ref *remote,
>  		/* Local default branch link */
>  		if (create_symref("HEAD", our->name, NULL) < 0)
>  			die(_("unable to update HEAD"));
> +		git_config_set("core.mainbranch", head);
>  		if (!option_bare) {
>  			update_ref(msg, "HEAD", &our->old_oid, NULL, 0,
>  				   UPDATE_REFS_DIE_ON_ERR);
Just making sure I understand what's going on here...

This covers the case that we've run "clone -b foo" or similar, but there are two other case arms when "foo" is a tag, or the remote HEAD is unreachable. And there we don't set core.mainbranch at all.

But we would not want it to be missing, because that will likely need to stay a default for "master" indefinitely (to keep behavior for existing repositories). However, it won't be missing. We'll always have set it during the init_db() call, and this is just overriding that. So we'd end update_head() with either:

  - core.mainbranch set to the same branch we point HEAD to, whether we
    got it from the remote side or from "-b foo"
  - if we write a detached HEAD, then core.mainbranch remains at
    init.mainbranch (or defaulting to "master" now, and probably "main"
    later). We have no better option.
If so, then that makes sense to me.
-Peff
Johannes Schindelin· Jun 23, 2020, 20:58 UTC · re: Jeff King · lore

Re: [PATCH v2 09/12] clone: handle overridden main branch names

Hi Peff,
On Tue, 16 Jun 2020, Jeff King wrote:
Show 20 quoted lines
> On Mon, Jun 15, 2020 at 12:50:13PM +0000, Johannes Schindelin via GitGitGadget wrote:
>
> > diff --git a/builtin/clone.c b/builtin/clone.c
> > index 487b0a42d75..755fcaeb0ba 100644
> > --- a/builtin/clone.c
> > +++ b/builtin/clone.c
> > @@ -718,6 +718,7 @@ static void update_head(const struct ref *our, const struct ref *remote,
> >  		/* Local default branch link */
> >  		if (create_symref("HEAD", our->name, NULL) < 0)
> >  			die(_("unable to update HEAD"));
> > +		git_config_set("core.mainbranch", head);
> >  		if (!option_bare) {
> >  			update_ref(msg, "HEAD", &our->old_oid, NULL, 0,
> >  				   UPDATE_REFS_DIE_ON_ERR);
>
> Just making sure I understand what's going on here...
>
> This covers the case that we've run "clone -b foo" or similar, but there
> are two other case arms when "foo" is a tag, or the remote HEAD is
> unreachable. And there we don't set core.mainbranch at all.

It was actually meant to catch the case where the remote repository has a default branch other than `master`.

Show 14 quoted lines
> But we would not want it to be missing, because that will likely need to
> stay a default for "master" indefinitely (to keep behavior for existing
> repositories). However, it won't be missing. We'll always have set it
> during the init_db() call, and this is just overriding that. So we'd end
> update_head() with either:
>
>   - core.mainbranch set to the same branch we point HEAD to, whether we
>     got it from the remote side or from "-b foo"
>
>   - if we write a detached HEAD, then core.mainbranch remains at
>     init.mainbranch (or defaulting to "master" now, and probably "main"
>     later). We have no better option.
>
> If so, then that makes sense to me.

In any case, this does not matter anymore, as I am dropping `core.mainBranch` from v3, as you had suggested elsewhere in this thread.

Ciao, Dscho

Don Goodman-Wilson via GitGitGadget· Jun 15, 2020, 12:50 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v2 08/12] init: allow overriding the default main branch name via the config

From: Don Goodman-Wilson <don@goodman-wilson.com>

We just introduced the command-line option `--main-branch=<branch-name>` to allow initializing a new repository with a different initial branch than the hard-coded one.

To allow users to override the default main branch name more permanently (i.e. without having to specify the name manually for each and every `git init` invocation), let's introduce the `init.defaultBranch` config setting.

Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Helped-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Don Goodman-Wilson <don@goodman-wilson.com>
---
 Documentation/config/init.txt |  4 ++++
 builtin/init-db.c             |  6 ++++--
 refs.c                        |  7 +++++--
 refs.h                        |  4 ++++
 t/t0001-init.sh               | 16 ++++++++++++++++
 5 files changed, 33 insertions(+), 4 deletions(-)
Show changes to 5 files +33 −4

Documentation/config/init.txt, builtin/init-db.c, refs.c, refs.h, t/t0001-init.sh

diff --git a/Documentation/config/init.txt b/Documentation/config/init.txt
index 46fa8c6a082..6ae4a38416e 100644
--- a/Documentation/config/init.txt
+++ b/Documentation/config/init.txt
@@ -1,3 +1,7 @@
 init.templateDir::
 	Specify the directory from which templates will be copied.
 	(See the "TEMPLATE DIRECTORY" section of linkgit:git-init[1].)
+
+init.defaultBranch::
+	Allows overriding the default branch name when initializing
+	a new repository.
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 287cdafaab1..d09c9dc7845 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -266,10 +266,11 @@ static int create_default_files(const char *template_path,
 	reinit = (!access(path, R_OK)
 		  || readlink(path, junk, sizeof(junk)-1) != -1);
 	if (!reinit) {
-		char *ref;
+		char *ref, *fall_back = NULL;
 
 		if (!main_branch)
-			main_branch = "master";
+			main_branch = fall_back =
+				git_main_branch_name(MAIN_BRANCH_FOR_INIT);
 
 		ref = xstrfmt("refs/heads/%s", main_branch);
 		if (check_refname_format(ref, 0) < 0)
@@ -280,6 +281,7 @@ static int create_default_files(const char *template_path,
 		free(ref);
 
 		git_config_set("core.mainbranch", main_branch);
+		free(fall_back);
 	} else if (main_branch)
 		warning(_("re-init: ignoring --main-branch=%s"), main_branch);
 
diff --git a/refs.c b/refs.c
index 7da3ac178c4..4b0e5b14062 100644
--- a/refs.c
+++ b/refs.c
@@ -563,8 +563,11 @@ void expand_ref_prefix(struct argv_array *prefixes, const char *prefix)
 char *repo_main_branch_name(struct repository *r, int flags)
 {
 	int full_name = flags & MAIN_BRANCH_FULL_NAME;
-	const char *config_key = "core.mainbranch";
-	const char *config_display_key = "core.mainBranch";
+	int for_init = flags & MAIN_BRANCH_FOR_INIT;
+	const char *config_key = for_init ?
+		 "init.defaultbranch" : "core.mainbranch";
+	const char *config_display_key = for_init ?
+		 "init.defaultBranch" : "core.mainBranch";
 	const char *fall_back = "master";
 	char *name = NULL, *ret;
 
diff --git a/refs.h b/refs.h
index 96472f9a9f5..c801d08490c 100644
--- a/refs.h
+++ b/refs.h
@@ -158,10 +158,14 @@ 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
  * repository.
  *
+ * To obtain the default for newly-initialized repositories, pass the flag
+ * `MAIN_BRANCH_FOR_INIT`.
+ *
  * The result is an allocated string. Unless the flags ask for a short name, it
  * will be prefixed with "refs/heads/".
  */
 #define MAIN_BRANCH_FULL_NAME (1<<0)
+#define MAIN_BRANCH_FOR_INIT   (1<<1)
 char *git_main_branch_name(int flags);
 char *repo_main_branch_name(struct repository *r, int flags);
 
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index 5d8e321a703..fbf02066940 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -479,4 +479,20 @@ test_expect_success '--main-branch' '
 	grep hello actual
 '
 
+test_expect_success 'overridden default main branch name (config)' '
+	test_config_global init.defaultBranch nmb &&
+	git init main-branch-config &&
+	git -C main-branch-config symbolic-ref HEAD >actual &&
+	grep nmb actual &&
+	git -C main-branch-config config core.mainBranch >actual &&
+	echo nmb >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'invalid default branch name' '
+	test_config_global init.defaultBranch "with space" &&
+	test_must_fail git init main-branch-invalid 2>err &&
+	test_i18ngrep "invalid branch name" err
+'
+
 test_done
-- 
gitgitgadget
Johannes Schindelin via GitGitGadget· Jun 15, 2020, 12:50 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v2 07/12] init: allow specifying the main branch name for the new repository

From: Johannes Schindelin <johannes.schindelin@gmx.de>

There is a growing number of projects trying to avoid the non-inclusive name `master` in their repositories: The `master`/`slave` terminology is insensitive and perpetuates injustice. This `master`/`slave` idea is actually where Git's naming comes from, as it was inherited from BitKeeper which uses the term in exactly this way, see https://mail.gnome.org/archives/desktop-devel-list/2019-May/msg00066.html

To change that branch name for new repositories, currently the only way to do that automatically is by copying all of Git's template directory, then hard-coding the desired default branch name into the `.git/HEAD` file, and then configuring `init.templateDir` to point to those copied template files.

To make this process much less cumbersome, let's introduce a new option: `--main-branch=<branch-name>`.

This will not only initialize the repository with the specified initial branch; It will also record that branch name in `core.mainBranch`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 Documentation/git-init.txt |  7 +++++++
 builtin/clone.c            |  3 ++-
 builtin/init-db.c          | 34 +++++++++++++++++++++++++++-------
 cache.h                    |  2 +-
 t/t0001-init.sh            | 15 +++++++++++++++
 5 files changed, 52 insertions(+), 9 deletions(-)
Show changes to 5 files +52 −9

Documentation/git-init.txt, builtin/clone.c, builtin/init-db.c, cache.h, t/t0001-init.sh

diff --git a/Documentation/git-init.txt b/Documentation/git-init.txt
index adc6adfd380..011a7ff4d76 100644
--- a/Documentation/git-init.txt
+++ b/Documentation/git-init.txt
@@ -11,6 +11,7 @@ SYNOPSIS
 [verse]
 'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
 	  [--separate-git-dir <git dir>] [--object-format=<format]
+	  [-b <branch-name> | --main-branch=<branch-name>]
 	  [--shared[=<permissions>]] [directory]
 
 
@@ -67,6 +68,12 @@ repository.
 +
 If this is reinitialization, the repository will be moved to the specified path.
 
+-b <branch-name::
+--main-branch=<branch-name>::
+
+Use the specified name for the main (or: initial) branch in the newly created
+repository. If not specified, fall back to the default name: `master`.
+
 --shared[=(false|true|umask|group|all|world|everybody|0xxx)]::
 
 Specify that the Git repository is to be shared amongst several users.  This
diff --git a/builtin/clone.c b/builtin/clone.c
index cb48a291caf..487b0a42d75 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1108,7 +1108,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		}
 	}
 
-	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, INIT_DB_QUIET);
+	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL,
+		INIT_DB_QUIET);
 
 	if (real_git_dir)
 		git_dir = real_git_dir;
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 0b7222e7188..287cdafaab1 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -203,6 +203,7 @@ void initialize_repository_version(int hash_algo)
 
 static int create_default_files(const char *template_path,
 				const char *original_git_dir,
+				const char *main_branch,
 				const struct repository_format *fmt)
 {
 	struct stat st1;
@@ -258,16 +259,29 @@ static int create_default_files(const char *template_path,
 		die("failed to set up refs db: %s", err.buf);
 
 	/*
-	 * Create the default symlink from ".git/HEAD" to the "master"
-	 * branch, if it does not exist yet.
+	 * Create the default symlink from ".git/HEAD" to the default
+	 * branch name, if it does not exist yet.
 	 */
 	path = git_path_buf(&buf, "HEAD");
 	reinit = (!access(path, R_OK)
 		  || readlink(path, junk, sizeof(junk)-1) != -1);
 	if (!reinit) {
-		if (create_symref("HEAD", "refs/heads/master", NULL) < 0)
+		char *ref;
+
+		if (!main_branch)
+			main_branch = "master";
+
+		ref = xstrfmt("refs/heads/%s", main_branch);
+		if (check_refname_format(ref, 0) < 0)
+			die(_("invalid main branch name: '%s'"), main_branch);
+
+		if (create_symref("HEAD", ref, NULL) < 0)
 			exit(1);
-	}
+		free(ref);
+
+		git_config_set("core.mainbranch", main_branch);
+	} else if (main_branch)
+		warning(_("re-init: ignoring --main-branch=%s"), main_branch);
 
 	initialize_repository_version(fmt->hash_algo);
 
@@ -383,7 +397,8 @@ static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash
 }
 
 int init_db(const char *git_dir, const char *real_git_dir,
-	    const char *template_dir, int hash, unsigned int flags)
+	    const char *template_dir, int hash, const char *main_branch,
+	    unsigned int flags)
 {
 	int reinit;
 	int exist_ok = flags & INIT_DB_EXIST_OK;
@@ -425,7 +440,8 @@ int init_db(const char *git_dir, const char *real_git_dir,
 
 	validate_hash_algorithm(&repo_fmt, hash);
 
-	reinit = create_default_files(template_dir, original_git_dir, &repo_fmt);
+	reinit = create_default_files(template_dir, original_git_dir,
+				      main_branch, &repo_fmt);
 
 	create_object_directory();
 
@@ -528,6 +544,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	const char *template_dir = NULL;
 	unsigned int flags = 0;
 	const char *object_format = NULL;
+	const char *main_branch = NULL;
 	int hash_algo = GIT_HASH_UNKNOWN;
 	const struct option init_db_options[] = {
 		OPT_STRING(0, "template", &template_dir, N_("template-directory"),
@@ -541,6 +558,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 		OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET),
 		OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
 			   N_("separate git dir from working tree")),
+		OPT_STRING('b', "main-branch", &main_branch, N_("name"),
+			   N_("override the name of the main branch")),
 		OPT_STRING(0, "object-format", &object_format, N_("hash"),
 			   N_("specify the hash algorithm to use")),
 		OPT_END()
@@ -652,5 +671,6 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	UNLEAK(work_tree);
 
 	flags |= INIT_DB_EXIST_OK;
-	return init_db(git_dir, real_git_dir, template_dir, hash_algo, flags);
+	return init_db(git_dir, real_git_dir, template_dir, hash_algo,
+		       main_branch, flags);
 }
diff --git a/cache.h b/cache.h
index 0f0485ecfe2..afd5ad3121f 100644
--- a/cache.h
+++ b/cache.h
@@ -628,7 +628,7 @@ int path_inside_repo(const char *prefix, const char *path);
 
 int init_db(const char *git_dir, const char *real_git_dir,
 	    const char *template_dir, int hash_algo,
-	    unsigned int flags);
+	    const char *main_branch, unsigned int flags);
 void initialize_repository_version(int hash_algo);
 
 void sanitize_stdfds(void);
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index 1edd5aeb8f0..5d8e321a703 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -464,4 +464,19 @@ test_expect_success MINGW 'redirect std handles' '
 	grep "Needed a single revision" output.txt
 '
 
+test_expect_success '--main-branch' '
+	git init --main-branch=hello main-branch-option &&
+	git -C main-branch-option symbolic-ref HEAD >actual &&
+	echo refs/heads/hello >expect &&
+	test_cmp expect actual &&
+
+	: re-initializing should not change the main branch name &&
+	git init --main-branch=ignore main-branch-option 2>err &&
+	test_i18ngrep "ignoring --main-branch" err &&
+	git -C main-branch-option symbolic-ref HEAD >actual &&
+	grep hello actual &&
+	git -C main-branch-option config core.mainBranch >actual &&
+	grep hello actual
+'
+
 test_done
-- 
gitgitgadget
Johannes Schindelin via GitGitGadget· Jun 23, 2020, 22:33 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v3 0/8] Allow overriding the default name of the default branch

A growing number of open source projects aims to avoid the branch name master due to its negative connotation. See [1] for an existing discussion on this. The links [2], [3], and [4] describe community-driven ways for users to rename their default branches or use template edits to set a new default branch name.

[1] https://lore.kernel.org/git/CAOAHyQwyXC1Z3v7BZAC+Bq6JBaM7FvBenA-1fcqeDV==apdWDg@mail.gmail.com/

[2] https://twitter.com/mislav/status/1270388510684598272

[3] https://www.hanselman.com/blog/EasilyRenameYourGitDefaultBranchFromMasterToMain.aspx

[4] https://github.com/ethomson/retarget_prs

By necessity, existing repositories require a lot of manual work to move away from that branch name, but it should be much easier for new repositories.

This patch series allows overriding the branch name being used for new repositories' main branch. This can be configured via init.defaultBranch.

The initial patch was started by newcomer Don Goodman-Wilson, as well as the bigger change that morphed into #655, where we demonstrate how to change Git's hard-coded default branch name for new repositories to main based on this here patch series, verifying the approach. Thanks for the contribution!

This series DOES NOT change the default automatically, but only provides an opt-in mechanism for interested users. The plan for that is to convert the test scripts incrementally (by introducing GIT_TEST_DEFAULT_MAIN_BRANCH_NAME , which overrides init.defaultBranch, and then converting the tricky test scripts first, one by one, using that environment variable).

Changes since v2:
 * Dropped the fast-export patches, as they have been superseded by Peff's 
   jk/fast-export-anonym
   [https://github.com/gitgitgadget/git/commits/jk/fast-export-anonym].
   
   
 * Adjusted the fmt-merge-msg patch so as to not special-case master anymore
   (instead of special-casing a specific "main" branch).
   
   
 * Modified the git submodule patch so that it uses origin/HEAD instead of
   trying to look for a remote branch with the name indicated by 
   init.defaultBranch.
   
   
Changes since v1:
 * The modifications to respect GIT_TEST_DEFAULT_BRANCH_NAME have been
   backed out from this patch series, as they are only relevant once we
   start converting the test suite to accommodate for a new default main
   branch name.
   
   
 * An error message that started with an upper-case letter was downcased.
   
   
 * git_default_branch_name()'s logic was simplified by replacing an if ...
   else ... by a ternary assignment.
   
   
 * The git_default_branch_name() function was renamed to 
   git_main_branch_name() and a corresponding repo_main_branch_name() was
   introduced.
   
   
 * The "init" commit message's first paragraph now elaborates a little bit
   on the reasoning why projects want to move away from the current default
   branch name.
   
   
 * The "init" commit was split into two.
   
   
 * There are now two config settings: init.defaultBranch (defining the
   branch name to use when initializing new repositories) and 
   core.mainBranch (which is now configured by init_db(), declaring what the
   name of the main branch is in this repository).
   
   
 * The commits were re-ordered to introduce the concept of core.mainBranch 
   first because technically, this is something that we could do even
   without changing git init at all.
   
   
 * git fast-export --anonymize now always uses the ref name ref0 for the
   main branch, no matter whether it was overridden or whether the fall-back
   is in effect.
   
   
 * The code comment regarding anonymizing the main branch to ref0 in git
   fast-export --anonymize was enhanced.
   
   
 * A new patch was added to rename core.mainBranch if the main branch is
   renamed via git branch -m.
   
   
 * Added a patch that introduces support for git init
   --main-branch=<branch-name>.
   
   
 * Where possible, I added tests (although I did not try to extend test
   coverage to all changes: the send-pack.c/transport-helper.c patch only
   adds a test for the send-pack.c adjustment, for example).
Don Goodman-Wilson (1):
  init: allow setting the default for the initial branch name via the
    config
Johannes Schindelin (7):
  fmt-merge-msg: stop treating `master` specially
  send-pack/transport-helper: avoid mentioning a particular branch
  submodule: use a better fall-back for missing remote.<name>.branch
  init: allow specifying the initial branch name for the new repository
  clone: use configured default branch name when appropriate
  remote: use the configured default branch name when appropriate
  testsvn: respect `init.defaultBranch`
 Documentation/config/init.txt                 |  4 ++
 Documentation/git-init.txt                    |  7 ++
 Documentation/git-submodule.txt               |  4 +-
 builtin/clone.c                               | 13 ++--
 builtin/init-db.c                             | 34 +++++++--
 builtin/submodule--helper.c                   |  2 +-
 cache.h                                       |  2 +-
 fmt-merge-msg.c                               |  5 +-
 refs.c                                        | 30 ++++++++
 refs.h                                        |  9 +++
 remote-testsvn.c                              | 10 ++-
 remote.c                                      | 14 +++-
 send-pack.c                                   |  2 +-
 t/t0001-init.sh                               | 26 +++++++
 t/t1507-rev-parse-upstream.sh                 |  2 +-
 t/t4013-diff-various.sh                       |  4 +-
 t/t4013/diff.log_--decorate=full_--all        |  2 +-
 t/t4013/diff.log_--decorate_--all             |  2 +-
 ...--patch-with-stat_--summary_master_--_dir_ |  2 +-
 t/t4013/diff.log_--patch-with-stat_master     |  2 +-
 .../diff.log_--patch-with-stat_master_--_dir_ |  2 +-
 ...ot_--cc_--patch-with-stat_--summary_master |  2 +-
 ..._--root_--patch-with-stat_--summary_master |  2 +-
 .../diff.log_--root_--patch-with-stat_master  |  2 +-
 ...root_-c_--patch-with-stat_--summary_master |  2 +-
 t/t4013/diff.log_--root_-p_master             |  2 +-
 t/t4013/diff.log_--root_master                |  2 +-
 t/t4013/diff.log_-m_-p_--first-parent_master  |  2 +-
 t/t4013/diff.log_-m_-p_master                 |  4 +-
 t/t4013/diff.log_-p_--first-parent_master     |  2 +-
 t/t4013/diff.log_-p_master                    |  2 +-
 t/t4013/diff.log_master                       |  2 +-
 t/t4013/diff.show_--first-parent_master       |  2 +-
 t/t4013/diff.show_-c_master                   |  2 +-
 t/t4013/diff.show_-m_master                   |  4 +-
 t/t4013/diff.show_master                      |  2 +-
 ...ot_--cc_--patch-with-stat_--summary_master |  2 +-
 ...root_-c_--patch-with-stat_--summary_master |  2 +-
 t/t4202-log.sh                                | 72 +++++++++----------
 t/t5528-push-default.sh                       |  6 ++
 t/t5606-clone-options.sh                      | 24 +++++++
 t/t6200-fmt-merge-msg.sh                      | 36 +++++-----
 t/t7406-submodule-update.sh                   | 16 +++++
 t/t7419-submodule-set-branch.sh               |  7 +-
 t/t7600-merge.sh                              | 14 ++--
 t/t7608-merge-messages.sh                     | 10 +--
 t/t9020-remote-svn.sh                         |  6 ++
 transport-helper.c                            |  2 +-
 48 files changed, 287 insertions(+), 122 deletions(-)
base-commit: c9c318d6bf26bcecdca5b6f31683b9d5887a83ee
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-656%2Fdscho%2Fdefault-branch-name-option-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-656/dscho/default-branch-name-option-v3
Pull-Request: https://github.com/gitgitgadget/git/pull/656
Range-diff vs v2:
  1:  ebd10f73cd <  -:  ---------- fast-export: do anonymize the primary branch name
  -:  ---------- >  1:  fffdb9944f fmt-merge-msg: stop treating `master` specially
  3:  bd8af3755a !  2:  a29943d7bb send-pack/transport-helper: respect `core.mainBranch`
     @@ Metadata
      Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
      
       ## Commit message ##
     -    send-pack/transport-helper: respect `core.mainBranch`
     +    send-pack/transport-helper: avoid mentioning a particular branch
      
     -    When mentioning the main branch name in an error message, we want to go
     -    with the preference specified by the user, only falling back to Git's
     -    own, hard-coded default when none was configured explicitly.
     +    When trying to push all matching branches, but none match, we offer a
     +    message suggesting to push the `master` branch.
     +
     +    However, we want to step away from making that branch any more special
     +    than any other branch, so let's reword that message to mention no branch
     +    in particular.
      
          Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
      
       ## send-pack.c ##
      @@ send-pack.c: int send_pack(struct send_pack_args *args,
     - 	}
       
       	if (!remote_refs) {
     -+		char *branch_name = git_main_branch_name();
     -+
       		fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
      -			"Perhaps you should specify a branch such as 'master'.\n");
     -+			"Perhaps you should specify a branch such as '%s'.\n",
     -+			branch_name);
     -+		free(branch_name);
     ++			"Perhaps you should specify a specific branch.\n");
       		return 0;
       	}
       	if (args->atomic && !atomic_supported)
     @@ t/t5528-push-default.sh: test_expect_success 'push from/to new branch with upstr
       
      +test_expect_success '"matching" fails if none match' '
      +	git init --bare empty &&
     -+	test_must_fail git -c core.mainBranch=unmatch push empty : 2>actual &&
     -+	needle="Perhaps you should specify a branch such as '\''unmatch'\''" &&
     -+	test_i18ngrep "$needle" actual
     ++	test_must_fail git push empty : 2>actual &&
     ++	test_i18ngrep "Perhaps you should specify a specific branch" actual
      +'
      +
       test_expect_success 'push ambiguously named branch with upstream, matching and simple' '
     @@ t/t5528-push-default.sh: test_expect_success 'push from/to new branch with upstr
      
       ## transport-helper.c ##
      @@ transport-helper.c: static int push_refs(struct transport *transport,
     - 	}
     - 
       	if (!remote_refs) {
     -+		char *branch_name = git_main_branch_name();
     -+
       		fprintf(stderr,
       			_("No refs in common and none specified; doing nothing.\n"
      -			  "Perhaps you should specify a branch such as 'master'.\n"));
     -+			  "Perhaps you should specify a branch such as '%s'.\n"),
     -+			branch_name);
     -+		free(branch_name);
     ++			  "Perhaps you should specify a specific branch.\n"));
       		return 0;
       	}
       
 11:  59d6267f09 !  3:  6bda69541b submodule: use the correct default for the main branch name
     @@ Metadata
      Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
      
       ## Commit message ##
     -    submodule: use the correct default for the main branch name
     +    submodule: use a better fall-back for missing remote.<name>.branch
      
     -    To allow for overriding the default branch name, we have introduced a
     -    config setting. With this patch, the `git submodule` command learns
     -    about this, too.
     +    When `remote.<name>.branch` is not configured, `git submodule update`
     +    currently falls back to using the branch name `master`. A much better
     +    idea, however, is to use `HEAD`: on all Git servers running reasonably
     +    recent Git versions, the symref `HEAD` points to the main branch.
     +
     +    Note: t7419 demonstrates that there _might_ be use cases out there that
     +    _expect_ `git submodule update --remote` to update submodules to the
     +    remote `master` branch even if the remote `HEAD` points to another
     +    branch. Arguably, this patch makes the behavior more intuitive, but
     +    there is a slight possibility that this might cause regressions in
     +    obscure setups.
      
          Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
      
     + ## Documentation/git-submodule.txt ##
     +@@ Documentation/git-submodule.txt: OPTIONS
     + 	`.gitmodules` for `update --remote`.  A special value of `.` is used to
     + 	indicate that the name of the branch in the submodule should be the
     + 	same name as the current branch in the current repository.  If the
     +-	option is not specified, it defaults to 'master'.
     ++	option is not specified, it defaults to 'HEAD'.
     + 
     + -f::
     + --force::
     +@@ Documentation/git-submodule.txt: OPTIONS
     + 	the superproject's recorded SHA-1 to update the submodule, use the
     + 	status of the submodule's remote-tracking branch.  The remote used
     + 	is branch's remote (`branch.<name>.remote`), defaulting to `origin`.
     +-	The remote branch used defaults to `master`, but the branch name may
     ++	The remote branch used defaults to `HEAD`, but the branch name may
     + 	be overridden by setting the `submodule.<name>.branch` option in
     + 	either `.gitmodules` or `.git/config` (with `.git/config` taking
     + 	precedence).
     +
       ## builtin/submodule--helper.c ##
      @@ builtin/submodule--helper.c: static const char *remote_submodule_branch(const char *path)
     - 		branch = sub->branch;
       	free(key);
       
     --	if (!branch)
     + 	if (!branch)
      -		return "master";
     -+	if (!branch) {
     -+		static char *fall_back;
     -+
     -+		if (!fall_back)
     -+			fall_back = git_main_branch_name(MAIN_BRANCH_FOR_INIT);
     -+
     -+		return fall_back;
     -+	}
     ++		return "HEAD";
       
       	if (!strcmp(branch, ".")) {
       		const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
     @@ t/t7406-submodule-update.sh: test_expect_success 'setup a submodule tree' '
       	)
       '
       
     -+test_expect_success 'update --remote uses configured default main branch' '
     -+	git clone super main-branch &&
     -+	test_must_fail git -C main-branch -c init.defaultBranch=hello \
     -+		submodule update --init --remote submodule 2>err &&
     -+	test_i18ngrep origin/hello err
     ++test_expect_success 'update --remote falls back to using HEAD' '
     ++	test_create_repo main-branch-submodule &&
     ++	test_commit -C main-branch-submodule initial &&
     ++
     ++	test_create_repo main-branch &&
     ++	git -C main-branch submodule add ../main-branch-submodule &&
     ++	git -C main-branch commit -m add-submodule &&
     ++
     ++	git -C main-branch-submodule switch -c hello &&
     ++	test_commit -C main-branch-submodule world &&
     ++
     ++	git clone --recursive main-branch main-branch-clone &&
     ++	git -C main-branch-clone submodule update --remote main-branch-submodule &&
     ++	test_path_exists main-branch-clone/main-branch-submodule/world.t
      +'
      +
       test_expect_success 'submodule update detaching the HEAD ' '
       	(cd super/submodule &&
       	 git reset --hard HEAD~1
     +
     + ## t/t7419-submodule-set-branch.sh ##
     +@@ t/t7419-submodule-set-branch.sh: test_expect_success 'test submodule set-branch --branch' '
     + '
     + 
     + test_expect_success 'test submodule set-branch --default' '
     ++	test_commit -C submodule c &&
     + 	(cd super &&
     + 		git submodule set-branch --default submodule &&
     + 		! grep branch .gitmodules &&
     + 		git submodule update --remote &&
     + 		cat <<-\EOF >expect &&
     +-		a
     ++		c
     + 		EOF
     + 		git -C submodule show -s --pretty=%s >actual &&
     + 		test_cmp expect actual
     +@@ t/t7419-submodule-set-branch.sh: test_expect_success 'test submodule set-branch --default' '
     + '
     + 
     + test_expect_success 'test submodule set-branch -b' '
     ++	test_commit -C submodule b &&
     + 	(cd super &&
     + 		git submodule set-branch -b topic submodule &&
     + 		grep "branch = topic" .gitmodules &&
     +@@ t/t7419-submodule-set-branch.sh: test_expect_success 'test submodule set-branch -b' '
     + '
     + 
     + test_expect_success 'test submodule set-branch -d' '
     ++	test_commit -C submodule d &&
     + 	(cd super &&
     + 		git submodule set-branch -d submodule &&
     + 		! grep branch .gitmodules &&
     + 		git submodule update --remote &&
     + 		cat <<-\EOF >expect &&
     +-		a
     ++		d
     + 		EOF
     + 		git -C submodule show -s --pretty=%s >actual &&
     + 		test_cmp expect actual
  7:  0ec04b2086 !  4:  e8a6587c1a init: allow specifying the main branch name for the new repository
     @@ Metadata
      Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
      
       ## Commit message ##
     -    init: allow specifying the main branch name for the new repository
     +    init: allow specifying the initial branch name for the new repository
      
     -    There is a growing number of projects trying to avoid the non-inclusive
     -    name `master` in their repositories: The `master`/`slave` terminology is
     -    insensitive and perpetuates injustice. This `master`/`slave` idea is
     -    actually where Git's naming comes from, as it was inherited from
     -    BitKeeper which uses the term in exactly this way, see
     -    https://mail.gnome.org/archives/desktop-devel-list/2019-May/msg00066.html
     +    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).
      
          To change that branch name for new repositories, currently the only way
          to do that automatically is by copying all of Git's template directory,
     @@ Commit message
          template files.
      
          To make this process much less cumbersome, let's introduce a new option:
     -    `--main-branch=<branch-name>`.
     -
     -    This will not only initialize the repository with the specified initial
     -    branch; It will also record that branch name in `core.mainBranch`.
     +    `--initial-branch=<branch-name>`.
      
          Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
      
     @@ Documentation/git-init.txt: SYNOPSIS
       [verse]
       'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
       	  [--separate-git-dir <git dir>] [--object-format=<format]
     -+	  [-b <branch-name> | --main-branch=<branch-name>]
     ++	  [-b <branch-name> | --initial-branch=<branch-name>]
       	  [--shared[=<permissions>]] [directory]
       
       
     @@ Documentation/git-init.txt: repository.
       If this is reinitialization, the repository will be moved to the specified path.
       
      +-b <branch-name::
     -+--main-branch=<branch-name>::
     ++--initial-branch=<branch-name>::
      +
     -+Use the specified name for the main (or: initial) branch in the newly created
     -+repository. If not specified, fall back to the default name: `master`.
     ++Use the specified name for the initial branch in the newly created repository.
     ++If not specified, fall back to the default name: `master`.
      +
       --shared[=(false|true|umask|group|all|world|everybody|0xxx)]::
       
     @@ builtin/init-db.c: void initialize_repository_version(int hash_algo)
       
       static int create_default_files(const char *template_path,
       				const char *original_git_dir,
     -+				const char *main_branch,
     ++				const char *initial_branch,
       				const struct repository_format *fmt)
       {
       	struct stat st1;
     @@ builtin/init-db.c: static int create_default_files(const char *template_path,
      -		if (create_symref("HEAD", "refs/heads/master", NULL) < 0)
      +		char *ref;
      +
     -+		if (!main_branch)
     -+			main_branch = "master";
     ++		if (!initial_branch)
     ++			initial_branch = "master";
      +
     -+		ref = xstrfmt("refs/heads/%s", main_branch);
     ++		ref = xstrfmt("refs/heads/%s", initial_branch);
      +		if (check_refname_format(ref, 0) < 0)
     -+			die(_("invalid main branch name: '%s'"), main_branch);
     ++			die(_("invalid initial branch name: '%s'"),
     ++			    initial_branch);
      +
      +		if (create_symref("HEAD", ref, NULL) < 0)
       			exit(1);
      -	}
      +		free(ref);
     -+
     -+		git_config_set("core.mainbranch", main_branch);
     -+	} else if (main_branch)
     -+		warning(_("re-init: ignoring --main-branch=%s"), main_branch);
     ++	} else if (initial_branch)
     ++		warning(_("re-init: ignoring --initial-branch=%s"),
     ++			initial_branch);
       
       	initialize_repository_version(fmt->hash_algo);
       
     @@ builtin/init-db.c: static void validate_hash_algorithm(struct repository_format
       
       int init_db(const char *git_dir, const char *real_git_dir,
      -	    const char *template_dir, int hash, unsigned int flags)
     -+	    const char *template_dir, int hash, const char *main_branch,
     ++	    const char *template_dir, int hash, const char *initial_branch,
      +	    unsigned int flags)
       {
       	int reinit;
     @@ builtin/init-db.c: int init_db(const char *git_dir, const char *real_git_dir,
       
      -	reinit = create_default_files(template_dir, original_git_dir, &repo_fmt);
      +	reinit = create_default_files(template_dir, original_git_dir,
     -+				      main_branch, &repo_fmt);
     ++				      initial_branch, &repo_fmt);
       
       	create_object_directory();
       
     @@ builtin/init-db.c: int cmd_init_db(int argc, const char **argv, const char *pref
       	const char *template_dir = NULL;
       	unsigned int flags = 0;
       	const char *object_format = NULL;
     -+	const char *main_branch = NULL;
     ++	const char *initial_branch = NULL;
       	int hash_algo = GIT_HASH_UNKNOWN;
       	const struct option init_db_options[] = {
       		OPT_STRING(0, "template", &template_dir, N_("template-directory"),
     @@ builtin/init-db.c: int cmd_init_db(int argc, const char **argv, const char *pref
       		OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET),
       		OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
       			   N_("separate git dir from working tree")),
     -+		OPT_STRING('b', "main-branch", &main_branch, N_("name"),
     -+			   N_("override the name of the main branch")),
     ++		OPT_STRING('b', "initial-branch", &initial_branch, N_("name"),
     ++			   N_("override the name of the initial branch")),
       		OPT_STRING(0, "object-format", &object_format, N_("hash"),
       			   N_("specify the hash algorithm to use")),
       		OPT_END()
     @@ builtin/init-db.c: int cmd_init_db(int argc, const char **argv, const char *pref
       	flags |= INIT_DB_EXIST_OK;
      -	return init_db(git_dir, real_git_dir, template_dir, hash_algo, flags);
      +	return init_db(git_dir, real_git_dir, template_dir, hash_algo,
     -+		       main_branch, flags);
     ++		       initial_branch, flags);
       }
      
       ## cache.h ##
     @@ cache.h: int path_inside_repo(const char *prefix, const char *path);
       int init_db(const char *git_dir, const char *real_git_dir,
       	    const char *template_dir, int hash_algo,
      -	    unsigned int flags);
     -+	    const char *main_branch, unsigned int flags);
     ++	    const char *initial_branch, unsigned int flags);
       void initialize_repository_version(int hash_algo);
       
       void sanitize_stdfds(void);
     @@ t/t0001-init.sh: test_expect_success MINGW 'redirect std handles' '
       	grep "Needed a single revision" output.txt
       '
       
     -+test_expect_success '--main-branch' '
     -+	git init --main-branch=hello main-branch-option &&
     -+	git -C main-branch-option symbolic-ref HEAD >actual &&
     ++test_expect_success '--initial-branch' '
     ++	git init --initial-branch=hello initial-branch-option &&
     ++	git -C initial-branch-option symbolic-ref HEAD >actual &&
      +	echo refs/heads/hello >expect &&
      +	test_cmp expect actual &&
      +
     -+	: re-initializing should not change the main branch name &&
     -+	git init --main-branch=ignore main-branch-option 2>err &&
     -+	test_i18ngrep "ignoring --main-branch" err &&
     -+	git -C main-branch-option symbolic-ref HEAD >actual &&
     -+	grep hello actual &&
     -+	git -C main-branch-option config core.mainBranch >actual &&
     ++	: re-initializing should not change the branch name &&
     ++	git init --initial-branch=ignore initial-branch-option 2>err &&
     ++	test_i18ngrep "ignoring --initial-branch" err &&
     ++	git -C initial-branch-option symbolic-ref HEAD >actual &&
      +	grep hello actual
      +'
      +
  2:  f4d5473915 !  5:  a500e0f214 fmt-merge-msg: introduce a way to override the main branch name
     @@
       ## Metadata ##
     -Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
     +Author: Don Goodman-Wilson <don@goodman-wilson.com>
      
       ## Commit message ##
     -    fmt-merge-msg: introduce a way to override the main branch name
     +    init: allow setting the default for the initial branch name via the config
      
     -    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).
     +    We just introduced the command-line option
     +    `--initial-branch=<branch-name>` to allow initializing a new repository
     +    with a different initial branch than the hard-coded one.
      
     -    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.
     +    To allow users to override the initial branch name more permanently
     +    (i.e. without having to specify the name manually for each and every
     +    `git init` invocation), let's introduce the `init.defaultBranch` config
     +    setting.
      
     -    Clearly, this is not what one wants when already having gone through all
     -    the steps to manually rename the main branch (and taking care of all the
     -    fall-out such as re-targeting existing Pull Requests).
     +    Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
     +    Helped-by: Derrick Stolee <dstolee@microsoft.com>
     +    Signed-off-by: Don Goodman-Wilson <don@goodman-wilson.com>
      
     -    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 <johannes.schindelin@gmx.de>
     -
     - ## Documentation/config/core.txt ##
     -@@ Documentation/config/core.txt: core.abbrev::
     - 	in your repository, which hopefully is enough for
     - 	abbreviated object names to stay unique for some time.
     - 	The minimum length is 4.
     + ## Documentation/config/init.txt ##
     +@@
     + init.templateDir::
     + 	Specify the directory from which templates will be copied.
     + 	(See the "TEMPLATE DIRECTORY" section of linkgit:git-init[1].)
      +
     -+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.
     ++init.defaultBranch::
     ++	Allows overriding the default branch name when initializing
     ++	a new repository.
      
     - ## fmt-merge-msg.c ##
     -@@ fmt-merge-msg.c: static void fmt_merge_msg_title(struct strbuf *out,
     - 				const char *current_branch)
     - {
     - 	int i = 0;
     --	char *sep = "";
     -+	char *sep = "", *main_branch;
     + ## builtin/init-db.c ##
     +@@ builtin/init-db.c: static int create_default_files(const char *template_path,
     + 		char *ref;
       
     - 	strbuf_addstr(out, "Merge ");
     - 	for (i = 0; i < srcs.nr; i++) {
     -@@ fmt-merge-msg.c: static void fmt_merge_msg_title(struct strbuf *out,
     - 			strbuf_addf(out, " of %s", srcs.items[i].string);
     - 	}
     + 		if (!initial_branch)
     +-			initial_branch = "master";
     ++			initial_branch = git_default_branch_name();
       
     --	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,
     + 		ref = xstrfmt("refs/heads/%s", initial_branch);
     + 		if (check_refname_format(ref, 0) < 0)
      
       ## refs.c ##
      @@ refs.c: 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)
     ++char *repo_default_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;
     ++	const char *config_key = "init.defaultbranch";
     ++	const char *config_display_key = "init.defaultBranch";
     ++	char *ret = NULL, *full_ref;
      +
     -+	if (repo_config_get_string(r, config_key, &name) < 0)
     ++	if (repo_config_get_string(r, config_key, &ret) < 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 (!ret)
     ++		ret = xstrdup("master");
      +
     -+	if (name != ret)
     -+		free(name);
     ++	full_ref = xstrfmt("refs/heads/%s", ret);
     ++	if (check_refname_format(full_ref, 0))
     ++		die(_("invalid branch name: %s = %s"), config_display_key, ret);
     ++	free(full_ref);
      +
      +	return ret;
      +}
      +
     -+char *git_main_branch_name(void)
     ++const char *git_default_branch_name(void)
      +{
     -+	return repo_main_branch_name(the_repository);
     ++	static char *ret;
     ++
     ++	if (!ret)
     ++		ret = repo_default_branch_name(the_repository);
     ++
     ++	return ret;
      +}
      +
       /*
     @@ refs.h: int repo_dwim_log(struct repository *r, const char *str, int len, struct
       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
     -+ * repository.
     ++ * Retrieves the default branch name for newly-initialized repositories.
     ++ *
     ++ * The return value of `repo_default_branch_name()` is an allocated string. The
     ++ * return value of `git_default_branch_name()` is a singleton.
      + */
     -+char *git_main_branch_name(void);
     -+char *repo_main_branch_name(struct repository *r);
     ++const char *git_default_branch_name(void);
     ++char *repo_default_branch_name(struct repository *r);
      +
       /*
        * A ref_transaction represents a collection of reference updates that
        * should succeed or fail together.
      
     - ## t/t6200-fmt-merge-msg.sh ##
     -@@ t/t6200-fmt-merge-msg.sh: test_expect_success 'setup FETCH_HEAD' '
     - 	git fetch . left
     + ## t/t0001-init.sh ##
     +@@ t/t0001-init.sh: test_expect_success '--initial-branch' '
     + 	grep hello actual
       '
       
     -+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 'overridden default initial branch name (config)' '
     ++	test_config_global init.defaultBranch nmb &&
     ++	git init initial-branch-config &&
     ++	git -C initial-branch-config symbolic-ref HEAD >actual &&
     ++	grep nmb actual
     ++'
     ++
     ++test_expect_success 'invalid default branch name' '
     ++	test_config_global init.defaultBranch "with space" &&
     ++	test_must_fail git init initial-branch-invalid 2>err &&
     ++	test_i18ngrep "invalid branch name" err
      +'
      +
     - test_expect_success 'merge.log=3 limits shortlog length' '
     - 	cat >expected <<-EOF &&
     - 	Merge branch ${apos}left${apos}
     + test_done
  4:  ca1c63c3e0 <  -:  ---------- git_main_branch_name(): optionally report the full ref name
  5:  a3be4f39aa <  -:  ---------- fast-export: handle overridden main branch names correctly
  6:  933e314813 <  -:  ---------- branch -m: adjust `core.mainBranch` if necessary
  8:  c711eba7e7 <  -:  ---------- init: allow overriding the default main branch name via the config
  9:  0e59b61816 !  6:  c0d74cedd1 clone: handle overridden main branch names
     @@ Metadata
      Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
      
       ## Commit message ##
     -    clone: handle overridden main branch names
     +    clone: use configured default branch name when appropriate
      
          When cloning a repository without any branches, Git chooses a default
          branch name for the as-yet unborn branch.
      
     -    As part of the implicit initialization of the local repository, Git
     -    just learned to respect `init.defaultBranch` to choose a different main
     +    As part of the implicit initialization of the local repository, Git just
     +    learned to respect `init.defaultBranch` to choose a different initial
          branch name. We now really want that branch name to be used as a
          fall-back.
      
     -    At the same time, we also want to make sure that `core.mainBranch` is
     -    set correctly, reflecting the name of the main branch. In case we detect
     -    a main branch, we do have to do that explicitly, otherwise `init_db()`
     -    will already have done that for us.
     -
          Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
      
       ## Documentation/config/init.txt ##
     @@ Documentation/config/init.txt: init.templateDir::
      +	a new repository or when cloning an empty repository.
      
       ## builtin/clone.c ##
     -@@ builtin/clone.c: static void update_head(const struct ref *our, const struct ref *remote,
     - 		/* Local default branch link */
     - 		if (create_symref("HEAD", our->name, NULL) < 0)
     - 			die(_("unable to update HEAD"));
     -+		git_config_set("core.mainbranch", head);
     - 		if (!option_bare) {
     - 			update_ref(msg, "HEAD", &our->old_oid, NULL, 0,
     - 				   UPDATE_REFS_DIE_ON_ERR);
      @@ builtin/clone.c: int cmd_clone(int argc, const char **argv, const char *prefix)
       		remote_head_points_at = NULL;
       		remote_head = NULL;
     @@ builtin/clone.c: int cmd_clone(int argc, const char **argv, const char *prefix)
      -			install_branch_config(0, "master", option_origin,
      -					      "refs/heads/master");
      +		if (!option_bare) {
     -+			char *main_branch =
     -+				git_main_branch_name(MAIN_BRANCH_FULL_NAME);
     -+			const char *nick;
     ++			const char *branch = git_default_branch_name();
     ++			char *ref = xstrfmt("refs/heads/%s", branch);
      +
     -+			if (!skip_prefix(main_branch, "refs/heads/", &nick))
     -+				BUG("unexpected default branch '%s'",
     -+				    main_branch);
     -+			install_branch_config(0, nick, option_origin,
     -+					      main_branch);
     -+			free(main_branch);
     ++			install_branch_config(0, branch, option_origin, ref);
     ++			free(ref);
      +		}
       	}
       
     @@ t/t5606-clone-options.sh: test_expect_success 'redirected clone -v does show pro
       
       '
       
     -+test_expect_success 'chooses correct default main branch name' '
     ++test_expect_success 'chooses correct default initial branch name' '
      +	git init --bare empty &&
      +	git -c init.defaultBranch=up clone empty whats-up &&
      +	test refs/heads/up = $(git -C whats-up symbolic-ref HEAD) &&
     -+	test up = $(git -C whats-up config core.mainBranch) &&
      +	test refs/heads/up = $(git -C whats-up config branch.up.merge)
      +'
      +
     -+test_expect_success 'guesses main branch name correctly' '
     -+	git init --main-branch=guess main-branch &&
     -+	test_commit -C main-branch no-spoilers &&
     -+	git -C main-branch branch abc guess &&
     -+	git clone main-branch is-it &&
     -+	test guess = $(git -C is-it config core.mainBranch) &&
     ++test_expect_success 'guesses initial branch name correctly' '
     ++	git init --initial-branch=guess initial-branch &&
     ++	test_commit -C initial-branch no-spoilers &&
     ++	git -C initial-branch branch abc guess &&
     ++	git clone initial-branch is-it &&
      +	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD)
      +'
      +
 10:  59b8f4cfbb !  7:  00a1b281e5 remote: learn about the possibly-overridden default main branch name
     @@ Metadata
      Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
      
       ## Commit message ##
     -    remote: learn about the possibly-overridden default main branch name
     +    remote: use the configured default branch name when appropriate
      
          When guessing the default branch name of a remote, and there are no refs
          to guess from, we want to go with the preference specified by the user
     -    for the fall-back, i.e. the default name to be used for the main branch
     -    of new repositories (because as far as the user is concerned, a remote
     -    that has no branches yet is a new repository).
     +    for the fall-back, i.e. the default name to be used for the initial
     +    branch of new repositories (because as far as the user is concerned, a
     +    remote that has no branches yet is a new repository).
     +
     +    At the same time, when talking to an older Git server that does not
     +    report a symref for `HEAD` (but instead reports a commit hash), let's
     +    try to guess the configured default branch name first. If it does not
     +    match the reported commit hash, let's fall back to `master` as before.
      
          Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
      
       ## remote.c ##
     -@@ remote.c: static void read_remotes_file(struct remote *remote)
     - 
     - static void read_branches_file(struct remote *remote)
     - {
     --	char *frag;
     -+	char *frag, *main_branch = NULL;
     - 	struct strbuf buf = STRBUF_INIT;
     - 	FILE *f = fopen_or_warn(git_path("branches/%s", remote->name), "r");
     - 
      @@ remote.c: static void read_branches_file(struct remote *remote)
       
       	/*
     @@ remote.c: static void read_branches_file(struct remote *remote)
       		*(frag++) = '\0';
       	else
      -		frag = "master";
     -+		frag = main_branch = git_main_branch_name(MAIN_BRANCH_FOR_INIT);
     ++		frag = (char *)git_default_branch_name();
       
       	add_url_alias(remote, strbuf_detach(&buf, NULL));
       	strbuf_addf(&buf, "refs/heads/%s:refs/heads/%s",
     -@@ remote.c: static void read_branches_file(struct remote *remote)
     - 	strbuf_addf(&buf, "HEAD:refs/heads/%s", frag);
     - 	refspec_append(&remote->push, buf.buf);
     - 	remote->fetch_tags = 1; /* always auto-follow */
     -+	free(main_branch);
     - 	strbuf_release(&buf);
     - }
     - 
      @@ remote.c: struct ref *guess_remote_head(const struct ref *head,
       	if (head->symref)
       		return copy_ref(find_ref_by_name(refs, head->symref));
       
      -	/* If refs/heads/master could be right, it is. */
     -+	/* If a remote branch exists with the main branch name, let's use it. */
     ++	/* If a remote branch exists with the default branch name, let's use it. */
       	if (!all) {
     --		r = find_ref_by_name(refs, "refs/heads/master");
     -+		char *name = git_main_branch_name(MAIN_BRANCH_FULL_NAME |
     -+						  MAIN_BRANCH_FOR_INIT);
     ++		char *ref = xstrfmt("refs/heads/%s", git_default_branch_name());
     ++
     ++		r = find_ref_by_name(refs, ref);
     ++		free(ref);
     ++		if (r && oideq(&r->old_oid, &head->old_oid))
     ++			return copy_ref(r);
      +
     -+		r = find_ref_by_name(refs, name);
     -+		free(name);
     ++		/* Fall back to the hard-coded historical default */
     + 		r = find_ref_by_name(refs, "refs/heads/master");
       		if (r && oideq(&r->old_oid, &head->old_oid))
       			return copy_ref(r);
     - 	}
      
       ## t/t5606-clone-options.sh ##
     -@@ t/t5606-clone-options.sh: test_expect_success 'guesses main branch name correctly' '
     - 	git -C main-branch branch abc guess &&
     - 	git clone main-branch is-it &&
     - 	test guess = $(git -C is-it config core.mainBranch) &&
     +@@ t/t5606-clone-options.sh: test_expect_success 'guesses initial branch name correctly' '
     + 	test_commit -C initial-branch no-spoilers &&
     + 	git -C initial-branch branch abc guess &&
     + 	git clone initial-branch is-it &&
      -	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD)
      +	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD) &&
      +
      +	git -c init.defaultBranch=none init --bare no-head &&
     -+	git -C main-branch push ../no-head guess abc &&
     ++	git -C initial-branch push ../no-head guess abc &&
      +	git clone no-head is-it2 &&
      +	test_must_fail git -C is-it2 symbolic-ref refs/remotes/origin/HEAD &&
      +	git -C no-head update-ref --no-deref HEAD refs/heads/guess &&
 12:  e09f857f06 !  8:  1aa0e63785 testsvn: respect `init.defaultBranch`
     @@ Metadata
       ## Commit message ##
          testsvn: respect `init.defaultBranch`
      
     -    The default name of the main branch in new repositories can now be
     +    The default name of the initial branch in new repositories can now be
          configured. The `testsvn` remote helper translates the remote Subversion
          repository's branch name `trunk` to the hard-coded name `master`.
     -    Clearly, the intention was to make the name align with Git's detaults.
     +    Clearly, the intention was to make the name align with Git's defaults.
      
          So while we are not talking about a newly-created repository in the
     -    `testsvn` context, it _still_ makes sense to use the overridden default
     -    name for the main branch whenever users configured it.
     +    `testsvn` context, it is a newly-created _Git_ repository, si it _still_
     +    makes sense to use the overridden default name for the initial branch
     +    whenever users configured it.
      
          Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
      
     @@ remote-testsvn.c: int cmd_main(int argc, const char **argv)
       		return 1;
       	}
       
     -+	remote_ref = git_main_branch_name(MAIN_BRANCH_FULL_NAME |
     -+					  MAIN_BRANCH_FOR_INIT);
     -+	if (!skip_prefix(remote_ref, "refs/heads/", &remote_ref_short))
     -+		BUG("unexpected remote_ref '%s'", remote_ref);
     ++	remote_ref_short = git_default_branch_name();
     ++	remote_ref = xstrfmt("refs/heads/%s", remote_ref_short);
      +
       	remote = remote_get(argv[1]);
       	url_in = (argc == 3) ? argv[2] : remote->url[0];
     @@ t/t9020-remote-svn.sh: test_expect_success REMOTE_SVN 'incremental imports must
       	test_cmp master.good .git/refs/remotes/svnsim/master
       '
       
     -+test_expect_success REMOTE_SVN 'respects configured default main branch' '
     ++test_expect_success REMOTE_SVN 'respects configured default initial branch' '
      +	git -c init.defaultBranch=trunk remote add -f trunk \
      +		"testsvn::file://$TEST_DIRECTORY/t9154/svn.dump" &&
      +	git rev-parse --verify refs/remotes/trunk/trunk
-- 
gitgitgadget
Johannes Schindelin via GitGitGadget· Jun 23, 2020, 22:33 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v3 2/8] send-pack/transport-helper: avoid mentioning a particular branch

From: Johannes Schindelin <johannes.schindelin@gmx.de>

When trying to push all matching branches, but none match, we offer a message suggesting to push the `master` branch.

However, we want to step away from making that branch any more special than any other branch, so let's reword that message to mention no branch in particular.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 send-pack.c             | 2 +-
 t/t5528-push-default.sh | 6 ++++++
 transport-helper.c      | 2 +-
 3 files changed, 8 insertions(+), 2 deletions(-)
Show changes to 3 files +8 −2

send-pack.c, t/t5528-push-default.sh, transport-helper.c

diff --git a/send-pack.c b/send-pack.c
index 0abee22283..db79cdac77 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -406,7 +406,7 @@ int send_pack(struct send_pack_args *args,
 
 	if (!remote_refs) {
 		fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
-			"Perhaps you should specify a branch such as 'master'.\n");
+			"Perhaps you should specify a specific branch.\n");
 		return 0;
 	}
 	if (args->atomic && !atomic_supported)
diff --git a/t/t5528-push-default.sh b/t/t5528-push-default.sh
index 4d1e0c363e..68b84c4add 100755
--- a/t/t5528-push-default.sh
+++ b/t/t5528-push-default.sh
@@ -98,6 +98,12 @@ test_expect_success 'push from/to new branch with upstream, matching and simple'
 	test_push_failure upstream
 '
 
+test_expect_success '"matching" fails if none match' '
+	git init --bare empty &&
+	test_must_fail git push empty : 2>actual &&
+	test_i18ngrep "Perhaps you should specify a specific branch" actual
+'
+
 test_expect_success 'push ambiguously named branch with upstream, matching and simple' '
 	git checkout -b ambiguous &&
 	test_config branch.ambiguous.remote parent1 &&
diff --git a/transport-helper.c b/transport-helper.c
index a46afcb69d..b81a3486bd 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -1046,7 +1046,7 @@ static int push_refs(struct transport *transport,
 	if (!remote_refs) {
 		fprintf(stderr,
 			_("No refs in common and none specified; doing nothing.\n"
-			  "Perhaps you should specify a branch such as 'master'.\n"));
+			  "Perhaps you should specify a specific branch.\n"));
 		return 0;
 	}
 
-- 
gitgitgadget
Junio C Hamano· Jun 24, 2020, 00:36 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH v3 2/8] send-pack/transport-helper: avoid mentioning a particular branch

"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com> writes:

Show 6 quoted lines
> @@ -1046,7 +1046,7 @@ static int push_refs(struct transport *transport,
>  	if (!remote_refs) {
>  		fprintf(stderr,
>  			_("No refs in common and none specified; doing nothing.\n"
> -			  "Perhaps you should specify a branch such as 'master'.\n"));
> +			  "Perhaps you should specify a specific branch.\n"));

Hmph, not just "specify a branch."? Maybe it is just me, but "specify a specific branch" did not roll well on my tongue.

Johannes Schindelin· Jun 24, 2020, 12:44 UTC · re: Junio C Hamano · lore

Re: [PATCH v3 2/8] send-pack/transport-helper: avoid mentioning a particular branch

Hi Junio,
On Tue, 23 Jun 2020, Junio C Hamano wrote:
Show 12 quoted lines
> "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
> writes:
>
> > @@ -1046,7 +1046,7 @@ static int push_refs(struct transport *transport,
> >  	if (!remote_refs) {
> >  		fprintf(stderr,
> >  			_("No refs in common and none specified; doing nothing.\n"
> > -			  "Perhaps you should specify a branch such as 'master'.\n"));
> > +			  "Perhaps you should specify a specific branch.\n"));
>
> Hmph, not just "specify a branch."?  Maybe it is just me, but
> "specify a specific branch" did not roll well on my tongue.

Oh well. "Perhaps you should specify a branch" sounded too judgmental to me, but I'm not a native speaker, so I simply removed the word "specific".

Ciao, Dscho

Junio C Hamano· Jun 24, 2020, 15:44 UTC · re: Johannes Schindelin · lore

Re: [PATCH v3 2/8] send-pack/transport-helper: avoid mentioning a particular branch

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
Show 19 quoted lines
> Hi Junio,
>
> On Tue, 23 Jun 2020, Junio C Hamano wrote:
>
>> "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
>> writes:
>>
>> > @@ -1046,7 +1046,7 @@ static int push_refs(struct transport *transport,
>> >  	if (!remote_refs) {
>> >  		fprintf(stderr,
>> >  			_("No refs in common and none specified; doing nothing.\n"
>> > -			  "Perhaps you should specify a branch such as 'master'.\n"));
>> > +			  "Perhaps you should specify a specific branch.\n"));
>>
>> Hmph, not just "specify a branch."?  Maybe it is just me, but
>> "specify a specific branch" did not roll well on my tongue.
>
> Oh well. "Perhaps you should specify a branch" sounded too judgmental to
> me, but I'm not a native speaker, so I simply removed the word "specific".

I'm not either. Note that when I say "maybe it is just me", I usually am not asking to change anything.

Johannes Schindelin· Jun 25, 2020, 13:05 UTC · re: Junio C Hamano · lore

Re: [PATCH v3 2/8] send-pack/transport-helper: avoid mentioning a particular branch

Hi Junio,
On Wed, 24 Jun 2020, Junio C Hamano wrote:
Show 21 quoted lines
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > On Tue, 23 Jun 2020, Junio C Hamano wrote:
> >
> >> "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
> >> writes:
> >>
> >> > @@ -1046,7 +1046,7 @@ static int push_refs(struct transport *transport,
> >> >  	if (!remote_refs) {
> >> >  		fprintf(stderr,
> >> >  			_("No refs in common and none specified; doing nothing.\n"
> >> > -			  "Perhaps you should specify a branch such as 'master'.\n"));
> >> > +			  "Perhaps you should specify a specific branch.\n"));
> >>
> >> Hmph, not just "specify a branch."?  Maybe it is just me, but
> >> "specify a specific branch" did not roll well on my tongue.
> >
> > Oh well. "Perhaps you should specify a branch" sounded too judgmental to
> > me, but I'm not a native speaker, so I simply removed the word "specific".
>
> I'm not either.
We should start a society or something ;-)
> Note that when I say "maybe it is just me", I usually am not asking to
> change anything.

Of course! In this instance, your suggestion made me think and prefer the non-repetitive version (because let's face it, taking out that word did not make it any more or less judgemental).

Ciao, Dscho

Johannes Schindelin via GitGitGadget· Jun 23, 2020, 22:33 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v3 1/8] fmt-merge-msg: stop treating `master` specially

From: Johannes Schindelin <johannes.schindelin@gmx.de>

In the context of many projects renaming their primary branch names away from `master`, Git wants to stop treating the `master` branch specially.

Let's start with `git fmt-merge-msg`.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 fmt-merge-msg.c                               |  5 +-
 t/t1507-rev-parse-upstream.sh                 |  2 +-
 t/t4013-diff-various.sh                       |  4 +-
 t/t4013/diff.log_--decorate=full_--all        |  2 +-
 t/t4013/diff.log_--decorate_--all             |  2 +-
 ...--patch-with-stat_--summary_master_--_dir_ |  2 +-
 t/t4013/diff.log_--patch-with-stat_master     |  2 +-
 .../diff.log_--patch-with-stat_master_--_dir_ |  2 +-
 ...ot_--cc_--patch-with-stat_--summary_master |  2 +-
 ..._--root_--patch-with-stat_--summary_master |  2 +-
 .../diff.log_--root_--patch-with-stat_master  |  2 +-
 ...root_-c_--patch-with-stat_--summary_master |  2 +-
 t/t4013/diff.log_--root_-p_master             |  2 +-
 t/t4013/diff.log_--root_master                |  2 +-
 t/t4013/diff.log_-m_-p_--first-parent_master  |  2 +-
 t/t4013/diff.log_-m_-p_master                 |  4 +-
 t/t4013/diff.log_-p_--first-parent_master     |  2 +-
 t/t4013/diff.log_-p_master                    |  2 +-
 t/t4013/diff.log_master                       |  2 +-
 t/t4013/diff.show_--first-parent_master       |  2 +-
 t/t4013/diff.show_-c_master                   |  2 +-
 t/t4013/diff.show_-m_master                   |  4 +-
 t/t4013/diff.show_master                      |  2 +-
 ...ot_--cc_--patch-with-stat_--summary_master |  2 +-
 ...root_-c_--patch-with-stat_--summary_master |  2 +-
 t/t4202-log.sh                                | 72 +++++++++----------
 t/t6200-fmt-merge-msg.sh                      | 36 +++++-----
 t/t7600-merge.sh                              | 14 ++--
 t/t7608-merge-messages.sh                     | 10 +--
 29 files changed, 94 insertions(+), 97 deletions(-)
Show changes to 29 files +94 −97

fmt-merge-msg.c, t/t1507-rev-parse-upstream.sh, t/t4013-diff-various.sh, t/t4013/diff.log_--decorate=full_--all, t/t4013/diff.log_--decorate_--all, t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_, t/t4013/diff.log_--patch-with-stat_master, t/t4013/diff.log_--patch-with-stat_master_--_dir_, t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master, t/t4013/diff.log_--root_--patch-with-stat_--summary_master, t/t4013/diff.log_--root_--patch-with-stat_master, t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master, t/t4013/diff.log_--root_-p_master, t/t4013/diff.log_--root_master, t/t4013/diff.log_-m_-p_--first-parent_master, t/t4013/diff.log_-m_-p_master, t/t4013/diff.log_-p_--first-parent_master, t/t4013/diff.log_-p_master, t/t4013/diff.log_master, t/t4013/diff.show_--first-parent_master, t/t4013/diff.show_-c_master, t/t4013/diff.show_-m_master, t/t4013/diff.show_master, t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master, t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master, t/t4202-log.sh, t/t6200-fmt-merge-msg.sh, t/t7600-merge.sh, t/t7608-merge-messages.sh

diff --git a/fmt-merge-msg.c b/fmt-merge-msg.c
index 72d32bd73b..cfb8ff2f33 100644
--- a/fmt-merge-msg.c
+++ b/fmt-merge-msg.c
@@ -451,10 +451,7 @@ static void fmt_merge_msg_title(struct strbuf *out,
 			strbuf_addf(out, " of %s", srcs.items[i].string);
 	}
 
-	if (!strcmp("master", current_branch))
-		strbuf_addch(out, '\n');
-	else
-		strbuf_addf(out, " into %s\n", current_branch);
+	strbuf_addf(out, " into %s\n", current_branch);
 }
 
 static void fmt_tag_signature(struct strbuf *tagbuf,
diff --git a/t/t1507-rev-parse-upstream.sh b/t/t1507-rev-parse-upstream.sh
index dfc0d96d8a..f213aa8053 100755
--- a/t/t1507-rev-parse-upstream.sh
+++ b/t/t1507-rev-parse-upstream.sh
@@ -137,7 +137,7 @@ test_expect_success 'merge my-side@{u} records the correct name' '
 	git branch -t new my-side@{u} &&
 	git merge -s ours new@{u} &&
 	git show -s --pretty=tformat:%s >actual &&
-	echo "Merge remote-tracking branch ${SQ}origin/side${SQ}" >expect &&
+	echo "Merge remote-tracking branch ${SQ}origin/side${SQ} into master" >expect &&
 	test_cmp expect actual
 )
 '
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index 3f60f7d96c..43267d6024 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -117,12 +117,12 @@ test_expect_success setup '
 
 : <<\EOF
 ! [initial] Initial
- * [master] Merge branch 'side'
+ * [master] Merge branch 'side' into master
   ! [rearrange] Rearranged lines in dir/sub
    ! [side] Side
 ----
   +  [rearrange] Rearranged lines in dir/sub
- -   [master] Merge branch 'side'
+ -   [master] Merge branch 'side' into master
  * + [side] Side
  *   [master^] Third
  *   [master~2] Second
diff --git a/t/t4013/diff.log_--decorate=full_--all b/t/t4013/diff.log_--decorate=full_--all
index 3f9b872ece..c56783b985 100644
--- a/t/t4013/diff.log_--decorate=full_--all
+++ b/t/t4013/diff.log_--decorate=full_--all
@@ -31,7 +31,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (refs/heads/side)
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--decorate_--all b/t/t4013/diff.log_--decorate_--all
index f5e20e1e14..1cbdc038f4 100644
--- a/t/t4013/diff.log_--decorate_--all
+++ b/t/t4013/diff.log_--decorate_--all
@@ -31,7 +31,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (side)
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_
index a18f1472a9..f5b1b6516b 100644
--- a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_
+++ b/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--patch-with-stat_master b/t/t4013/diff.log_--patch-with-stat_master
index ae425c4672..af23803cdc 100644
--- a/t/t4013/diff.log_--patch-with-stat_master
+++ b/t/t4013/diff.log_--patch-with-stat_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--patch-with-stat_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_master_--_dir_
index d5207cadf4..814098fbf8 100644
--- a/t/t4013/diff.log_--patch-with-stat_master_--_dir_
+++ b/t/t4013/diff.log_--patch-with-stat_master_--_dir_
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master
index 0fc1e8cd71..b927fe4a98 100644
--- a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
  dir/sub | 2 ++
  file0   | 3 +++
diff --git a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_--patch-with-stat_--summary_master
index dffc09dde9..6db3cea329 100644
--- a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.log_--root_--patch-with-stat_--summary_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--root_--patch-with-stat_master b/t/t4013/diff.log_--root_--patch-with-stat_master
index 55aa98012d..98e9c320c3 100644
--- a/t/t4013/diff.log_--root_--patch-with-stat_master
+++ b/t/t4013/diff.log_--root_--patch-with-stat_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master
index 019d85f7de..b61b1117ae 100644
--- a/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
  dir/sub | 2 ++
  file0   | 3 +++
diff --git a/t/t4013/diff.log_--root_-p_master b/t/t4013/diff.log_--root_-p_master
index b42c334439..345bd9e8a9 100644
--- a/t/t4013/diff.log_--root_-p_master
+++ b/t/t4013/diff.log_--root_-p_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--root_master b/t/t4013/diff.log_--root_master
index e8f46159da..db56b1fe6b 100644
--- a/t/t4013/diff.log_--root_master
+++ b/t/t4013/diff.log_--root_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-m_-p_--first-parent_master b/t/t4013/diff.log_-m_-p_--first-parent_master
index 7a0073f529..bcadb50e26 100644
--- a/t/t4013/diff.log_-m_-p_--first-parent_master
+++ b/t/t4013/diff.log_-m_-p_--first-parent_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 diff --git a/dir/sub b/dir/sub
 index cead32e..992913c 100644
diff --git a/t/t4013/diff.log_-m_-p_master b/t/t4013/diff.log_-m_-p_master
index 9ca62a01ed..2acf43a9fb 100644
--- a/t/t4013/diff.log_-m_-p_master
+++ b/t/t4013/diff.log_-m_-p_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 diff --git a/dir/sub b/dir/sub
 index cead32e..992913c 100644
@@ -33,7 +33,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 diff --git a/dir/sub b/dir/sub
 index 7289e35..992913c 100644
diff --git a/t/t4013/diff.log_-p_--first-parent_master b/t/t4013/diff.log_-p_--first-parent_master
index 3fc896d424..c6a5876d80 100644
--- a/t/t4013/diff.log_-p_--first-parent_master
+++ b/t/t4013/diff.log_-p_--first-parent_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-p_master b/t/t4013/diff.log_-p_master
index bf1326dc36..1841cded94 100644
--- a/t/t4013/diff.log_-p_master
+++ b/t/t4013/diff.log_-p_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_master b/t/t4013/diff.log_master
index a8f6ce5abd..f8ec445eb3 100644
--- a/t/t4013/diff.log_master
+++ b/t/t4013/diff.log_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.show_--first-parent_master b/t/t4013/diff.show_--first-parent_master
index 3dcbe473a0..94548f4598 100644
--- a/t/t4013/diff.show_--first-parent_master
+++ b/t/t4013/diff.show_--first-parent_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 diff --git a/dir/sub b/dir/sub
 index cead32e..992913c 100644
diff --git a/t/t4013/diff.show_-c_master b/t/t4013/diff.show_-c_master
index 81aba8da96..1c46ed64fd 100644
--- a/t/t4013/diff.show_-c_master
+++ b/t/t4013/diff.show_-c_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 diff --combined dir/sub
 index cead32e,7289e35..992913c
diff --git a/t/t4013/diff.show_-m_master b/t/t4013/diff.show_-m_master
index 4ea2ee453d..7559fc22f8 100644
--- a/t/t4013/diff.show_-m_master
+++ b/t/t4013/diff.show_-m_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 diff --git a/dir/sub b/dir/sub
 index cead32e..992913c 100644
@@ -33,7 +33,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 diff --git a/dir/sub b/dir/sub
 index 7289e35..992913c 100644
diff --git a/t/t4013/diff.show_master b/t/t4013/diff.show_master
index fb08ce0e46..57091c5d90 100644
--- a/t/t4013/diff.show_master
+++ b/t/t4013/diff.show_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 diff --cc dir/sub
 index cead32e,7289e35..992913c
diff --git a/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master
index 30aae7817b..5f13a71bb5 100644
--- a/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
  dir/sub | 2 ++
  file0   | 3 +++
diff --git a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master
index d1d32bd34c..8acb88267b 100644
--- a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
  dir/sub | 2 ++
  file0   | 3 +++
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index a0930599aa..fd9af658af 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -483,7 +483,7 @@ test_expect_success 'set up merge history' '
 '
 
 cat > expect <<\EOF
-*   Merge branch 'side'
+*   Merge branch 'side' into master
 |\
 | * side-2
 | * side-1
@@ -502,7 +502,7 @@ test_expect_success 'log --graph with merge' '
 '
 
 cat > expect <<\EOF
-| | | *   Merge branch 'side'
+| | | *   Merge branch 'side' into master
 | | | |\
 | | | | * side-2
 | | | | * side-1
@@ -521,7 +521,7 @@ test_expect_success 'log --graph --line-prefix="| | | " with merge' '
 '
 
 cat > expect.colors <<\EOF
-*   Merge branch 'side'
+*   Merge branch 'side' into master
 <BLUE>|<RESET><CYAN>\<RESET>
 <BLUE>|<RESET> * side-2
 <BLUE>|<RESET> * side-1
@@ -555,7 +555,7 @@ cat > expect <<\EOF
 |\  Merge: A B
 | | Author: A U Thor <author@example.com>
 | |
-| |     Merge branch 'side'
+| |     Merge branch 'side' into master
 | |
 | * commit tags/side-2
 | | Author: A U Thor <author@example.com>
@@ -632,11 +632,11 @@ test_expect_success 'set up more tangled history' '
 '
 
 cat > expect <<\EOF
-*   Merge tag 'reach'
+*   Merge tag 'reach' into master
 |\
 | \
 |  \
-*-. \   Merge tags 'octopus-a' and 'octopus-b'
+*-. \   Merge tags 'octopus-a' and 'octopus-b' into master
 |\ \ \
 * | | | seventh
 | | * | octopus-b
@@ -646,14 +646,14 @@ cat > expect <<\EOF
 |/ /
 | * reach
 |/
-*   Merge branch 'tangle'
+*   Merge branch 'tangle' into master
 |\
 | *   Merge branch 'side' (early part) into tangle
 | |\
 | * \   Merge branch 'master' (early part) into tangle
 | |\ \
 | * | | tangle-a
-* | | |   Merge branch 'side'
+* | | |   Merge branch 'side' into master
 |\ \ \ \
 | * | | | side-2
 | | |_|/
@@ -735,16 +735,16 @@ test_expect_success 'log.decorate configuration' '
 
 test_expect_success 'decorate-refs with glob' '
 	cat >expect.decorate <<-\EOF &&
-	Merge-tag-reach
-	Merge-tags-octopus-a-and-octopus-b
+	Merge-tag-reach-into-master
+	Merge-tags-octopus-a-and-octopus-b-into-master
 	seventh
 	octopus-b (octopus-b)
 	octopus-a (octopus-a)
 	reach
 	EOF
 	cat >expect.no-decorate <<-\EOF &&
-	Merge-tag-reach
-	Merge-tags-octopus-a-and-octopus-b
+	Merge-tag-reach-into-master
+	Merge-tags-octopus-a-and-octopus-b-into-master
 	seventh
 	octopus-b
 	octopus-a
@@ -765,8 +765,8 @@ test_expect_success 'decorate-refs with glob' '
 
 test_expect_success 'decorate-refs without globs' '
 	cat >expect.decorate <<-\EOF &&
-	Merge-tag-reach
-	Merge-tags-octopus-a-and-octopus-b
+	Merge-tag-reach-into-master
+	Merge-tags-octopus-a-and-octopus-b-into-master
 	seventh
 	octopus-b
 	octopus-a
@@ -779,8 +779,8 @@ test_expect_success 'decorate-refs without globs' '
 
 test_expect_success 'multiple decorate-refs' '
 	cat >expect.decorate <<-\EOF &&
-	Merge-tag-reach
-	Merge-tags-octopus-a-and-octopus-b
+	Merge-tag-reach-into-master
+	Merge-tags-octopus-a-and-octopus-b-into-master
 	seventh
 	octopus-b (octopus-b)
 	octopus-a (octopus-a)
@@ -794,8 +794,8 @@ test_expect_success 'multiple decorate-refs' '
 
 test_expect_success 'decorate-refs-exclude with glob' '
 	cat >expect.decorate <<-\EOF &&
-	Merge-tag-reach (HEAD -> master)
-	Merge-tags-octopus-a-and-octopus-b
+	Merge-tag-reach-into-master (HEAD -> master)
+	Merge-tags-octopus-a-and-octopus-b-into-master
 	seventh (tag: seventh)
 	octopus-b (tag: octopus-b)
 	octopus-a (tag: octopus-a)
@@ -811,8 +811,8 @@ test_expect_success 'decorate-refs-exclude with glob' '
 
 test_expect_success 'decorate-refs-exclude without globs' '
 	cat >expect.decorate <<-\EOF &&
-	Merge-tag-reach (HEAD -> master)
-	Merge-tags-octopus-a-and-octopus-b
+	Merge-tag-reach-into-master (HEAD -> master)
+	Merge-tags-octopus-a-and-octopus-b-into-master
 	seventh (tag: seventh)
 	octopus-b (tag: octopus-b, octopus-b)
 	octopus-a (tag: octopus-a, octopus-a)
@@ -828,8 +828,8 @@ test_expect_success 'decorate-refs-exclude without globs' '
 
 test_expect_success 'multiple decorate-refs-exclude' '
 	cat >expect.decorate <<-\EOF &&
-	Merge-tag-reach (HEAD -> master)
-	Merge-tags-octopus-a-and-octopus-b
+	Merge-tag-reach-into-master (HEAD -> master)
+	Merge-tags-octopus-a-and-octopus-b-into-master
 	seventh (tag: seventh)
 	octopus-b (tag: octopus-b)
 	octopus-a (tag: octopus-a)
@@ -851,8 +851,8 @@ test_expect_success 'multiple decorate-refs-exclude' '
 
 test_expect_success 'decorate-refs and decorate-refs-exclude' '
 	cat >expect.no-decorate <<-\EOF &&
-	Merge-tag-reach (master)
-	Merge-tags-octopus-a-and-octopus-b
+	Merge-tag-reach-into-master (master)
+	Merge-tags-octopus-a-and-octopus-b-into-master
 	seventh
 	octopus-b
 	octopus-a
@@ -866,8 +866,8 @@ test_expect_success 'decorate-refs and decorate-refs-exclude' '
 
 test_expect_success 'deocrate-refs and log.excludeDecoration' '
 	cat >expect.decorate <<-\EOF &&
-	Merge-tag-reach (master)
-	Merge-tags-octopus-a-and-octopus-b
+	Merge-tag-reach-into-master (master)
+	Merge-tags-octopus-a-and-octopus-b-into-master
 	seventh
 	octopus-b (octopus-b)
 	octopus-a (octopus-a)
@@ -881,10 +881,10 @@ test_expect_success 'deocrate-refs and log.excludeDecoration' '
 
 test_expect_success 'decorate-refs-exclude and simplify-by-decoration' '
 	cat >expect.decorate <<-\EOF &&
-	Merge-tag-reach (HEAD -> master)
+	Merge-tag-reach-into-master (HEAD -> master)
 	reach (tag: reach, reach)
 	seventh (tag: seventh)
-	Merge-branch-tangle
+	Merge-branch-tangle-into-master
 	Merge-branch-side-early-part-into-tangle (tangle)
 	tangle-a (tag: tangle-a)
 	EOF
@@ -1068,7 +1068,7 @@ cat >expect <<\EOF
 |\  Merge: MERGE_PARENTS
 | | Author: A U Thor <author@example.com>
 | |
-| |     Merge branch 'tangle'
+| |     Merge branch 'tangle' into master
 | |
 | *   commit COMMIT_OBJECT_NAME
 | |\  Merge: MERGE_PARENTS
@@ -1102,7 +1102,7 @@ cat >expect <<\EOF
 |\ \ \ \  Merge: MERGE_PARENTS
 | | | | | Author: A U Thor <author@example.com>
 | | | | |
-| | | | |     Merge branch 'side'
+| | | | |     Merge branch 'side' into master
 | | | | |
 | * | | | commit COMMIT_OBJECT_NAME
 | | |_|/  Author: A U Thor <author@example.com>
@@ -1343,7 +1343,7 @@ cat >expect <<\EOF
 *** |\  Merge: MERGE_PARENTS
 *** | | Author: A U Thor <author@example.com>
 *** | |
-*** | |     Merge branch 'tangle'
+*** | |     Merge branch 'tangle' into master
 *** | |
 *** | *   commit COMMIT_OBJECT_NAME
 *** | |\  Merge: MERGE_PARENTS
@@ -1377,7 +1377,7 @@ cat >expect <<\EOF
 *** |\ \ \ \  Merge: MERGE_PARENTS
 *** | | | | | Author: A U Thor <author@example.com>
 *** | | | | |
-*** | | | | |     Merge branch 'side'
+*** | | | | |     Merge branch 'side' into master
 *** | | | | |
 *** | * | | | commit COMMIT_OBJECT_NAME
 *** | | |_|/  Author: A U Thor <author@example.com>
@@ -1540,8 +1540,8 @@ cat >expect <<-\EOF
 * reach
 |
 | A	reach.t
-* Merge branch 'tangle'
-*   Merge branch 'side'
+* Merge branch 'tangle' into master
+*   Merge branch 'side' into master
 |\
 | * side-2
 |
@@ -1562,8 +1562,8 @@ cat >expect <<-\EOF
 * reach
 |
 | reach.t
-* Merge branch 'tangle'
-*   Merge branch 'side'
+* Merge branch 'tangle' into master
+*   Merge branch 'side' into master
 |\
 | * side-2
 |
diff --git a/t/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh
index e4c2a6eca4..2b3fd498d0 100755
--- a/t/t6200-fmt-merge-msg.sh
+++ b/t/t6200-fmt-merge-msg.sh
@@ -79,7 +79,7 @@ test_expect_success GPG 'set up a signed tag' '
 '
 
 test_expect_success 'message for merging local branch' '
-	echo "Merge branch ${apos}left${apos}" >expected &&
+	echo "Merge branch ${apos}left${apos} into master" >expected &&
 
 	git checkout master &&
 	git fetch . left &&
@@ -107,7 +107,7 @@ test_expect_success GPG 'message for merging local tag signed by unknown key' '
 '
 
 test_expect_success 'message for merging external branch' '
-	echo "Merge branch ${apos}left${apos} of $(pwd)" >expected &&
+	echo "Merge branch ${apos}left${apos} of $(pwd) into master" >expected &&
 
 	git checkout master &&
 	git fetch "$(pwd)" left &&
@@ -118,7 +118,7 @@ test_expect_success 'message for merging external branch' '
 
 test_expect_success '[merge] summary/log configuration' '
 	cat >expected <<-EOF &&
-	Merge branch ${apos}left${apos}
+	Merge branch ${apos}left${apos} into master
 
 	# By Another Author (3) and A U Thor (2)
 	# Via Another Committer
@@ -160,7 +160,7 @@ test_expect_success 'setup FETCH_HEAD' '
 
 test_expect_success 'merge.log=3 limits shortlog length' '
 	cat >expected <<-EOF &&
-	Merge branch ${apos}left${apos}
+	Merge branch ${apos}left${apos} into master
 
 	# By Another Author (3) and A U Thor (2)
 	# Via Another Committer
@@ -177,7 +177,7 @@ test_expect_success 'merge.log=3 limits shortlog length' '
 
 test_expect_success 'merge.log=5 shows all 5 commits' '
 	cat >expected <<-EOF &&
-	Merge branch ${apos}left${apos}
+	Merge branch ${apos}left${apos} into master
 
 	# By Another Author (3) and A U Thor (2)
 	# Via Another Committer
@@ -195,7 +195,7 @@ test_expect_success 'merge.log=5 shows all 5 commits' '
 
 test_expect_success '--log=5 with custom comment character' '
 	cat >expected <<-EOF &&
-	Merge branch ${apos}left${apos}
+	Merge branch ${apos}left${apos} into master
 
 	x By Another Author (3) and A U Thor (2)
 	x Via Another Committer
@@ -212,14 +212,14 @@ test_expect_success '--log=5 with custom comment character' '
 '
 
 test_expect_success 'merge.log=0 disables shortlog' '
-	echo "Merge branch ${apos}left${apos}" >expected &&
+	echo "Merge branch ${apos}left${apos} into master" >expected &&
 	git -c merge.log=0 fmt-merge-msg <.git/FETCH_HEAD >actual &&
 	test_cmp expected actual
 '
 
 test_expect_success '--log=3 limits shortlog length' '
 	cat >expected <<-EOF &&
-	Merge branch ${apos}left${apos}
+	Merge branch ${apos}left${apos} into master
 
 	# By Another Author (3) and A U Thor (2)
 	# Via Another Committer
@@ -236,7 +236,7 @@ test_expect_success '--log=3 limits shortlog length' '
 
 test_expect_success '--log=5 shows all 5 commits' '
 	cat >expected <<-EOF &&
-	Merge branch ${apos}left${apos}
+	Merge branch ${apos}left${apos} into master
 
 	# By Another Author (3) and A U Thor (2)
 	# Via Another Committer
@@ -253,13 +253,13 @@ test_expect_success '--log=5 shows all 5 commits' '
 '
 
 test_expect_success '--no-log disables shortlog' '
-	echo "Merge branch ${apos}left${apos}" >expected &&
+	echo "Merge branch ${apos}left${apos} into master" >expected &&
 	git fmt-merge-msg --no-log <.git/FETCH_HEAD >actual &&
 	test_cmp expected actual
 '
 
 test_expect_success '--log=0 disables shortlog' '
-	echo "Merge branch ${apos}left${apos}" >expected &&
+	echo "Merge branch ${apos}left${apos} into master" >expected &&
 	git fmt-merge-msg --no-log <.git/FETCH_HEAD >actual &&
 	test_cmp expected actual
 '
@@ -300,7 +300,7 @@ test_expect_success 'fmt-merge-msg -m' '
 
 test_expect_success 'setup: expected shortlog for two branches' '
 	cat >expected <<-EOF
-	Merge branches ${apos}left${apos} and ${apos}right${apos}
+	Merge branches ${apos}left${apos} and ${apos}right${apos} into master
 
 	# By Another Author (3) and A U Thor (2)
 	# Via Another Committer
@@ -397,7 +397,7 @@ test_expect_success 'merge-msg with nothing to merge' '
 
 test_expect_success 'merge-msg tag' '
 	cat >expected <<-EOF &&
-	Merge tag ${apos}tag-r3${apos}
+	Merge tag ${apos}tag-r3${apos} into master
 
 	* tag ${apos}tag-r3${apos}:
 	  Right #3
@@ -418,7 +418,7 @@ test_expect_success 'merge-msg tag' '
 
 test_expect_success 'merge-msg two tags' '
 	cat >expected <<-EOF &&
-	Merge tags ${apos}tag-r3${apos} and ${apos}tag-l5${apos}
+	Merge tags ${apos}tag-r3${apos} and ${apos}tag-l5${apos} into master
 
 	* tag ${apos}tag-r3${apos}:
 	  Right #3
@@ -448,7 +448,7 @@ test_expect_success 'merge-msg two tags' '
 
 test_expect_success 'merge-msg tag and branch' '
 	cat >expected <<-EOF &&
-	Merge branch ${apos}left${apos}, tag ${apos}tag-r3${apos}
+	Merge branch ${apos}left${apos}, tag ${apos}tag-r3${apos} into master
 
 	* tag ${apos}tag-r3${apos}:
 	  Right #3
@@ -479,7 +479,7 @@ test_expect_success 'merge-msg tag and branch' '
 test_expect_success 'merge-msg lots of commits' '
 	{
 		cat <<-EOF &&
-		Merge branch ${apos}long${apos}
+		Merge branch ${apos}long${apos} into master
 
 		* long: (35 commits)
 		EOF
@@ -516,7 +516,7 @@ test_expect_success 'merge-msg with "merging" an annotated tag' '
 	git fmt-merge-msg <.git/FETCH_HEAD >actual &&
 	{
 		cat <<-\EOF
-		Merge tag '\''annote'\''
+		Merge tag '\''annote'\'' into master
 
 		An annotated one
 
@@ -531,7 +531,7 @@ test_expect_success 'merge-msg with "merging" an annotated tag' '
 	git merge --no-commit --no-ff $annote &&
 	{
 		cat <<-EOF
-		Merge tag '\''$annote'\''
+		Merge tag '\''$annote'\'' into master
 
 		An annotated one
 
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 5883a6adc3..1d45f9a4ed 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -14,9 +14,9 @@ Testing basic merge operations/option parsing.
     ! [c4] c4
      ! [c5] c5
       ! [c6] c6
-       * [master] Merge commit 'c1'
+       * [master] Merge commit 'c1' into master
 --------
-       - [master] Merge commit 'c1'
+       - [master] Merge commit 'c1' into master
  +     * [c1] commit 1
       +  [c6] c6
      +   [c5] c5
@@ -44,8 +44,8 @@ test_write_lines '1 X' 2 '3 X' 4 '5 X' 6 7 8 '9 X' >result.1-3-5-9
 test_write_lines 1 2 3 4 5 6 7 8 '9 Z' >result.9z
 
 create_merge_msgs () {
-	echo "Merge tag 'c2'" >msg.1-5 &&
-	echo "Merge tags 'c2' and 'c3'" >msg.1-5-9 &&
+	echo "Merge tag 'c2' into master" >msg.1-5 &&
+	echo "Merge tags 'c2' and 'c3' into master" >msg.1-5-9 &&
 	{
 		echo "Squashed commit of the following:" &&
 		echo &&
@@ -258,7 +258,7 @@ test_expect_success 'merge c3 with c7 with commit.cleanup = scissors' '
 	git commit --no-edit -a &&
 
 	cat >expect <<-\EOF &&
-	Merge tag '"'"'c7'"'"'
+	Merge tag '"'"'c7'"'"' into master
 
 	# ------------------------ >8 ------------------------
 	# Do not modify or remove the line above.
@@ -808,10 +808,10 @@ test_expect_success 'merge with conflicted --autostash changes' '
 '
 
 cat >expected.branch <<\EOF
-Merge branch 'c5-branch' (early part)
+Merge branch 'c5-branch' (early part) into master
 EOF
 cat >expected.tag <<\EOF
-Merge commit 'c5~1'
+Merge commit 'c5~1' into master
 EOF
 
 test_expect_success 'merge early part of c2' '
diff --git a/t/t7608-merge-messages.sh b/t/t7608-merge-messages.sh
index 8e7e0a5865..2af33f195b 100755
--- a/t/t7608-merge-messages.sh
+++ b/t/t7608-merge-messages.sh
@@ -16,7 +16,7 @@ test_expect_success 'merge local branch' '
 	git checkout master &&
 	test_commit master-2 &&
 	git merge local-branch &&
-	check_oneline "Merge branch Qlocal-branchQ"
+	check_oneline "Merge branch Qlocal-branchQ into master"
 '
 
 test_expect_success 'merge octopus branches' '
@@ -26,7 +26,7 @@ test_expect_success 'merge octopus branches' '
 	test_commit octopus-2 &&
 	git checkout master &&
 	git merge octopus-a octopus-b &&
-	check_oneline "Merge branches Qoctopus-aQ and Qoctopus-bQ"
+	check_oneline "Merge branches Qoctopus-aQ and Qoctopus-bQ into master"
 '
 
 test_expect_success 'merge tag' '
@@ -35,7 +35,7 @@ test_expect_success 'merge tag' '
 	git checkout master &&
 	test_commit master-3 &&
 	git merge tag-1 &&
-	check_oneline "Merge tag Qtag-1Q"
+	check_oneline "Merge tag Qtag-1Q into master"
 '
 
 test_expect_success 'ambiguous tag' '
@@ -44,7 +44,7 @@ test_expect_success 'ambiguous tag' '
 	git checkout master &&
 	test_commit master-4 &&
 	git merge ambiguous &&
-	check_oneline "Merge tag QambiguousQ"
+	check_oneline "Merge tag QambiguousQ into master"
 '
 
 test_expect_success 'remote-tracking branch' '
@@ -54,7 +54,7 @@ test_expect_success 'remote-tracking branch' '
 	git checkout master &&
 	test_commit master-5 &&
 	git merge origin/master &&
-	check_oneline "Merge remote-tracking branch Qorigin/masterQ"
+	check_oneline "Merge remote-tracking branch Qorigin/masterQ into master"
 '
 
 test_done
-- 
gitgitgadget
Junio C Hamano· Jun 24, 2020, 16:16 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH v3 1/8] fmt-merge-msg: stop treating `master` specially

"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com> writes:

Show 39 quoted lines
> From: Johannes Schindelin <johannes.schindelin@gmx.de>
>
> In the context of many projects renaming their primary branch names away
> from `master`, Git wants to stop treating the `master` branch specially.
>
> Let's start with `git fmt-merge-msg`.
>
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> ---
>  fmt-merge-msg.c                               |  5 +-
>  t/t1507-rev-parse-upstream.sh                 |  2 +-
>  t/t4013-diff-various.sh                       |  4 +-
>  t/t4013/diff.log_--decorate=full_--all        |  2 +-
>  t/t4013/diff.log_--decorate_--all             |  2 +-
>  ...--patch-with-stat_--summary_master_--_dir_ |  2 +-
>  t/t4013/diff.log_--patch-with-stat_master     |  2 +-
>  .../diff.log_--patch-with-stat_master_--_dir_ |  2 +-
>  ...ot_--cc_--patch-with-stat_--summary_master |  2 +-
>  ..._--root_--patch-with-stat_--summary_master |  2 +-
>  .../diff.log_--root_--patch-with-stat_master  |  2 +-
>  ...root_-c_--patch-with-stat_--summary_master |  2 +-
>  t/t4013/diff.log_--root_-p_master             |  2 +-
>  t/t4013/diff.log_--root_master                |  2 +-
>  t/t4013/diff.log_-m_-p_--first-parent_master  |  2 +-
>  t/t4013/diff.log_-m_-p_master                 |  4 +-
>  t/t4013/diff.log_-p_--first-parent_master     |  2 +-
>  t/t4013/diff.log_-p_master                    |  2 +-
>  t/t4013/diff.log_master                       |  2 +-
>  t/t4013/diff.show_--first-parent_master       |  2 +-
>  t/t4013/diff.show_-c_master                   |  2 +-
>  t/t4013/diff.show_-m_master                   |  4 +-
>  t/t4013/diff.show_master                      |  2 +-
>  ...ot_--cc_--patch-with-stat_--summary_master |  2 +-
>  ...root_-c_--patch-with-stat_--summary_master |  2 +-
>  t/t4202-log.sh                                | 72 +++++++++----------
>  t/t6200-fmt-merge-msg.sh                      | 36 +++++-----
>  t/t7600-merge.sh                              | 14 ++--
>  t/t7608-merge-messages.sh                     | 10 +--
>  29 files changed, 94 insertions(+), 97 deletions(-)

This must have been tedious as the tests with merge commits are all over the place (I know updating t4013 would not have been too much of the work as it has its own self-update knob, but it still is a lot of work to verify that the changes make sense).

Thanks.
Johannes Schindelin· Jun 25, 2020, 13:07 UTC · re: Junio C Hamano · lore

Re: [PATCH v3 1/8] fmt-merge-msg: stop treating `master` specially

Hi Junio,
On Wed, 24 Jun 2020, Junio C Hamano wrote:
Show 47 quoted lines
> "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
> writes:
>
> > From: Johannes Schindelin <johannes.schindelin@gmx.de>
> >
> > In the context of many projects renaming their primary branch names away
> > from `master`, Git wants to stop treating the `master` branch specially.
> >
> > Let's start with `git fmt-merge-msg`.
> >
> > Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> > ---
> >  fmt-merge-msg.c                               |  5 +-
> >  t/t1507-rev-parse-upstream.sh                 |  2 +-
> >  t/t4013-diff-various.sh                       |  4 +-
> >  t/t4013/diff.log_--decorate=full_--all        |  2 +-
> >  t/t4013/diff.log_--decorate_--all             |  2 +-
> >  ...--patch-with-stat_--summary_master_--_dir_ |  2 +-
> >  t/t4013/diff.log_--patch-with-stat_master     |  2 +-
> >  .../diff.log_--patch-with-stat_master_--_dir_ |  2 +-
> >  ...ot_--cc_--patch-with-stat_--summary_master |  2 +-
> >  ..._--root_--patch-with-stat_--summary_master |  2 +-
> >  .../diff.log_--root_--patch-with-stat_master  |  2 +-
> >  ...root_-c_--patch-with-stat_--summary_master |  2 +-
> >  t/t4013/diff.log_--root_-p_master             |  2 +-
> >  t/t4013/diff.log_--root_master                |  2 +-
> >  t/t4013/diff.log_-m_-p_--first-parent_master  |  2 +-
> >  t/t4013/diff.log_-m_-p_master                 |  4 +-
> >  t/t4013/diff.log_-p_--first-parent_master     |  2 +-
> >  t/t4013/diff.log_-p_master                    |  2 +-
> >  t/t4013/diff.log_master                       |  2 +-
> >  t/t4013/diff.show_--first-parent_master       |  2 +-
> >  t/t4013/diff.show_-c_master                   |  2 +-
> >  t/t4013/diff.show_-m_master                   |  4 +-
> >  t/t4013/diff.show_master                      |  2 +-
> >  ...ot_--cc_--patch-with-stat_--summary_master |  2 +-
> >  ...root_-c_--patch-with-stat_--summary_master |  2 +-
> >  t/t4202-log.sh                                | 72 +++++++++----------
> >  t/t6200-fmt-merge-msg.sh                      | 36 +++++-----
> >  t/t7600-merge.sh                              | 14 ++--
> >  t/t7608-merge-messages.sh                     | 10 +--
> >  29 files changed, 94 insertions(+), 97 deletions(-)
>
> This must have been tedious as the tests with merge commits are all
> over the place (I know updating t4013 would not have been too much
> of the work as it has its own self-update knob, but it still is a
> lot of work to verify that the changes make sense).

I missed the self-update knob, but in any case, I would not have used it, anyway, to make sure that I do look closely at all the sites.

Ciao, Dscho

Johannes Schindelin via GitGitGadget· Jun 23, 2020, 22:33 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v3 8/8] testsvn: respect `init.defaultBranch`

From: Johannes Schindelin <johannes.schindelin@gmx.de>

The default name of the initial branch in new repositories can now be configured. The `testsvn` remote helper translates the remote Subversion repository's branch name `trunk` to the hard-coded name `master`. Clearly, the intention was to make the name align with Git's defaults.

So while we are not talking about a newly-created repository in the `testsvn` context, it is a newly-created _Git_ repository, si it _still_ makes sense to use the overridden default name for the initial branch whenever users configured it.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 remote-testsvn.c      | 10 +++++++---
 t/t9020-remote-svn.sh |  6 ++++++
 2 files changed, 13 insertions(+), 3 deletions(-)
Show changes to 2 files +13 −3

remote-testsvn.c, t/t9020-remote-svn.sh

diff --git a/remote-testsvn.c b/remote-testsvn.c
index 3af708c5b6..cde39b94fb 100644
--- a/remote-testsvn.c
+++ b/remote-testsvn.c
@@ -13,7 +13,7 @@
 static const char *url;
 static int dump_from_file;
 static const char *private_ref;
-static const char *remote_ref = "refs/heads/master";
+static char *remote_ref;
 static const char *marksfilename, *notes_ref;
 struct rev_note { unsigned int rev_nr; };
 
@@ -286,7 +286,7 @@ int cmd_main(int argc, const char **argv)
 			private_ref_sb = STRBUF_INIT, marksfilename_sb = STRBUF_INIT,
 			notes_ref_sb = STRBUF_INIT;
 	static struct remote *remote;
-	const char *url_in;
+	const char *url_in, *remote_ref_short;
 
 	setup_git_directory();
 	if (argc < 2 || argc > 3) {
@@ -294,6 +294,9 @@ int cmd_main(int argc, const char **argv)
 		return 1;
 	}
 
+	remote_ref_short = git_default_branch_name();
+	remote_ref = xstrfmt("refs/heads/%s", remote_ref_short);
+
 	remote = remote_get(argv[1]);
 	url_in = (argc == 3) ? argv[2] : remote->url[0];
 
@@ -306,7 +309,8 @@ int cmd_main(int argc, const char **argv)
 		url = url_sb.buf;
 	}
 
-	strbuf_addf(&private_ref_sb, "refs/svn/%s/master", remote->name);
+	strbuf_addf(&private_ref_sb, "refs/svn/%s/%s",
+		    remote->name, remote_ref_short);
 	private_ref = private_ref_sb.buf;
 
 	strbuf_addf(&notes_ref_sb, "refs/notes/%s/revs", remote->name);
diff --git a/t/t9020-remote-svn.sh b/t/t9020-remote-svn.sh
index 9fcfa969a9..754c4a3284 100755
--- a/t/t9020-remote-svn.sh
+++ b/t/t9020-remote-svn.sh
@@ -84,6 +84,12 @@ test_expect_success REMOTE_SVN 'incremental imports must lead to the same head'
 	test_cmp master.good .git/refs/remotes/svnsim/master
 '
 
+test_expect_success REMOTE_SVN 'respects configured default initial branch' '
+	git -c init.defaultBranch=trunk remote add -f trunk \
+		"testsvn::file://$TEST_DIRECTORY/t9154/svn.dump" &&
+	git rev-parse --verify refs/remotes/trunk/trunk
+'
+
 test_debug 'git branch -a'
 
 test_done
-- 
gitgitgadget
Johannes Schindelin via GitGitGadget· Jun 23, 2020, 22:33 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v3 4/8] init: allow specifying the initial branch name for the new repository

From: Johannes Schindelin <johannes.schindelin@gmx.de>

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).

To change that branch name for new repositories, currently the only way to do that automatically is by copying all of Git's template directory, then hard-coding the desired default branch name into the `.git/HEAD` file, and then configuring `init.templateDir` to point to those copied template files.

To make this process much less cumbersome, let's introduce a new option: `--initial-branch=<branch-name>`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 Documentation/git-init.txt |  7 +++++++
 builtin/clone.c            |  3 ++-
 builtin/init-db.c          | 34 +++++++++++++++++++++++++++-------
 cache.h                    |  2 +-
 t/t0001-init.sh            | 13 +++++++++++++
 5 files changed, 50 insertions(+), 9 deletions(-)
Show changes to 5 files +50 −9

Documentation/git-init.txt, builtin/clone.c, builtin/init-db.c, cache.h, t/t0001-init.sh

diff --git a/Documentation/git-init.txt b/Documentation/git-init.txt
index adc6adfd38..36dccc6e52 100644
--- a/Documentation/git-init.txt
+++ b/Documentation/git-init.txt
@@ -11,6 +11,7 @@ SYNOPSIS
 [verse]
 'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
 	  [--separate-git-dir <git dir>] [--object-format=<format]
+	  [-b <branch-name> | --initial-branch=<branch-name>]
 	  [--shared[=<permissions>]] [directory]
 
 
@@ -67,6 +68,12 @@ repository.
 +
 If this is reinitialization, the repository will be moved to the specified path.
 
+-b <branch-name::
+--initial-branch=<branch-name>::
+
+Use the specified name for the initial branch in the newly created repository.
+If not specified, fall back to the default name: `master`.
+
 --shared[=(false|true|umask|group|all|world|everybody|0xxx)]::
 
 Specify that the Git repository is to be shared amongst several users.  This
diff --git a/builtin/clone.c b/builtin/clone.c
index 2a8e3aaaed..b751bdf13e 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1111,7 +1111,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		}
 	}
 
-	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, INIT_DB_QUIET);
+	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL,
+		INIT_DB_QUIET);
 
 	if (real_git_dir)
 		git_dir = real_git_dir;
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 0b7222e718..a898153901 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -203,6 +203,7 @@ void initialize_repository_version(int hash_algo)
 
 static int create_default_files(const char *template_path,
 				const char *original_git_dir,
+				const char *initial_branch,
 				const struct repository_format *fmt)
 {
 	struct stat st1;
@@ -258,16 +259,29 @@ static int create_default_files(const char *template_path,
 		die("failed to set up refs db: %s", err.buf);
 
 	/*
-	 * Create the default symlink from ".git/HEAD" to the "master"
-	 * branch, if it does not exist yet.
+	 * Create the default symlink from ".git/HEAD" to the default
+	 * branch name, if it does not exist yet.
 	 */
 	path = git_path_buf(&buf, "HEAD");
 	reinit = (!access(path, R_OK)
 		  || readlink(path, junk, sizeof(junk)-1) != -1);
 	if (!reinit) {
-		if (create_symref("HEAD", "refs/heads/master", NULL) < 0)
+		char *ref;
+
+		if (!initial_branch)
+			initial_branch = "master";
+
+		ref = xstrfmt("refs/heads/%s", initial_branch);
+		if (check_refname_format(ref, 0) < 0)
+			die(_("invalid initial branch name: '%s'"),
+			    initial_branch);
+
+		if (create_symref("HEAD", ref, NULL) < 0)
 			exit(1);
-	}
+		free(ref);
+	} else if (initial_branch)
+		warning(_("re-init: ignoring --initial-branch=%s"),
+			initial_branch);
 
 	initialize_repository_version(fmt->hash_algo);
 
@@ -383,7 +397,8 @@ static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash
 }
 
 int init_db(const char *git_dir, const char *real_git_dir,
-	    const char *template_dir, int hash, unsigned int flags)
+	    const char *template_dir, int hash, const char *initial_branch,
+	    unsigned int flags)
 {
 	int reinit;
 	int exist_ok = flags & INIT_DB_EXIST_OK;
@@ -425,7 +440,8 @@ int init_db(const char *git_dir, const char *real_git_dir,
 
 	validate_hash_algorithm(&repo_fmt, hash);
 
-	reinit = create_default_files(template_dir, original_git_dir, &repo_fmt);
+	reinit = create_default_files(template_dir, original_git_dir,
+				      initial_branch, &repo_fmt);
 
 	create_object_directory();
 
@@ -528,6 +544,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	const char *template_dir = NULL;
 	unsigned int flags = 0;
 	const char *object_format = NULL;
+	const char *initial_branch = NULL;
 	int hash_algo = GIT_HASH_UNKNOWN;
 	const struct option init_db_options[] = {
 		OPT_STRING(0, "template", &template_dir, N_("template-directory"),
@@ -541,6 +558,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 		OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET),
 		OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
 			   N_("separate git dir from working tree")),
+		OPT_STRING('b', "initial-branch", &initial_branch, N_("name"),
+			   N_("override the name of the initial branch")),
 		OPT_STRING(0, "object-format", &object_format, N_("hash"),
 			   N_("specify the hash algorithm to use")),
 		OPT_END()
@@ -652,5 +671,6 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	UNLEAK(work_tree);
 
 	flags |= INIT_DB_EXIST_OK;
-	return init_db(git_dir, real_git_dir, template_dir, hash_algo, flags);
+	return init_db(git_dir, real_git_dir, template_dir, hash_algo,
+		       initial_branch, flags);
 }
diff --git a/cache.h b/cache.h
index 0f0485ecfe..654426460c 100644
--- a/cache.h
+++ b/cache.h
@@ -628,7 +628,7 @@ int path_inside_repo(const char *prefix, const char *path);
 
 int init_db(const char *git_dir, const char *real_git_dir,
 	    const char *template_dir, int hash_algo,
-	    unsigned int flags);
+	    const char *initial_branch, unsigned int flags);
 void initialize_repository_version(int hash_algo);
 
 void sanitize_stdfds(void);
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index 1edd5aeb8f..61837ca25f 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -464,4 +464,17 @@ test_expect_success MINGW 'redirect std handles' '
 	grep "Needed a single revision" output.txt
 '
 
+test_expect_success '--initial-branch' '
+	git init --initial-branch=hello initial-branch-option &&
+	git -C initial-branch-option symbolic-ref HEAD >actual &&
+	echo refs/heads/hello >expect &&
+	test_cmp expect actual &&
+
+	: re-initializing should not change the branch name &&
+	git init --initial-branch=ignore initial-branch-option 2>err &&
+	test_i18ngrep "ignoring --initial-branch" err &&
+	git -C initial-branch-option symbolic-ref HEAD >actual &&
+	grep hello actual
+'
+
 test_done
-- 
gitgitgadget
Junio C Hamano· Jun 24, 2020, 00:58 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH v3 4/8] init: allow specifying the initial branch name for the new repository

"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com> writes:

>  [verse]
>  'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
>  	  [--separate-git-dir <git dir>] [--object-format=<format]
Completely offtopic.  We lack the closing ket> here.
Show 13 quoted lines
> +	  [-b <branch-name> | --initial-branch=<branch-name>]
>  	  [--shared[=<permissions>]] [directory]
>  
>  
> @@ -67,6 +68,12 @@ repository.
>  +
>  If this is reinitialization, the repository will be moved to the specified path.
>  
> +-b <branch-name::
> +--initial-branch=<branch-name>::
> +
> +Use the specified name for the initial branch in the newly created repository.
> +If not specified, fall back to the default name: `master`.
OK.
Show 35 quoted lines
> diff --git a/builtin/clone.c b/builtin/clone.c
> index 2a8e3aaaed..b751bdf13e 100644
> --- a/builtin/clone.c
> +++ b/builtin/clone.c
> @@ -1111,7 +1111,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
>  		}
>  	}
>  
> -	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, INIT_DB_QUIET);
> +	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL,
> +		INIT_DB_QUIET);
>  
>  	if (real_git_dir)
>  		git_dir = real_git_dir;
> diff --git a/builtin/init-db.c b/builtin/init-db.c
> index 0b7222e718..a898153901 100644
> --- a/builtin/init-db.c
> +++ b/builtin/init-db.c
> @@ -203,6 +203,7 @@ void initialize_repository_version(int hash_algo)
>  
>  static int create_default_files(const char *template_path,
>  				const char *original_git_dir,
> +				const char *initial_branch,
>  				const struct repository_format *fmt)
>  {
>  	struct stat st1;
> @@ -258,16 +259,29 @@ static int create_default_files(const char *template_path,
>  		die("failed to set up refs db: %s", err.buf);
>  
>  	/*
> -	 * Create the default symlink from ".git/HEAD" to the "master"
> -	 * branch, if it does not exist yet.
> +	 * Create the default symlink from ".git/HEAD" to the default
> +	 * branch name, if it does not exist yet.
>  	 */

To the caller of this helper, it may be "the default", but as far as this helper is concerned, it is not "default" but the initial branch that was given by the caller. How about...

	/*
	 * Point the initial branch with HEAD symref, if HEAD does
	 * not exist yet.
	 */

... to modernize the reference to symlink and replace it with symref?

Show 7 quoted lines
> +		if (!initial_branch)
> +			initial_branch = "master";
> +
> +		ref = xstrfmt("refs/heads/%s", initial_branch);
> +		if (check_refname_format(ref, 0) < 0)
> +			die(_("invalid initial branch name: '%s'"),
> +			    initial_branch);

Good. We make sure to prefix with "refs/heads/" so the callers cannot abuse us to point HEAD outside the local branches.

Show 7 quoted lines
> +		if (create_symref("HEAD", ref, NULL) < 0)
>  			exit(1);
> -	}
> +		free(ref);
> +	} else if (initial_branch)
> +		warning(_("re-init: ignoring --initial-branch=%s"),
> +			initial_branch);

Somehow the error checking convention feels uneven in this API. It is a warning-worthy offense for the caller to give initial_branch when we are re-initializing, but it is not an error for the caller not to supply the initial branch name on the other side of if/else. Worse yet, this helper function even knows the command line option name that resulted in the parameter coming to it.

That unevenness ultimately comes from the fact that the caller does not know if we are dealing with a repository that already has HEAD before calling, but at least we should be able to tell the caller if we initialized or not with our return value and allow the caller to issue this warning---that way we can lose the warning from here and get rid of the uneven feeling. Oh, and ...

Show 17 quoted lines
> @@ -383,7 +397,8 @@ static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash
>  }
>  
>  int init_db(const char *git_dir, const char *real_git_dir,
> -	    const char *template_dir, int hash, unsigned int flags)
> +	    const char *template_dir, int hash, const char *initial_branch,
> +	    unsigned int flags)
>  {
>  	int reinit;
>  	int exist_ok = flags & INIT_DB_EXIST_OK;
> @@ -425,7 +440,8 @@ int init_db(const char *git_dir, const char *real_git_dir,
>  
>  	validate_hash_algorithm(&repo_fmt, hash);
>  
> -	reinit = create_default_files(template_dir, original_git_dir, &repo_fmt);
> +	reinit = create_default_files(template_dir, original_git_dir,
> +				      initial_branch, &repo_fmt);

... we are telling the caller if we are in reinit situation, so we can afford to do exactly that.

	reinit = create_default_files...
 	if (reinit && initial_branch)
		warning(_("re-init: ignored --initial-branch"));
That's much better ;-)
Other than that, looks good to me.
Thanks.
Johannes Schindelin· Jun 24, 2020, 12:55 UTC · re: Junio C Hamano · lore

Re: [PATCH v3 4/8] init: allow specifying the initial branch name for the new repository

Hi Junio,
On Tue, 23 Jun 2020, Junio C Hamano wrote:
Show 8 quoted lines
> "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
> writes:
>
> >  [verse]
> >  'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
> >  	  [--separate-git-dir <git dir>] [--object-format=<format]
>
> Completely offtopic.  We lack the closing ket> here.

Not so off-topic: the fix for this would cause conflicts. In the interest of avoiding merge conflicts, I incorporated a patch to fix that (`git grep` found two more instances, which I fixed "while at it").

Show 63 quoted lines
> > +	  [-b <branch-name> | --initial-branch=<branch-name>]
> >  	  [--shared[=<permissions>]] [directory]
> >
> >
> > @@ -67,6 +68,12 @@ repository.
> >  +
> >  If this is reinitialization, the repository will be moved to the specified path.
> >
> > +-b <branch-name::
> > +--initial-branch=<branch-name>::
> > +
> > +Use the specified name for the initial branch in the newly created repository.
> > +If not specified, fall back to the default name: `master`.
>
> OK.
>
> > diff --git a/builtin/clone.c b/builtin/clone.c
> > index 2a8e3aaaed..b751bdf13e 100644
> > --- a/builtin/clone.c
> > +++ b/builtin/clone.c
> > @@ -1111,7 +1111,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
> >  		}
> >  	}
> >
> > -	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, INIT_DB_QUIET);
> > +	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL,
> > +		INIT_DB_QUIET);
> >
> >  	if (real_git_dir)
> >  		git_dir = real_git_dir;
> > diff --git a/builtin/init-db.c b/builtin/init-db.c
> > index 0b7222e718..a898153901 100644
> > --- a/builtin/init-db.c
> > +++ b/builtin/init-db.c
> > @@ -203,6 +203,7 @@ void initialize_repository_version(int hash_algo)
> >
> >  static int create_default_files(const char *template_path,
> >  				const char *original_git_dir,
> > +				const char *initial_branch,
> >  				const struct repository_format *fmt)
> >  {
> >  	struct stat st1;
> > @@ -258,16 +259,29 @@ static int create_default_files(const char *template_path,
> >  		die("failed to set up refs db: %s", err.buf);
> >
> >  	/*
> > -	 * Create the default symlink from ".git/HEAD" to the "master"
> > -	 * branch, if it does not exist yet.
> > +	 * Create the default symlink from ".git/HEAD" to the default
> > +	 * branch name, if it does not exist yet.
> >  	 */
>
> To the caller of this helper, it may be "the default", but as far as
> this helper is concerned, it is not "default" but the initial branch
> that was given by the caller.  How about...
>
> 	/*
> 	 * Point the initial branch with HEAD symref, if HEAD does
> 	 * not exist yet.
> 	 */
>
> ... to modernize the reference to symlink and replace it with
> symref?

Good point. I massaged your proposed comment and replaced the old one with it.

Show 10 quoted lines
> > +		if (!initial_branch)
> > +			initial_branch = "master";
> > +
> > +		ref = xstrfmt("refs/heads/%s", initial_branch);
> > +		if (check_refname_format(ref, 0) < 0)
> > +			die(_("invalid initial branch name: '%s'"),
> > +			    initial_branch);
>
> Good.  We make sure to prefix with "refs/heads/" so the callers
> cannot abuse us to point HEAD outside the local branches.
Yes, Peff offered that concern, and I agree.
Show 46 quoted lines
> > +		if (create_symref("HEAD", ref, NULL) < 0)
> >  			exit(1);
> > -	}
> > +		free(ref);
> > +	} else if (initial_branch)
> > +		warning(_("re-init: ignoring --initial-branch=%s"),
> > +			initial_branch);
>
> Somehow the error checking convention feels uneven in this API.  It
> is a warning-worthy offense for the caller to give initial_branch
> when we are re-initializing, but it is not an error for the caller
> not to supply the initial branch name on the other side of if/else.
> Worse yet, this helper function even knows the command line option
> name that resulted in the parameter coming to it.
>
> That unevenness ultimately comes from the fact that the caller does
> not know if we are dealing with a repository that already has HEAD
> before calling, but at least we should be able to tell the caller
> if we initialized or not with our return value and allow the caller
> to issue this warning---that way we can lose the warning from here
> and get rid of the uneven feeling.  Oh, and ...
>
> > @@ -383,7 +397,8 @@ static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash
> >  }
> >
> >  int init_db(const char *git_dir, const char *real_git_dir,
> > -	    const char *template_dir, int hash, unsigned int flags)
> > +	    const char *template_dir, int hash, const char *initial_branch,
> > +	    unsigned int flags)
> >  {
> >  	int reinit;
> >  	int exist_ok = flags & INIT_DB_EXIST_OK;
> > @@ -425,7 +440,8 @@ int init_db(const char *git_dir, const char *real_git_dir,
> >
> >  	validate_hash_algorithm(&repo_fmt, hash);
> >
> > -	reinit = create_default_files(template_dir, original_git_dir, &repo_fmt);
> > +	reinit = create_default_files(template_dir, original_git_dir,
> > +				      initial_branch, &repo_fmt);
>
> ... we are telling the caller if we are in reinit situation, so we
> can afford to do exactly that.
>
> 	reinit = create_default_files...
>  	if (reinit && initial_branch)
> 		warning(_("re-init: ignored --initial-branch"));
I changed it accordingly.

Thanks, Dscho

Show 8 quoted lines
>
> That's much better ;-)
>
> Other than that, looks good to me.
>
> Thanks.
>
>
Johannes Schindelin via GitGitGadget· Jun 23, 2020, 22:33 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v3 7/8] remote: use the configured default branch name when appropriate

From: Johannes Schindelin <johannes.schindelin@gmx.de>

When guessing the default branch name of a remote, and there are no refs to guess from, we want to go with the preference specified by the user for the fall-back, i.e. the default name to be used for the initial branch of new repositories (because as far as the user is concerned, a remote that has no branches yet is a new repository).

At the same time, when talking to an older Git server that does not report a symref for `HEAD` (but instead reports a commit hash), let's try to guess the configured default branch name first. If it does not match the reported commit hash, let's fall back to `master` as before.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 remote.c                 | 14 +++++++++++---
 t/t5606-clone-options.sh | 11 ++++++++++-
 2 files changed, 21 insertions(+), 4 deletions(-)
Show changes to 2 files +21 −4

remote.c, t/t5606-clone-options.sh

diff --git a/remote.c b/remote.c
index 534c6426f1..965129adc3 100644
--- a/remote.c
+++ b/remote.c
@@ -276,7 +276,7 @@ static void read_branches_file(struct remote *remote)
 
 	/*
 	 * The branches file would have URL and optionally
-	 * #branch specified.  The "master" (or specified) branch is
+	 * #branch specified.  The main (or specified) branch is
 	 * fetched and stored in the local branch matching the
 	 * remote name.
 	 */
@@ -284,7 +284,7 @@ static void read_branches_file(struct remote *remote)
 	if (frag)
 		*(frag++) = '\0';
 	else
-		frag = "master";
+		frag = (char *)git_default_branch_name();
 
 	add_url_alias(remote, strbuf_detach(&buf, NULL));
 	strbuf_addf(&buf, "refs/heads/%s:refs/heads/%s",
@@ -2097,8 +2097,16 @@ struct ref *guess_remote_head(const struct ref *head,
 	if (head->symref)
 		return copy_ref(find_ref_by_name(refs, head->symref));
 
-	/* If refs/heads/master could be right, it is. */
+	/* If a remote branch exists with the default branch name, let's use it. */
 	if (!all) {
+		char *ref = xstrfmt("refs/heads/%s", git_default_branch_name());
+
+		r = find_ref_by_name(refs, ref);
+		free(ref);
+		if (r && oideq(&r->old_oid, &head->old_oid))
+			return copy_ref(r);
+
+		/* Fall back to the hard-coded historical default */
 		r = find_ref_by_name(refs, "refs/heads/master");
 		if (r && oideq(&r->old_oid, &head->old_oid))
 			return copy_ref(r);
diff --git a/t/t5606-clone-options.sh b/t/t5606-clone-options.sh
index 286bfd93ac..e69427f881 100755
--- a/t/t5606-clone-options.sh
+++ b/t/t5606-clone-options.sh
@@ -47,7 +47,16 @@ test_expect_success 'guesses initial branch name correctly' '
 	test_commit -C initial-branch no-spoilers &&
 	git -C initial-branch branch abc guess &&
 	git clone initial-branch is-it &&
-	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD)
+	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD) &&
+
+	git -c init.defaultBranch=none init --bare no-head &&
+	git -C initial-branch push ../no-head guess abc &&
+	git clone no-head is-it2 &&
+	test_must_fail git -C is-it2 symbolic-ref refs/remotes/origin/HEAD &&
+	git -C no-head update-ref --no-deref HEAD refs/heads/guess &&
+	git -c init.defaultBranch=guess clone no-head is-it3 &&
+	test refs/remotes/origin/guess = \
+		$(git -C is-it3 symbolic-ref refs/remotes/origin/HEAD)
 '
 
 test_done
-- 
gitgitgadget
Junio C Hamano· Jun 24, 2020, 01:10 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH v3 7/8] remote: use the configured default branch name when appropriate

"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com> writes:

Show 13 quoted lines
> diff --git a/remote.c b/remote.c
> index 534c6426f1..965129adc3 100644
> --- a/remote.c
> +++ b/remote.c
> @@ -276,7 +276,7 @@ static void read_branches_file(struct remote *remote)
>  
>  	/*
>  	 * The branches file would have URL and optionally
> -	 * #branch specified.  The "master" (or specified) branch is
> +	 * #branch specified.  The main (or specified) branch is
>  	 * fetched and stored in the local branch matching the
>  	 * remote name.
>  	 */
Isn't this a bit premature here?
Johannes Schindelin· Jun 24, 2020, 13:00 UTC · re: Junio C Hamano · lore

Re: [PATCH v3 7/8] remote: use the configured default branch name when appropriate

Hi Junio,
On Tue, 23 Jun 2020, Junio C Hamano wrote:
Show 18 quoted lines
> "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
> writes:
>
> > diff --git a/remote.c b/remote.c
> > index 534c6426f1..965129adc3 100644
> > --- a/remote.c
> > +++ b/remote.c
> > @@ -276,7 +276,7 @@ static void read_branches_file(struct remote *remote)
> >
> >  	/*
> >  	 * The branches file would have URL and optionally
> > -	 * #branch specified.  The "master" (or specified) branch is
> > +	 * #branch specified.  The main (or specified) branch is
> >  	 * fetched and stored in the local branch matching the
> >  	 * remote name.
> >  	 */
>
> Isn't this a bit premature here?

Actually, it is just wrong. It should talk about the default branch instead.

Ciao, Dscho

Johannes Schindelin via GitGitGadget· Jun 23, 2020, 22:33 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v3 3/8] submodule: use a better fall-back for missing remote.<name>.branch

From: Johannes Schindelin <johannes.schindelin@gmx.de>

When `remote.<name>.branch` is not configured, `git submodule update` currently falls back to using the branch name `master`. A much better idea, however, is to use `HEAD`: on all Git servers running reasonably recent Git versions, the symref `HEAD` points to the main branch.

Note: t7419 demonstrates that there _might_ be use cases out there that
_expect_ `git submodule update --remote` to update submodules to the
remote `master` branch even if the remote `HEAD` points to another
branch. Arguably, this patch makes the behavior more intuitive, but
there is a slight possibility that this might cause regressions in
obscure setups.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 Documentation/git-submodule.txt |  4 ++--
 builtin/submodule--helper.c     |  2 +-
 t/t7406-submodule-update.sh     | 16 ++++++++++++++++
 t/t7419-submodule-set-branch.sh |  7 +++++--
 4 files changed, 24 insertions(+), 5 deletions(-)
Show changes to 4 files +24 −5

Documentation/git-submodule.txt, builtin/submodule--helper.c, t/t7406-submodule-update.sh, t/t7419-submodule-set-branch.sh

diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index c9ed2bf3d5..b20f85e622 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -284,7 +284,7 @@ OPTIONS
 	`.gitmodules` for `update --remote`.  A special value of `.` is used to
 	indicate that the name of the branch in the submodule should be the
 	same name as the current branch in the current repository.  If the
-	option is not specified, it defaults to 'master'.
+	option is not specified, it defaults to 'HEAD'.
 
 -f::
 --force::
@@ -322,7 +322,7 @@ OPTIONS
 	the superproject's recorded SHA-1 to update the submodule, use the
 	status of the submodule's remote-tracking branch.  The remote used
 	is branch's remote (`branch.<name>.remote`), defaulting to `origin`.
-	The remote branch used defaults to `master`, but the branch name may
+	The remote branch used defaults to `HEAD`, but the branch name may
 	be overridden by setting the `submodule.<name>.branch` option in
 	either `.gitmodules` or `.git/config` (with `.git/config` taking
 	precedence).
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 46c03d2a12..f55f7b7704 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1981,7 +1981,7 @@ static const char *remote_submodule_branch(const char *path)
 	free(key);
 
 	if (!branch)
-		return "master";
+		return "HEAD";
 
 	if (!strcmp(branch, ".")) {
 		const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index 4fb447a143..aa19ff3a2e 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -70,6 +70,22 @@ test_expect_success 'setup a submodule tree' '
 	)
 '
 
+test_expect_success 'update --remote falls back to using HEAD' '
+	test_create_repo main-branch-submodule &&
+	test_commit -C main-branch-submodule initial &&
+
+	test_create_repo main-branch &&
+	git -C main-branch submodule add ../main-branch-submodule &&
+	git -C main-branch commit -m add-submodule &&
+
+	git -C main-branch-submodule switch -c hello &&
+	test_commit -C main-branch-submodule world &&
+
+	git clone --recursive main-branch main-branch-clone &&
+	git -C main-branch-clone submodule update --remote main-branch-submodule &&
+	test_path_exists main-branch-clone/main-branch-submodule/world.t
+'
+
 test_expect_success 'submodule update detaching the HEAD ' '
 	(cd super/submodule &&
 	 git reset --hard HEAD~1
diff --git a/t/t7419-submodule-set-branch.sh b/t/t7419-submodule-set-branch.sh
index fd25f786a3..3b925c302f 100755
--- a/t/t7419-submodule-set-branch.sh
+++ b/t/t7419-submodule-set-branch.sh
@@ -52,12 +52,13 @@ test_expect_success 'test submodule set-branch --branch' '
 '
 
 test_expect_success 'test submodule set-branch --default' '
+	test_commit -C submodule c &&
 	(cd super &&
 		git submodule set-branch --default submodule &&
 		! grep branch .gitmodules &&
 		git submodule update --remote &&
 		cat <<-\EOF >expect &&
-		a
+		c
 		EOF
 		git -C submodule show -s --pretty=%s >actual &&
 		test_cmp expect actual
@@ -65,6 +66,7 @@ test_expect_success 'test submodule set-branch --default' '
 '
 
 test_expect_success 'test submodule set-branch -b' '
+	test_commit -C submodule b &&
 	(cd super &&
 		git submodule set-branch -b topic submodule &&
 		grep "branch = topic" .gitmodules &&
@@ -78,12 +80,13 @@ test_expect_success 'test submodule set-branch -b' '
 '
 
 test_expect_success 'test submodule set-branch -d' '
+	test_commit -C submodule d &&
 	(cd super &&
 		git submodule set-branch -d submodule &&
 		! grep branch .gitmodules &&
 		git submodule update --remote &&
 		cat <<-\EOF >expect &&
-		a
+		d
 		EOF
 		git -C submodule show -s --pretty=%s >actual &&
 		test_cmp expect actual
-- 
gitgitgadget
Philippe Blain· Jun 24, 2020, 02:18 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH v3 3/8] submodule: use a better fall-back for missing remote.<name>.branch

Hi Dscho,
Show 8 quoted lines
> Le 23 juin 2020 à 18:33, Johannes Schindelin via GitGitGadget <gitgitgadget@gmail.com> a écrit :
> 
> From: Johannes Schindelin <johannes.schindelin@gmx.de>
> 
> When `remote.<name>.branch` is not configured, `git submodule update`
> currently falls back to using the branch name `master`. A much better
> idea, however, is to use `HEAD`: on all Git servers running reasonably
> recent Git versions, the symref `HEAD` points to the main branch.

To be pedantic, it is up to the maintainer/developers to make sure that HEAD on the canonic repository indeed points to the branch that is considered the 'main' branch of the project; the Git version does not really matter IMO... I've seen plenty of repos at work that have HEAD pointing to `master` but `master` is not used, or not anymore...

Show 8 quoted lines
> Note: t7419 demonstrates that there _might_ be use cases out there that
> _expect_ `git submodule update --remote` to update submodules to the
> remote `master` branch even if the remote `HEAD` points to another
> branch. Arguably, this patch makes the behavior more intuitive, but
> there is a slight possibility that this might cause regressions in
> obscure setups.
> 
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>

I think that's an excellent idea. However I'd be more explicit in the commit message title: submodule: fall back to remote's HEAD for missing remote.<name>.branch

meta comment: I never know where is the best place to make suggestions about changing the commit message title, since I can't quote it in my replies!

Show 6 quoted lines
> ---
> Documentation/git-submodule.txt |  4 ++--
> builtin/submodule--helper.c     |  2 +-
> t/t7406-submodule-update.sh     | 16 ++++++++++++++++
> t/t7419-submodule-set-branch.sh |  7 +++++--
> 4 files changed, 24 insertions(+), 5 deletions(-)
I think Documentation/gitmodules.txt (`submodule.<name>.branch` header)
 should also be changed to reflect the behaviour change: 
Show changes to 2 files +4 −4

Documentation/gitmodules.txt, Documentation/git-submodule.txt

diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt
index 67275fd187..539b4e1997 100644
--- a/Documentation/gitmodules.txt
+++ b/Documentation/gitmodules.txt
@@ -49,9 +49,9 @@ submodule.<name>.update::
 
 submodule.<name>.branch::
 	A remote branch name for tracking updates in the upstream submodule.
-	If the option is not specified, it defaults to 'master'.  A special
-	value of `.` is used to indicate that the name of the branch in the
-	submodule should be the same name as the current branch in the
+	If the option is not specified, it defaults to the remote 'HEAD'.
+	A special value of `.` is used to indicate that the name of the branch
+	in the submodule should be the same name as the current branch in the
 	current repository.  See the `--remote` documentation in
 	linkgit:git-submodule[1] for details.

> diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
> index c9ed2bf3d5..b20f85e622 100644
> --- a/Documentation/git-submodule.txt
> +++ b/Documentation/git-submodule.txt
> @@ -284,7 +284,7 @@ OPTIONS
> 	`.gitmodules` for `update --remote`.  A special value of `.` is used to
> 	indicate that the name of the branch in the submodule should be the
> 	same name as the current branch in the current repository.  If the
> -	option is not specified, it defaults to 'master'.
> +	option is not specified, it defaults to 'HEAD'.

Just to be extra clear (it's easy to get confused with submodules!) I'd say explicitly:

If the option is not specified, it defaults to the remote 'HEAD'.

> 
> -f::
> --force::
> @@ -322,7 +322,7 @@ OPTIONS
> 	the superproject's recorded SHA-1 to update the submodule, use the
> 	status of the submodule's remote-tracking branch.  The remote used
> 	is branch's remote (`branch.<name>.remote`), defaulting to `origin`.
> -	The remote branch used defaults to `master`, but the branch name may
> +	The remote branch used defaults to `HEAD`, but the branch name may

Same thing here:

The remote branch used defaults to the remote `HEAD`.

> 	be overridden by setting the `submodule.<name>.branch` option in
> 	either `.gitmodules` or `.git/config` (with `.git/config` taking
> 	precedence).

Also, you seem to have missed the `master` reference in the description of 
the 'set-branch' subcommand. Something like this would do, I think:

diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index c9ed2bf3d5..8cf5831a72 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -183,7 +183,7 @@ set-branch (-d|--default) [--] <path>::
 	Sets the default remote tracking branch for the submodule. The
 	`--branch` option allows the remote branch to be specified. The
 	`--default` option removes the submodule.<name>.branch configuration
-	key, which causes the tracking branch to default to 'master'.
+	key, which causes the tracking branch to default to the remote 'HEAD'.
 
 set-url [--] <path> <newurl>::
 	Sets the URL of the specified submodule to <newurl>. Then, it will


The rest of the patch looks good.

Cheers,
Philippe.
Johannes Schindelin· Jun 24, 2020, 12:51 UTC · re: Philippe Blain · lore

Re: [PATCH v3 3/8] submodule: use a better fall-back for missing remote.<name>.branch

Hi Philippe,
On Tue, 23 Jun 2020, Philippe Blain wrote:
Show 14 quoted lines
> > Le 23 juin 2020 à 18:33, Johannes Schindelin via GitGitGadget <gitgitgadget@gmail.com> a écrit :
> >
> > From: Johannes Schindelin <johannes.schindelin@gmx.de>
> >
> > When `remote.<name>.branch` is not configured, `git submodule update`
> > currently falls back to using the branch name `master`. A much better
> > idea, however, is to use `HEAD`: on all Git servers running reasonably
> > recent Git versions, the symref `HEAD` points to the main branch.
>
> To be pedantic, it is up to the maintainer/developers to make sure that
> HEAD on the canonic repository indeed points to the branch that is
> considered the 'main' branch of the project; the Git version does not
> really matter IMO... I've seen plenty of repos at work that have HEAD
> pointing to `master` but `master` is not used, or not anymore...

Oh, but in this case, my main concern was servers that are so old that `HEAD` is not a symref, in which case it can be a bit tricky to figure out the default branch.

In any case, I feel this is such a minor point that I don't really want to spend a lot of time on this paragraph.

Show 13 quoted lines
> > Note: t7419 demonstrates that there _might_ be use cases out there that
> > _expect_ `git submodule update --remote` to update submodules to the
> > remote `master` branch even if the remote `HEAD` points to another
> > branch. Arguably, this patch makes the behavior more intuitive, but
> > there is a slight possibility that this might cause regressions in
> > obscure setups.
> >
> > Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
>
> I think that's an excellent idea. However I'd be more explicit in the
> commit message title:
>
> submodule: fall back to remote's HEAD for missing remote.<name>.branch
Great!
> meta comment: I never know where is the best place to make suggestions
> about changing the commit message title, since I can't quote it in my
> replies!
True. You could copy it, but that's not the same.
Show 26 quoted lines
> > ---
> > Documentation/git-submodule.txt |  4 ++--
> > builtin/submodule--helper.c     |  2 +-
> > t/t7406-submodule-update.sh     | 16 ++++++++++++++++
> > t/t7419-submodule-set-branch.sh |  7 +++++--
> > 4 files changed, 24 insertions(+), 5 deletions(-)
>
> I think Documentation/gitmodules.txt (`submodule.<name>.branch` header)
>  should also be changed to reflect the behaviour change:
>
> diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt
> index 67275fd187..539b4e1997 100644
> --- a/Documentation/gitmodules.txt
> +++ b/Documentation/gitmodules.txt
> @@ -49,9 +49,9 @@ submodule.<name>.update::
>
>  submodule.<name>.branch::
>  	A remote branch name for tracking updates in the upstream submodule.
> -	If the option is not specified, it defaults to 'master'.  A special
> -	value of `.` is used to indicate that the name of the branch in the
> -	submodule should be the same name as the current branch in the
> +	If the option is not specified, it defaults to the remote 'HEAD'.
> +	A special value of `.` is used to indicate that the name of the branch
> +	in the submodule should be the same name as the current branch in the
>  	current repository.  See the `--remote` documentation in
>  	linkgit:git-submodule[1] for details.
Excellent, I used that verbatim. Thank you!
Show 15 quoted lines
> > diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
> > index c9ed2bf3d5..b20f85e622 100644
> > --- a/Documentation/git-submodule.txt
> > +++ b/Documentation/git-submodule.txt
> > @@ -284,7 +284,7 @@ OPTIONS
> > 	`.gitmodules` for `update --remote`.  A special value of `.` is used to
> > 	indicate that the name of the branch in the submodule should be the
> > 	same name as the current branch in the current repository.  If the
> > -	option is not specified, it defaults to 'master'.
> > +	option is not specified, it defaults to 'HEAD'.
>
> Just to be extra clear (it's easy to get confused with submodules!) I'd
> say explicitly:
>
> If the option is not specified, it defaults to the remote 'HEAD'.
Good idea. I incorporated that, too.
Show 12 quoted lines
> > -f::
> > --force::
> > @@ -322,7 +322,7 @@ OPTIONS
> > 	the superproject's recorded SHA-1 to update the submodule, use the
> > 	status of the submodule's remote-tracking branch.  The remote used
> > 	is branch's remote (`branch.<name>.remote`), defaulting to `origin`.
> > -	The remote branch used defaults to `master`, but the branch name may
> > +	The remote branch used defaults to `HEAD`, but the branch name may
>
> Same thing here:
>
> The remote branch used defaults to the remote `HEAD`.
And that.
Show 20 quoted lines
> > 	be overridden by setting the `submodule.<name>.branch` option in
> > 	either `.gitmodules` or `.git/config` (with `.git/config` taking
> > 	precedence).
>
> Also, you seem to have missed the `master` reference in the description of
> the 'set-branch' subcommand. Something like this would do, I think:
>
> diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
> index c9ed2bf3d5..8cf5831a72 100644
> --- a/Documentation/git-submodule.txt
> +++ b/Documentation/git-submodule.txt
> @@ -183,7 +183,7 @@ set-branch (-d|--default) [--] <path>::
>  	Sets the default remote tracking branch for the submodule. The
>  	`--branch` option allows the remote branch to be specified. The
>  	`--default` option removes the submodule.<name>.branch configuration
> -	key, which causes the tracking branch to default to 'master'.
> +	key, which causes the tracking branch to default to the remote 'HEAD'.
>
>  set-url [--] <path> <newurl>::
>  	Sets the URL of the specified submodule to <newurl>. Then, it will
And that.
> The rest of the patch looks good.
Awesome. Thank you for helping me improve this patch series!

Ciao, Dscho

Johannes Schindelin via GitGitGadget· Jun 23, 2020, 22:33 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v3 6/8] clone: use configured default branch name when appropriate

From: Johannes Schindelin <johannes.schindelin@gmx.de>

When cloning a repository without any branches, Git chooses a default branch name for the as-yet unborn branch.

As part of the implicit initialization of the local repository, Git just learned to respect `init.defaultBranch` to choose a different initial branch name. We now really want that branch name to be used as a fall-back.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 Documentation/config/init.txt |  4 ++--
 builtin/clone.c               | 10 +++++++---
 t/t5606-clone-options.sh      | 15 +++++++++++++++
 3 files changed, 24 insertions(+), 5 deletions(-)
Show changes to 3 files +24 −5

Documentation/config/init.txt, builtin/clone.c, t/t5606-clone-options.sh

diff --git a/Documentation/config/init.txt b/Documentation/config/init.txt
index 6ae4a38416..dc77f8c844 100644
--- a/Documentation/config/init.txt
+++ b/Documentation/config/init.txt
@@ -3,5 +3,5 @@ init.templateDir::
 	(See the "TEMPLATE DIRECTORY" section of linkgit:git-init[1].)
 
 init.defaultBranch::
-	Allows overriding the default branch name when initializing
-	a new repository.
+	Allows overriding the default branch name e.g. when initializing
+	a new repository or when cloning an empty repository.
diff --git a/builtin/clone.c b/builtin/clone.c
index b751bdf13e..9a3f91b268 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1267,9 +1267,13 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		remote_head_points_at = NULL;
 		remote_head = NULL;
 		option_no_checkout = 1;
-		if (!option_bare)
-			install_branch_config(0, "master", option_origin,
-					      "refs/heads/master");
+		if (!option_bare) {
+			const char *branch = git_default_branch_name();
+			char *ref = xstrfmt("refs/heads/%s", branch);
+
+			install_branch_config(0, branch, option_origin, ref);
+			free(ref);
+		}
 	}
 
 	write_refspec_config(src_ref_prefix, our_head_points_at,
diff --git a/t/t5606-clone-options.sh b/t/t5606-clone-options.sh
index 9e24ec88e6..286bfd93ac 100755
--- a/t/t5606-clone-options.sh
+++ b/t/t5606-clone-options.sh
@@ -35,4 +35,19 @@ test_expect_success 'redirected clone -v does show progress' '
 
 '
 
+test_expect_success 'chooses correct default initial branch name' '
+	git init --bare empty &&
+	git -c init.defaultBranch=up clone empty whats-up &&
+	test refs/heads/up = $(git -C whats-up symbolic-ref HEAD) &&
+	test refs/heads/up = $(git -C whats-up config branch.up.merge)
+'
+
+test_expect_success 'guesses initial branch name correctly' '
+	git init --initial-branch=guess initial-branch &&
+	test_commit -C initial-branch no-spoilers &&
+	git -C initial-branch branch abc guess &&
+	git clone initial-branch is-it &&
+	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD)
+'
+
 test_done
-- 
gitgitgadget
Don Goodman-Wilson via GitGitGadget· Jun 23, 2020, 22:33 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v3 5/8] init: allow setting the default for the initial branch name via the config

From: Don Goodman-Wilson <don@goodman-wilson.com>

We just introduced the command-line option `--initial-branch=<branch-name>` to allow initializing a new repository with a different initial branch than the hard-coded one.

To allow users to override the initial branch name more permanently (i.e. without having to specify the name manually for each and every `git init` invocation), let's introduce the `init.defaultBranch` config setting.

Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Helped-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Don Goodman-Wilson <don@goodman-wilson.com>
---
 Documentation/config/init.txt |  4 ++++
 builtin/init-db.c             |  2 +-
 refs.c                        | 30 ++++++++++++++++++++++++++++++
 refs.h                        |  9 +++++++++
 t/t0001-init.sh               | 13 +++++++++++++
 5 files changed, 57 insertions(+), 1 deletion(-)
Show changes to 5 files +57 −1

Documentation/config/init.txt, builtin/init-db.c, refs.c, refs.h, t/t0001-init.sh

diff --git a/Documentation/config/init.txt b/Documentation/config/init.txt
index 46fa8c6a08..6ae4a38416 100644
--- a/Documentation/config/init.txt
+++ b/Documentation/config/init.txt
@@ -1,3 +1,7 @@
 init.templateDir::
 	Specify the directory from which templates will be copied.
 	(See the "TEMPLATE DIRECTORY" section of linkgit:git-init[1].)
+
+init.defaultBranch::
+	Allows overriding the default branch name when initializing
+	a new repository.
diff --git a/builtin/init-db.c b/builtin/init-db.c
index a898153901..b8634b5f35 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -269,7 +269,7 @@ static int create_default_files(const char *template_path,
 		char *ref;
 
 		if (!initial_branch)
-			initial_branch = "master";
+			initial_branch = git_default_branch_name();
 
 		ref = xstrfmt("refs/heads/%s", initial_branch);
 		if (check_refname_format(ref, 0) < 0)
diff --git a/refs.c b/refs.c
index 224ff66c7b..b98dea5217 100644
--- a/refs.c
+++ b/refs.c
@@ -560,6 +560,36 @@ void expand_ref_prefix(struct argv_array *prefixes, const char *prefix)
 		argv_array_pushf(prefixes, *p, len, prefix);
 }
 
+char *repo_default_branch_name(struct repository *r)
+{
+	const char *config_key = "init.defaultbranch";
+	const char *config_display_key = "init.defaultBranch";
+	char *ret = NULL, *full_ref;
+
+	if (repo_config_get_string(r, config_key, &ret) < 0)
+		die(_("could not retrieve `%s`"), config_display_key);
+
+	if (!ret)
+		ret = xstrdup("master");
+
+	full_ref = xstrfmt("refs/heads/%s", ret);
+	if (check_refname_format(full_ref, 0))
+		die(_("invalid branch name: %s = %s"), config_display_key, ret);
+	free(full_ref);
+
+	return ret;
+}
+
+const char *git_default_branch_name(void)
+{
+	static char *ret;
+
+	if (!ret)
+		ret = repo_default_branch_name(the_repository);
+
+	return ret;
+}
+
 /*
  * *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 e010f8aec2..f212f8945e 100644
--- a/refs.h
+++ b/refs.h
@@ -154,6 +154,15 @@ 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 default branch name for newly-initialized repositories.
+ *
+ * The return value of `repo_default_branch_name()` is an allocated string. The
+ * return value of `git_default_branch_name()` is a singleton.
+ */
+const char *git_default_branch_name(void);
+char *repo_default_branch_name(struct repository *r);
+
 /*
  * A ref_transaction represents a collection of reference updates that
  * should succeed or fail together.
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index 61837ca25f..047197d08f 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -477,4 +477,17 @@ test_expect_success '--initial-branch' '
 	grep hello actual
 '
 
+test_expect_success 'overridden default initial branch name (config)' '
+	test_config_global init.defaultBranch nmb &&
+	git init initial-branch-config &&
+	git -C initial-branch-config symbolic-ref HEAD >actual &&
+	grep nmb actual
+'
+
+test_expect_success 'invalid default branch name' '
+	test_config_global init.defaultBranch "with space" &&
+	test_must_fail git init initial-branch-invalid 2>err &&
+	test_i18ngrep "invalid branch name" err
+'
+
 test_done
-- 
gitgitgadget
Junio C Hamano· Jun 24, 2020, 01:05 UTC · re: Don Goodman-Wilson via GitGitGadget · lore

Re: [PATCH v3 5/8] init: allow setting the default for the initial branch name via the config

"Don Goodman-Wilson via GitGitGadget" <gitgitgadget@gmail.com> writes:

Show 13 quoted lines
> diff --git a/builtin/init-db.c b/builtin/init-db.c
> index a898153901..b8634b5f35 100644
> --- a/builtin/init-db.c
> +++ b/builtin/init-db.c
> @@ -269,7 +269,7 @@ static int create_default_files(const char *template_path,
>  		char *ref;
>  
>  		if (!initial_branch)
> -			initial_branch = "master";
> +			initial_branch = git_default_branch_name();
>  
>  		ref = xstrfmt("refs/heads/%s", initial_branch);
>  		if (check_refname_format(ref, 0) < 0)

Continuing with the division of labor between this helper and its caller, I had this funny dislike of falling back here and not in the caller. But with the same idea of using "reinit", we could get rid of this "if the caller didn't give us initial_branch, fall back to..." logic from the function. The caller may do

	reinit = create_default_files(...
			initial_branch ? initial_branch : "master",
			...);
	if (reinit || initial_branch)
		warning(_(...));
	
in the previous step and then we can teach the caller to use the
configured value instead of the hardcoded "master".
That's much better ;-)
Other than that, looks good to me.
Thanks.
Johannes Schindelin· Jun 24, 2020, 12:56 UTC · re: Junio C Hamano · lore

Re: [PATCH v3 5/8] init: allow setting the default for the initial branch name via the config

Hi Junio,
On Tue, 23 Jun 2020, Junio C Hamano wrote:
Show 31 quoted lines
> "Don Goodman-Wilson via GitGitGadget" <gitgitgadget@gmail.com>
> writes:
>
> > diff --git a/builtin/init-db.c b/builtin/init-db.c
> > index a898153901..b8634b5f35 100644
> > --- a/builtin/init-db.c
> > +++ b/builtin/init-db.c
> > @@ -269,7 +269,7 @@ static int create_default_files(const char *template_path,
> >  		char *ref;
> >
> >  		if (!initial_branch)
> > -			initial_branch = "master";
> > +			initial_branch = git_default_branch_name();
> >
> >  		ref = xstrfmt("refs/heads/%s", initial_branch);
> >  		if (check_refname_format(ref, 0) < 0)
>
> Continuing with the division of labor between this helper and its
> caller, I had this funny dislike of falling back here and not in the
> caller.  But with the same idea of using "reinit", we could get rid
> of this "if the caller didn't give us initial_branch, fall back
> to..." logic from the function.  The caller may do
>
> 	reinit = create_default_files(...
> 			initial_branch ? initial_branch : "master",
> 			...);
> 	if (reinit || initial_branch)
> 		warning(_(...));
>
> in the previous step and then we can teach the caller to use the
> configured value instead of the hardcoded "master".

While that is really tempting, there is another called of `init_db()` (which calls `create_default_files()`): `builtin/clone.c`. And I do not wish to duplicate the logic there.

So I left this as-is.

Ciao, Dscho

Show 7 quoted lines
>
> That's much better ;-)
>
> Other than that, looks good to me.
>
> Thanks.
>
Junio C Hamano· Jun 24, 2020, 16:25 UTC · re: Johannes Schindelin · lore

Re: [PATCH v3 5/8] init: allow setting the default for the initial branch name via the config

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
Show 14 quoted lines
>> 	reinit = create_default_files(...
>> 			initial_branch ? initial_branch : "master",
>> 			...);
>> 	if (reinit || initial_branch)
>> 		warning(_(...));
>>
>> in the previous step and then we can teach the caller to use the
>> configured value instead of the hardcoded "master".
>
> While that is really tempting, there is another called of `init_db()`
> (which calls `create_default_files()`): `builtin/clone.c`. And I do not
> wish to duplicate the logic there.
>
> So I left this as-is.

I am still on the fence after seeing v4, but let's leave it as is. The reason why I wanted to leave the "default to" logic out of the helper was to make sure it implements little or no policy, which would leave the door open to let other callers of the helper to use their own and different default, but we can revisit when we acquire the third caller. I do not see an immediate need to make the clone's fallback default configurable separately from what init uses for the default initial branch name, and with modern servers it is doubtful that the fallback default by clone is ever used anyway.

Thanks.
Johannes Schindelin via GitGitGadget· Jun 24, 2020, 14:46 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v4 0/9] Allow overriding the default name of the default branch

A growing number of open source projects aims to avoid the branch name master due to its negative connotation. See [1] for an existing discussion on this. The links [2], [3], and [4] describe community-driven ways for users to rename their default branches or use template edits to set a new default branch name.

[1] https://lore.kernel.org/git/CAOAHyQwyXC1Z3v7BZAC+Bq6JBaM7FvBenA-1fcqeDV==apdWDg@mail.gmail.com/

[2] https://twitter.com/mislav/status/1270388510684598272

[3] https://www.hanselman.com/blog/EasilyRenameYourGitDefaultBranchFromMasterToMain.aspx

[4] https://github.com/ethomson/retarget_prs

By necessity, existing repositories require a lot of manual work to move away from that branch name, but it should be much easier for new repositories.

This patch series allows overriding the branch name being used for new repositories' main branch. This can be configured via init.defaultBranch.

The initial patch was started by newcomer Don Goodman-Wilson, as well as the bigger change that morphed into #655, where we demonstrate how to change Git's hard-coded default branch name for new repositories to main based on this here patch series, verifying the approach. Thanks for the contribution!

This series DOES NOT change the default automatically, but only provides an opt-in mechanism for interested users. The plan for that is to convert the test scripts incrementally (by introducing GIT_TEST_DEFAULT_MAIN_BRANCH_NAME , which overrides init.defaultBranch, and then converting the tricky test scripts first, one by one, using that environment variable).

Changes since v3:
 * We now avoid the phrasing "specify a specific" in the messages.
   
   
 * The git submodule patch has a better commit title now, and it also
   adjusts the documentation more completely now (thanks, Philippe!).
   
   
 * A code comment in builtin/init-db.c was updated to no longer talk about a 
   symlink when it comes to HEAD.
   
   
 * Made it the responsibility of the caller to warn about reinit &&
   initial_branch.
   
   
Changes since v2:
 * Dropped the fast-export patches, as they have been superseded by Peff's 
   jk/fast-export-anonym
   [https://github.com/gitgitgadget/git/commits/jk/fast-export-anonym].
   
   
 * Adjusted the fmt-merge-msg patch so as to not special-case master anymore
   (instead of special-casing a specific "main" branch).
   
   
 * Modified the git submodule patch so that it uses origin/HEAD instead of
   trying to look for a remote branch with the name indicated by 
   init.defaultBranch.
   
   
Changes since v1:
 * The modifications to respect GIT_TEST_DEFAULT_BRANCH_NAME have been
   backed out from this patch series, as they are only relevant once we
   start converting the test suite to accommodate for a new default main
   branch name.
   
   
 * An error message that started with an upper-case letter was downcased.
   
   
 * git_default_branch_name()'s logic was simplified by replacing an if ...
   else ... by a ternary assignment.
   
   
 * The git_default_branch_name() function was renamed to 
   git_main_branch_name() and a corresponding repo_main_branch_name() was
   introduced.
   
   
 * The "init" commit message's first paragraph now elaborates a little bit
   on the reasoning why projects want to move away from the current default
   branch name.
   
   
 * The "init" commit was split into two.
   
   
 * There are now two config settings: init.defaultBranch (defining the
   branch name to use when initializing new repositories) and 
   core.mainBranch (which is now configured by init_db(), declaring what the
   name of the main branch is in this repository).
   
   
 * The commits were re-ordered to introduce the concept of core.mainBranch 
   first because technically, this is something that we could do even
   without changing git init at all.
   
   
 * git fast-export --anonymize now always uses the ref name ref0 for the
   main branch, no matter whether it was overridden or whether the fall-back
   is in effect.
   
   
 * The code comment regarding anonymizing the main branch to ref0 in git
   fast-export --anonymize was enhanced.
   
   
 * A new patch was added to rename core.mainBranch if the main branch is
   renamed via git branch -m.
   
   
 * Added a patch that introduces support for git init
   --main-branch=<branch-name>.
   
   
 * Where possible, I added tests (although I did not try to extend test
   coverage to all changes: the send-pack.c/transport-helper.c patch only
   adds a test for the send-pack.c adjustment, for example).
Don Goodman-Wilson (1):
  init: allow setting the default for the initial branch name via the
    config
Johannes Schindelin (8):
  fmt-merge-msg: stop treating `master` specially
  send-pack/transport-helper: avoid mentioning a particular branch
  submodule: fall back to remote's HEAD for missing remote.<name>.branch
  docs: add missing diamond brackets
  init: allow specifying the initial branch name for the new repository
  clone: use configured default branch name when appropriate
  remote: use the configured default branch name when appropriate
  testsvn: respect `init.defaultBranch`
 Documentation/config/init.txt                 |  4 ++
 Documentation/git-branch.txt                  |  2 +-
 Documentation/git-clone.txt                   |  2 +-
 Documentation/git-init.txt                    |  9 ++-
 Documentation/git-submodule.txt               | 12 ++--
 Documentation/gitmodules.txt                  |  6 +-
 builtin/clone.c                               | 13 ++--
 builtin/init-db.c                             | 33 +++++++--
 builtin/submodule--helper.c                   |  2 +-
 cache.h                                       |  2 +-
 fmt-merge-msg.c                               |  5 +-
 refs.c                                        | 30 ++++++++
 refs.h                                        |  9 +++
 remote-testsvn.c                              | 10 ++-
 remote.c                                      | 14 +++-
 send-pack.c                                   |  2 +-
 t/t0001-init.sh                               | 26 +++++++
 t/t1507-rev-parse-upstream.sh                 |  2 +-
 t/t4013-diff-various.sh                       |  4 +-
 t/t4013/diff.log_--decorate=full_--all        |  2 +-
 t/t4013/diff.log_--decorate_--all             |  2 +-
 ...--patch-with-stat_--summary_master_--_dir_ |  2 +-
 t/t4013/diff.log_--patch-with-stat_master     |  2 +-
 .../diff.log_--patch-with-stat_master_--_dir_ |  2 +-
 ...ot_--cc_--patch-with-stat_--summary_master |  2 +-
 ..._--root_--patch-with-stat_--summary_master |  2 +-
 .../diff.log_--root_--patch-with-stat_master  |  2 +-
 ...root_-c_--patch-with-stat_--summary_master |  2 +-
 t/t4013/diff.log_--root_-p_master             |  2 +-
 t/t4013/diff.log_--root_master                |  2 +-
 t/t4013/diff.log_-m_-p_--first-parent_master  |  2 +-
 t/t4013/diff.log_-m_-p_master                 |  4 +-
 t/t4013/diff.log_-p_--first-parent_master     |  2 +-
 t/t4013/diff.log_-p_master                    |  2 +-
 t/t4013/diff.log_master                       |  2 +-
 t/t4013/diff.show_--first-parent_master       |  2 +-
 t/t4013/diff.show_-c_master                   |  2 +-
 t/t4013/diff.show_-m_master                   |  4 +-
 t/t4013/diff.show_master                      |  2 +-
 ...ot_--cc_--patch-with-stat_--summary_master |  2 +-
 ...root_-c_--patch-with-stat_--summary_master |  2 +-
 t/t4202-log.sh                                | 72 +++++++++----------
 t/t5528-push-default.sh                       |  6 ++
 t/t5606-clone-options.sh                      | 24 +++++++
 t/t6200-fmt-merge-msg.sh                      | 36 +++++-----
 t/t7406-submodule-update.sh                   | 16 +++++
 t/t7419-submodule-set-branch.sh               |  7 +-
 t/t7600-merge.sh                              | 14 ++--
 t/t7608-merge-messages.sh                     | 10 +--
 t/t9020-remote-svn.sh                         |  6 ++
 transport-helper.c                            |  2 +-
 51 files changed, 297 insertions(+), 131 deletions(-)
base-commit: c9c318d6bf26bcecdca5b6f31683b9d5887a83ee
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-656%2Fdscho%2Fdefault-branch-name-option-v4
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-656/dscho/default-branch-name-option-v4
Pull-Request: https://github.com/gitgitgadget/git/pull/656
Range-diff vs v3:
  1:  fffdb9944f =  1:  fffdb9944f fmt-merge-msg: stop treating `master` specially
  2:  a29943d7bb !  2:  1216de51ab send-pack/transport-helper: avoid mentioning a particular branch
     @@ send-pack.c: int send_pack(struct send_pack_args *args,
       	if (!remote_refs) {
       		fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
      -			"Perhaps you should specify a branch such as 'master'.\n");
     -+			"Perhaps you should specify a specific branch.\n");
     ++			"Perhaps you should specify a branch.\n");
       		return 0;
       	}
       	if (args->atomic && !atomic_supported)
     @@ t/t5528-push-default.sh: test_expect_success 'push from/to new branch with upstr
      +test_expect_success '"matching" fails if none match' '
      +	git init --bare empty &&
      +	test_must_fail git push empty : 2>actual &&
     -+	test_i18ngrep "Perhaps you should specify a specific branch" actual
     ++	test_i18ngrep "Perhaps you should specify a branch" actual
      +'
      +
       test_expect_success 'push ambiguously named branch with upstream, matching and simple' '
     @@ transport-helper.c: static int push_refs(struct transport *transport,
       		fprintf(stderr,
       			_("No refs in common and none specified; doing nothing.\n"
      -			  "Perhaps you should specify a branch such as 'master'.\n"));
     -+			  "Perhaps you should specify a specific branch.\n"));
     ++			  "Perhaps you should specify a branch.\n"));
       		return 0;
       	}
       
  3:  6bda69541b !  3:  54563642db submodule: use a better fall-back for missing remote.<name>.branch
     @@ Metadata
      Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
      
       ## Commit message ##
     -    submodule: use a better fall-back for missing remote.<name>.branch
     +    submodule: fall back to remote's HEAD for missing remote.<name>.branch
      
          When `remote.<name>.branch` is not configured, `git submodule update`
          currently falls back to using the branch name `master`. A much better
     -    idea, however, is to use `HEAD`: on all Git servers running reasonably
     -    recent Git versions, the symref `HEAD` points to the main branch.
     +    idea, however, is to use the remote `HEAD`: on all Git servers running
     +    reasonably recent Git versions, the symref `HEAD` points to the main
     +    branch.
      
          Note: t7419 demonstrates that there _might_ be use cases out there that
          _expect_ `git submodule update --remote` to update submodules to the
     @@ Commit message
          there is a slight possibility that this might cause regressions in
          obscure setups.
      
     +    Even so, it should be okay to fix this behavior without anything like a
     +    longer transition period:
     +
     +    - The `git submodule update --remote` command is not really common.
     +
     +    - Current Git's behavior when running this command is outright
     +      confusing, unless the remote repository's current branch _is_ `master`
     +      (in which case the proposed behavior matches the old behavior).
     +
     +    - If a user encounters a regression due to the changed behavior, the fix
     +      is actually trivial: setting `submodule.<name>.branch` to `master`
     +      will reinstate the old behavior.
     +
     +    Helped-by: Philippe Blain <levraiphilippeblain@gmail.com>
          Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
      
       ## Documentation/git-submodule.txt ##
     +@@ Documentation/git-submodule.txt: set-branch (-d|--default) [--] <path>::
     + 	Sets the default remote tracking branch for the submodule. The
     + 	`--branch` option allows the remote branch to be specified. The
     + 	`--default` option removes the submodule.<name>.branch configuration
     +-	key, which causes the tracking branch to default to 'master'.
     ++	key, which causes the tracking branch to default to the remote 'HEAD'.
     + 
     + set-url [--] <path> <newurl>::
     + 	Sets the URL of the specified submodule to <newurl>. Then, it will
      @@ Documentation/git-submodule.txt: OPTIONS
       	`.gitmodules` for `update --remote`.  A special value of `.` is used to
       	indicate that the name of the branch in the submodule should be the
       	same name as the current branch in the current repository.  If the
      -	option is not specified, it defaults to 'master'.
     -+	option is not specified, it defaults to 'HEAD'.
     ++	option is not specified, it defaults to the remote 'HEAD'.
       
       -f::
       --force::
     @@ Documentation/git-submodule.txt: OPTIONS
       	status of the submodule's remote-tracking branch.  The remote used
       	is branch's remote (`branch.<name>.remote`), defaulting to `origin`.
      -	The remote branch used defaults to `master`, but the branch name may
     -+	The remote branch used defaults to `HEAD`, but the branch name may
     - 	be overridden by setting the `submodule.<name>.branch` option in
     - 	either `.gitmodules` or `.git/config` (with `.git/config` taking
     - 	precedence).
     +-	be overridden by setting the `submodule.<name>.branch` option in
     +-	either `.gitmodules` or `.git/config` (with `.git/config` taking
     +-	precedence).
     ++	The remote branch used defaults to the remote `HEAD`, but the branch
     ++	name may be overridden by setting the `submodule.<name>.branch`
     ++	option in either `.gitmodules` or `.git/config` (with `.git/config`
     ++	taking precedence).
     + +
     + This works for any of the supported update procedures (`--checkout`,
     + `--rebase`, etc.).  The only change is the source of the target SHA-1.
     +
     + ## Documentation/gitmodules.txt ##
     +@@ Documentation/gitmodules.txt: submodule.<name>.update::
     + 
     + submodule.<name>.branch::
     + 	A remote branch name for tracking updates in the upstream submodule.
     +-	If the option is not specified, it defaults to 'master'.  A special
     +-	value of `.` is used to indicate that the name of the branch in the
     +-	submodule should be the same name as the current branch in the
     ++	If the option is not specified, it defaults to the remote 'HEAD'.
     ++	A special value of `.` is used to indicate that the name of the branch
     ++	in the submodule should be the same name as the current branch in the
     + 	current repository.  See the `--remote` documentation in
     + 	linkgit:git-submodule[1] for details.
     + 
      
       ## builtin/submodule--helper.c ##
      @@ builtin/submodule--helper.c: static const char *remote_submodule_branch(const char *path)
  -:  ---------- >  4:  1d723d35ed docs: add missing diamond brackets
  4:  e8a6587c1a !  5:  9edd4fd3b2 init: allow specifying the initial branch name for the new repository
     @@ Documentation/git-init.txt
      @@ Documentation/git-init.txt: SYNOPSIS
       [verse]
       'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
     - 	  [--separate-git-dir <git dir>] [--object-format=<format]
     + 	  [--separate-git-dir <git dir>] [--object-format=<format>]
      +	  [-b <branch-name> | --initial-branch=<branch-name>]
       	  [--shared[=<permissions>]] [directory]
       
     @@ builtin/init-db.c: static int create_default_files(const char *template_path,
       	/*
      -	 * Create the default symlink from ".git/HEAD" to the "master"
      -	 * branch, if it does not exist yet.
     -+	 * Create the default symlink from ".git/HEAD" to the default
     -+	 * branch name, if it does not exist yet.
     ++	 * Point the HEAD symref to the initial branch with if HEAD does
     ++	 * not yet exist.
       	 */
       	path = git_path_buf(&buf, "HEAD");
       	reinit = (!access(path, R_OK)
     @@ builtin/init-db.c: static int create_default_files(const char *template_path,
      +
      +		if (create_symref("HEAD", ref, NULL) < 0)
       			exit(1);
     --	}
      +		free(ref);
     -+	} else if (initial_branch)
     -+		warning(_("re-init: ignoring --initial-branch=%s"),
     -+			initial_branch);
     + 	}
       
       	initialize_repository_version(fmt->hash_algo);
     - 
      @@ builtin/init-db.c: static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash
       }
       
     @@ builtin/init-db.c: int init_db(const char *git_dir, const char *real_git_dir,
      -	reinit = create_default_files(template_dir, original_git_dir, &repo_fmt);
      +	reinit = create_default_files(template_dir, original_git_dir,
      +				      initial_branch, &repo_fmt);
     ++	if (reinit && initial_branch)
     ++		warning(_("re-init: ignored --initial-branch=%s"),
     ++			initial_branch);
       
       	create_object_directory();
       
     @@ t/t0001-init.sh: test_expect_success MINGW 'redirect std handles' '
      +
      +	: re-initializing should not change the branch name &&
      +	git init --initial-branch=ignore initial-branch-option 2>err &&
     -+	test_i18ngrep "ignoring --initial-branch" err &&
     ++	test_i18ngrep "ignored --initial-branch" err &&
      +	git -C initial-branch-option symbolic-ref HEAD >actual &&
      +	grep hello actual
      +'
  5:  a500e0f214 =  6:  7747eaa57d init: allow setting the default for the initial branch name via the config
  6:  c0d74cedd1 =  7:  1cff7705e4 clone: use configured default branch name when appropriate
  7:  00a1b281e5 !  8:  0a7c0bdfda remote: use the configured default branch name when appropriate
     @@ remote.c: static void read_branches_file(struct remote *remote)
       	/*
       	 * The branches file would have URL and optionally
      -	 * #branch specified.  The "master" (or specified) branch is
     -+	 * #branch specified.  The main (or specified) branch is
     ++	 * #branch specified.  The default (or specified) branch is
       	 * fetched and stored in the local branch matching the
       	 * remote name.
       	 */
  8:  1aa0e63785 =  9:  6c72abf677 testsvn: respect `init.defaultBranch`
-- 
gitgitgadget
Johannes Schindelin via GitGitGadget· Jun 24, 2020, 14:46 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v4 2/9] send-pack/transport-helper: avoid mentioning a particular branch

From: Johannes Schindelin <johannes.schindelin@gmx.de>

When trying to push all matching branches, but none match, we offer a message suggesting to push the `master` branch.

However, we want to step away from making that branch any more special than any other branch, so let's reword that message to mention no branch in particular.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 send-pack.c             | 2 +-
 t/t5528-push-default.sh | 6 ++++++
 transport-helper.c      | 2 +-
 3 files changed, 8 insertions(+), 2 deletions(-)
Show changes to 3 files +8 −2

send-pack.c, t/t5528-push-default.sh, transport-helper.c

diff --git a/send-pack.c b/send-pack.c
index 0abee22283..19eb9b04e4 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -406,7 +406,7 @@ int send_pack(struct send_pack_args *args,
 
 	if (!remote_refs) {
 		fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
-			"Perhaps you should specify a branch such as 'master'.\n");
+			"Perhaps you should specify a branch.\n");
 		return 0;
 	}
 	if (args->atomic && !atomic_supported)
diff --git a/t/t5528-push-default.sh b/t/t5528-push-default.sh
index 4d1e0c363e..f0a287d97d 100755
--- a/t/t5528-push-default.sh
+++ b/t/t5528-push-default.sh
@@ -98,6 +98,12 @@ test_expect_success 'push from/to new branch with upstream, matching and simple'
 	test_push_failure upstream
 '
 
+test_expect_success '"matching" fails if none match' '
+	git init --bare empty &&
+	test_must_fail git push empty : 2>actual &&
+	test_i18ngrep "Perhaps you should specify a branch" actual
+'
+
 test_expect_success 'push ambiguously named branch with upstream, matching and simple' '
 	git checkout -b ambiguous &&
 	test_config branch.ambiguous.remote parent1 &&
diff --git a/transport-helper.c b/transport-helper.c
index a46afcb69d..8a711cda29 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -1046,7 +1046,7 @@ static int push_refs(struct transport *transport,
 	if (!remote_refs) {
 		fprintf(stderr,
 			_("No refs in common and none specified; doing nothing.\n"
-			  "Perhaps you should specify a branch such as 'master'.\n"));
+			  "Perhaps you should specify a branch.\n"));
 		return 0;
 	}
 
-- 
gitgitgadget
Johannes Schindelin via GitGitGadget· Jun 24, 2020, 14:46 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v4 7/9] clone: use configured default branch name when appropriate

From: Johannes Schindelin <johannes.schindelin@gmx.de>

When cloning a repository without any branches, Git chooses a default branch name for the as-yet unborn branch.

As part of the implicit initialization of the local repository, Git just learned to respect `init.defaultBranch` to choose a different initial branch name. We now really want that branch name to be used as a fall-back.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 Documentation/config/init.txt |  4 ++--
 builtin/clone.c               | 10 +++++++---
 t/t5606-clone-options.sh      | 15 +++++++++++++++
 3 files changed, 24 insertions(+), 5 deletions(-)
Show changes to 3 files +24 −5

Documentation/config/init.txt, builtin/clone.c, t/t5606-clone-options.sh

diff --git a/Documentation/config/init.txt b/Documentation/config/init.txt
index 6ae4a38416..dc77f8c844 100644
--- a/Documentation/config/init.txt
+++ b/Documentation/config/init.txt
@@ -3,5 +3,5 @@ init.templateDir::
 	(See the "TEMPLATE DIRECTORY" section of linkgit:git-init[1].)
 
 init.defaultBranch::
-	Allows overriding the default branch name when initializing
-	a new repository.
+	Allows overriding the default branch name e.g. when initializing
+	a new repository or when cloning an empty repository.
diff --git a/builtin/clone.c b/builtin/clone.c
index b751bdf13e..9a3f91b268 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1267,9 +1267,13 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		remote_head_points_at = NULL;
 		remote_head = NULL;
 		option_no_checkout = 1;
-		if (!option_bare)
-			install_branch_config(0, "master", option_origin,
-					      "refs/heads/master");
+		if (!option_bare) {
+			const char *branch = git_default_branch_name();
+			char *ref = xstrfmt("refs/heads/%s", branch);
+
+			install_branch_config(0, branch, option_origin, ref);
+			free(ref);
+		}
 	}
 
 	write_refspec_config(src_ref_prefix, our_head_points_at,
diff --git a/t/t5606-clone-options.sh b/t/t5606-clone-options.sh
index 9e24ec88e6..286bfd93ac 100755
--- a/t/t5606-clone-options.sh
+++ b/t/t5606-clone-options.sh
@@ -35,4 +35,19 @@ test_expect_success 'redirected clone -v does show progress' '
 
 '
 
+test_expect_success 'chooses correct default initial branch name' '
+	git init --bare empty &&
+	git -c init.defaultBranch=up clone empty whats-up &&
+	test refs/heads/up = $(git -C whats-up symbolic-ref HEAD) &&
+	test refs/heads/up = $(git -C whats-up config branch.up.merge)
+'
+
+test_expect_success 'guesses initial branch name correctly' '
+	git init --initial-branch=guess initial-branch &&
+	test_commit -C initial-branch no-spoilers &&
+	git -C initial-branch branch abc guess &&
+	git clone initial-branch is-it &&
+	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD)
+'
+
 test_done
-- 
gitgitgadget
Johannes Schindelin via GitGitGadget· Jun 24, 2020, 14:46 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v4 9/9] testsvn: respect `init.defaultBranch`

From: Johannes Schindelin <johannes.schindelin@gmx.de>

The default name of the initial branch in new repositories can now be configured. The `testsvn` remote helper translates the remote Subversion repository's branch name `trunk` to the hard-coded name `master`. Clearly, the intention was to make the name align with Git's defaults.

So while we are not talking about a newly-created repository in the `testsvn` context, it is a newly-created _Git_ repository, si it _still_ makes sense to use the overridden default name for the initial branch whenever users configured it.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 remote-testsvn.c      | 10 +++++++---
 t/t9020-remote-svn.sh |  6 ++++++
 2 files changed, 13 insertions(+), 3 deletions(-)
Show changes to 2 files +13 −3

remote-testsvn.c, t/t9020-remote-svn.sh

diff --git a/remote-testsvn.c b/remote-testsvn.c
index 3af708c5b6..cde39b94fb 100644
--- a/remote-testsvn.c
+++ b/remote-testsvn.c
@@ -13,7 +13,7 @@
 static const char *url;
 static int dump_from_file;
 static const char *private_ref;
-static const char *remote_ref = "refs/heads/master";
+static char *remote_ref;
 static const char *marksfilename, *notes_ref;
 struct rev_note { unsigned int rev_nr; };
 
@@ -286,7 +286,7 @@ int cmd_main(int argc, const char **argv)
 			private_ref_sb = STRBUF_INIT, marksfilename_sb = STRBUF_INIT,
 			notes_ref_sb = STRBUF_INIT;
 	static struct remote *remote;
-	const char *url_in;
+	const char *url_in, *remote_ref_short;
 
 	setup_git_directory();
 	if (argc < 2 || argc > 3) {
@@ -294,6 +294,9 @@ int cmd_main(int argc, const char **argv)
 		return 1;
 	}
 
+	remote_ref_short = git_default_branch_name();
+	remote_ref = xstrfmt("refs/heads/%s", remote_ref_short);
+
 	remote = remote_get(argv[1]);
 	url_in = (argc == 3) ? argv[2] : remote->url[0];
 
@@ -306,7 +309,8 @@ int cmd_main(int argc, const char **argv)
 		url = url_sb.buf;
 	}
 
-	strbuf_addf(&private_ref_sb, "refs/svn/%s/master", remote->name);
+	strbuf_addf(&private_ref_sb, "refs/svn/%s/%s",
+		    remote->name, remote_ref_short);
 	private_ref = private_ref_sb.buf;
 
 	strbuf_addf(&notes_ref_sb, "refs/notes/%s/revs", remote->name);
diff --git a/t/t9020-remote-svn.sh b/t/t9020-remote-svn.sh
index 9fcfa969a9..754c4a3284 100755
--- a/t/t9020-remote-svn.sh
+++ b/t/t9020-remote-svn.sh
@@ -84,6 +84,12 @@ test_expect_success REMOTE_SVN 'incremental imports must lead to the same head'
 	test_cmp master.good .git/refs/remotes/svnsim/master
 '
 
+test_expect_success REMOTE_SVN 'respects configured default initial branch' '
+	git -c init.defaultBranch=trunk remote add -f trunk \
+		"testsvn::file://$TEST_DIRECTORY/t9154/svn.dump" &&
+	git rev-parse --verify refs/remotes/trunk/trunk
+'
+
 test_debug 'git branch -a'
 
 test_done
-- 
gitgitgadget
Johannes Schindelin via GitGitGadget· Jun 24, 2020, 14:46 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v4 8/9] remote: use the configured default branch name when appropriate

From: Johannes Schindelin <johannes.schindelin@gmx.de>

When guessing the default branch name of a remote, and there are no refs to guess from, we want to go with the preference specified by the user for the fall-back, i.e. the default name to be used for the initial branch of new repositories (because as far as the user is concerned, a remote that has no branches yet is a new repository).

At the same time, when talking to an older Git server that does not report a symref for `HEAD` (but instead reports a commit hash), let's try to guess the configured default branch name first. If it does not match the reported commit hash, let's fall back to `master` as before.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 remote.c                 | 14 +++++++++++---
 t/t5606-clone-options.sh | 11 ++++++++++-
 2 files changed, 21 insertions(+), 4 deletions(-)
Show changes to 2 files +21 −4

remote.c, t/t5606-clone-options.sh

diff --git a/remote.c b/remote.c
index 534c6426f1..bc46413e6a 100644
--- a/remote.c
+++ b/remote.c
@@ -276,7 +276,7 @@ static void read_branches_file(struct remote *remote)
 
 	/*
 	 * The branches file would have URL and optionally
-	 * #branch specified.  The "master" (or specified) branch is
+	 * #branch specified.  The default (or specified) branch is
 	 * fetched and stored in the local branch matching the
 	 * remote name.
 	 */
@@ -284,7 +284,7 @@ static void read_branches_file(struct remote *remote)
 	if (frag)
 		*(frag++) = '\0';
 	else
-		frag = "master";
+		frag = (char *)git_default_branch_name();
 
 	add_url_alias(remote, strbuf_detach(&buf, NULL));
 	strbuf_addf(&buf, "refs/heads/%s:refs/heads/%s",
@@ -2097,8 +2097,16 @@ struct ref *guess_remote_head(const struct ref *head,
 	if (head->symref)
 		return copy_ref(find_ref_by_name(refs, head->symref));
 
-	/* If refs/heads/master could be right, it is. */
+	/* If a remote branch exists with the default branch name, let's use it. */
 	if (!all) {
+		char *ref = xstrfmt("refs/heads/%s", git_default_branch_name());
+
+		r = find_ref_by_name(refs, ref);
+		free(ref);
+		if (r && oideq(&r->old_oid, &head->old_oid))
+			return copy_ref(r);
+
+		/* Fall back to the hard-coded historical default */
 		r = find_ref_by_name(refs, "refs/heads/master");
 		if (r && oideq(&r->old_oid, &head->old_oid))
 			return copy_ref(r);
diff --git a/t/t5606-clone-options.sh b/t/t5606-clone-options.sh
index 286bfd93ac..e69427f881 100755
--- a/t/t5606-clone-options.sh
+++ b/t/t5606-clone-options.sh
@@ -47,7 +47,16 @@ test_expect_success 'guesses initial branch name correctly' '
 	test_commit -C initial-branch no-spoilers &&
 	git -C initial-branch branch abc guess &&
 	git clone initial-branch is-it &&
-	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD)
+	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD) &&
+
+	git -c init.defaultBranch=none init --bare no-head &&
+	git -C initial-branch push ../no-head guess abc &&
+	git clone no-head is-it2 &&
+	test_must_fail git -C is-it2 symbolic-ref refs/remotes/origin/HEAD &&
+	git -C no-head update-ref --no-deref HEAD refs/heads/guess &&
+	git -c init.defaultBranch=guess clone no-head is-it3 &&
+	test refs/remotes/origin/guess = \
+		$(git -C is-it3 symbolic-ref refs/remotes/origin/HEAD)
 '
 
 test_done
-- 
gitgitgadget
Johannes Schindelin via GitGitGadget· Jun 24, 2020, 14:46 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v4 4/9] docs: add missing diamond brackets

From: Johannes Schindelin <johannes.schindelin@gmx.de>

There were a couple of instances in our manual pages that had an opening diamond bracket without a corresponding closing one.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 Documentation/git-branch.txt | 2 +-
 Documentation/git-clone.txt  | 2 +-
 Documentation/git-init.txt   | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)
Show changes to 3 files +3 −2

Documentation/git-branch.txt, Documentation/git-clone.txt, Documentation/git-init.txt

diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index 135206ff4a..03c0824d52 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -12,7 +12,7 @@ SYNOPSIS
 	[-v [--abbrev=<length> | --no-abbrev]]
 	[--column[=<options>] | --no-column] [--sort=<key>]
 	[(--merged | --no-merged) [<commit>]]
-	[--contains [<commit]] [--no-contains [<commit>]]
+	[--contains [<commit>]] [--no-contains [<commit>]]
 	[--points-at <object>] [--format=<format>]
 	[(-r | --remotes) | (-a | --all)]
 	[--list] [<pattern>...]
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index 08d6045c4a..c898310099 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -259,7 +259,7 @@ maintain a branch with no references other than a single cloned
 branch. This is useful e.g. to maintain minimal clones of the default
 branch of some repository for search indexing.
 
---recurse-submodules[=<pathspec]::
+--recurse-submodules[=<pathspec>]::
 	After the clone is created, initialize and clone submodules
 	within based on the provided pathspec.  If no pathspec is
 	provided, all submodules are initialized and cloned.
diff --git a/Documentation/git-init.txt b/Documentation/git-init.txt
index adc6adfd38..f9467cc6a4 100644
--- a/Documentation/git-init.txt
+++ b/Documentation/git-init.txt
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
-	  [--separate-git-dir <git dir>] [--object-format=<format]
+	  [--separate-git-dir <git dir>] [--object-format=<format>]
 	  [--shared[=<permissions>]] [directory]
 
 
-- 
gitgitgadget
Johannes Schindelin via GitGitGadget· Jun 24, 2020, 14:46 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v4 3/9] submodule: fall back to remote's HEAD for missing remote.<name>.branch

From: Johannes Schindelin <johannes.schindelin@gmx.de>

When `remote.<name>.branch` is not configured, `git submodule update` currently falls back to using the branch name `master`. A much better idea, however, is to use the remote `HEAD`: on all Git servers running reasonably recent Git versions, the symref `HEAD` points to the main branch.

Note: t7419 demonstrates that there _might_ be use cases out there that
_expect_ `git submodule update --remote` to update submodules to the
remote `master` branch even if the remote `HEAD` points to another
branch. Arguably, this patch makes the behavior more intuitive, but
there is a slight possibility that this might cause regressions in
obscure setups.

Even so, it should be okay to fix this behavior without anything like a longer transition period:

- The `git submodule update --remote` command is not really common.
- Current Git's behavior when running this command is outright
  confusing, unless the remote repository's current branch _is_ `master`
  (in which case the proposed behavior matches the old behavior).
- If a user encounters a regression due to the changed behavior, the fix
  is actually trivial: setting `submodule.<name>.branch` to `master`
  will reinstate the old behavior.
Helped-by: Philippe Blain <levraiphilippeblain@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 Documentation/git-submodule.txt | 12 ++++++------
 Documentation/gitmodules.txt    |  6 +++---
 builtin/submodule--helper.c     |  2 +-
 t/t7406-submodule-update.sh     | 16 ++++++++++++++++
 t/t7419-submodule-set-branch.sh |  7 +++++--
 5 files changed, 31 insertions(+), 12 deletions(-)
Show changes to 5 files +31 −12

Documentation/git-submodule.txt, Documentation/gitmodules.txt, builtin/submodule--helper.c, t/t7406-submodule-update.sh, t/t7419-submodule-set-branch.sh

diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index c9ed2bf3d5..7e5f995f77 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -183,7 +183,7 @@ set-branch (-d|--default) [--] <path>::
 	Sets the default remote tracking branch for the submodule. The
 	`--branch` option allows the remote branch to be specified. The
 	`--default` option removes the submodule.<name>.branch configuration
-	key, which causes the tracking branch to default to 'master'.
+	key, which causes the tracking branch to default to the remote 'HEAD'.
 
 set-url [--] <path> <newurl>::
 	Sets the URL of the specified submodule to <newurl>. Then, it will
@@ -284,7 +284,7 @@ OPTIONS
 	`.gitmodules` for `update --remote`.  A special value of `.` is used to
 	indicate that the name of the branch in the submodule should be the
 	same name as the current branch in the current repository.  If the
-	option is not specified, it defaults to 'master'.
+	option is not specified, it defaults to the remote 'HEAD'.
 
 -f::
 --force::
@@ -322,10 +322,10 @@ OPTIONS
 	the superproject's recorded SHA-1 to update the submodule, use the
 	status of the submodule's remote-tracking branch.  The remote used
 	is branch's remote (`branch.<name>.remote`), defaulting to `origin`.
-	The remote branch used defaults to `master`, but the branch name may
-	be overridden by setting the `submodule.<name>.branch` option in
-	either `.gitmodules` or `.git/config` (with `.git/config` taking
-	precedence).
+	The remote branch used defaults to the remote `HEAD`, but the branch
+	name may be overridden by setting the `submodule.<name>.branch`
+	option in either `.gitmodules` or `.git/config` (with `.git/config`
+	taking precedence).
 +
 This works for any of the supported update procedures (`--checkout`,
 `--rebase`, etc.).  The only change is the source of the target SHA-1.
diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt
index 67275fd187..539b4e1997 100644
--- a/Documentation/gitmodules.txt
+++ b/Documentation/gitmodules.txt
@@ -49,9 +49,9 @@ submodule.<name>.update::
 
 submodule.<name>.branch::
 	A remote branch name for tracking updates in the upstream submodule.
-	If the option is not specified, it defaults to 'master'.  A special
-	value of `.` is used to indicate that the name of the branch in the
-	submodule should be the same name as the current branch in the
+	If the option is not specified, it defaults to the remote 'HEAD'.
+	A special value of `.` is used to indicate that the name of the branch
+	in the submodule should be the same name as the current branch in the
 	current repository.  See the `--remote` documentation in
 	linkgit:git-submodule[1] for details.
 
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 46c03d2a12..f55f7b7704 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1981,7 +1981,7 @@ static const char *remote_submodule_branch(const char *path)
 	free(key);
 
 	if (!branch)
-		return "master";
+		return "HEAD";
 
 	if (!strcmp(branch, ".")) {
 		const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index 4fb447a143..aa19ff3a2e 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -70,6 +70,22 @@ test_expect_success 'setup a submodule tree' '
 	)
 '
 
+test_expect_success 'update --remote falls back to using HEAD' '
+	test_create_repo main-branch-submodule &&
+	test_commit -C main-branch-submodule initial &&
+
+	test_create_repo main-branch &&
+	git -C main-branch submodule add ../main-branch-submodule &&
+	git -C main-branch commit -m add-submodule &&
+
+	git -C main-branch-submodule switch -c hello &&
+	test_commit -C main-branch-submodule world &&
+
+	git clone --recursive main-branch main-branch-clone &&
+	git -C main-branch-clone submodule update --remote main-branch-submodule &&
+	test_path_exists main-branch-clone/main-branch-submodule/world.t
+'
+
 test_expect_success 'submodule update detaching the HEAD ' '
 	(cd super/submodule &&
 	 git reset --hard HEAD~1
diff --git a/t/t7419-submodule-set-branch.sh b/t/t7419-submodule-set-branch.sh
index fd25f786a3..3b925c302f 100755
--- a/t/t7419-submodule-set-branch.sh
+++ b/t/t7419-submodule-set-branch.sh
@@ -52,12 +52,13 @@ test_expect_success 'test submodule set-branch --branch' '
 '
 
 test_expect_success 'test submodule set-branch --default' '
+	test_commit -C submodule c &&
 	(cd super &&
 		git submodule set-branch --default submodule &&
 		! grep branch .gitmodules &&
 		git submodule update --remote &&
 		cat <<-\EOF >expect &&
-		a
+		c
 		EOF
 		git -C submodule show -s --pretty=%s >actual &&
 		test_cmp expect actual
@@ -65,6 +66,7 @@ test_expect_success 'test submodule set-branch --default' '
 '
 
 test_expect_success 'test submodule set-branch -b' '
+	test_commit -C submodule b &&
 	(cd super &&
 		git submodule set-branch -b topic submodule &&
 		grep "branch = topic" .gitmodules &&
@@ -78,12 +80,13 @@ test_expect_success 'test submodule set-branch -b' '
 '
 
 test_expect_success 'test submodule set-branch -d' '
+	test_commit -C submodule d &&
 	(cd super &&
 		git submodule set-branch -d submodule &&
 		! grep branch .gitmodules &&
 		git submodule update --remote &&
 		cat <<-\EOF >expect &&
-		a
+		d
 		EOF
 		git -C submodule show -s --pretty=%s >actual &&
 		test_cmp expect actual
-- 
gitgitgadget
Junio C Hamano· Jun 24, 2020, 16:17 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH v4 3/9] submodule: fall back to remote's HEAD for missing remote.<name>.branch

"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com> writes:

Show 16 quoted lines
> Even so, it should be okay to fix this behavior without anything like a
> longer transition period:
>
> - The `git submodule update --remote` command is not really common.
>
> - Current Git's behavior when running this command is outright
>   confusing, unless the remote repository's current branch _is_ `master`
>   (in which case the proposed behavior matches the old behavior).
>
> - If a user encounters a regression due to the changed behavior, the fix
>   is actually trivial: setting `submodule.<name>.branch` to `master`
>   will reinstate the old behavior.
>
> Helped-by: Philippe Blain <levraiphilippeblain@gmail.com>
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> ---
Well explained.  Thanks.
Johannes Schindelin via GitGitGadget· Jun 24, 2020, 14:46 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v4 1/9] fmt-merge-msg: stop treating `master` specially

From: Johannes Schindelin <johannes.schindelin@gmx.de>

In the context of many projects renaming their primary branch names away from `master`, Git wants to stop treating the `master` branch specially.

Let's start with `git fmt-merge-msg`.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 fmt-merge-msg.c                               |  5 +-
 t/t1507-rev-parse-upstream.sh                 |  2 +-
 t/t4013-diff-various.sh                       |  4 +-
 t/t4013/diff.log_--decorate=full_--all        |  2 +-
 t/t4013/diff.log_--decorate_--all             |  2 +-
 ...--patch-with-stat_--summary_master_--_dir_ |  2 +-
 t/t4013/diff.log_--patch-with-stat_master     |  2 +-
 .../diff.log_--patch-with-stat_master_--_dir_ |  2 +-
 ...ot_--cc_--patch-with-stat_--summary_master |  2 +-
 ..._--root_--patch-with-stat_--summary_master |  2 +-
 .../diff.log_--root_--patch-with-stat_master  |  2 +-
 ...root_-c_--patch-with-stat_--summary_master |  2 +-
 t/t4013/diff.log_--root_-p_master             |  2 +-
 t/t4013/diff.log_--root_master                |  2 +-
 t/t4013/diff.log_-m_-p_--first-parent_master  |  2 +-
 t/t4013/diff.log_-m_-p_master                 |  4 +-
 t/t4013/diff.log_-p_--first-parent_master     |  2 +-
 t/t4013/diff.log_-p_master                    |  2 +-
 t/t4013/diff.log_master                       |  2 +-
 t/t4013/diff.show_--first-parent_master       |  2 +-
 t/t4013/diff.show_-c_master                   |  2 +-
 t/t4013/diff.show_-m_master                   |  4 +-
 t/t4013/diff.show_master                      |  2 +-
 ...ot_--cc_--patch-with-stat_--summary_master |  2 +-
 ...root_-c_--patch-with-stat_--summary_master |  2 +-
 t/t4202-log.sh                                | 72 +++++++++----------
 t/t6200-fmt-merge-msg.sh                      | 36 +++++-----
 t/t7600-merge.sh                              | 14 ++--
 t/t7608-merge-messages.sh                     | 10 +--
 29 files changed, 94 insertions(+), 97 deletions(-)
Show changes to 29 files +94 −97

fmt-merge-msg.c, t/t1507-rev-parse-upstream.sh, t/t4013-diff-various.sh, t/t4013/diff.log_--decorate=full_--all, t/t4013/diff.log_--decorate_--all, t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_, t/t4013/diff.log_--patch-with-stat_master, t/t4013/diff.log_--patch-with-stat_master_--_dir_, t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master, t/t4013/diff.log_--root_--patch-with-stat_--summary_master, t/t4013/diff.log_--root_--patch-with-stat_master, t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master, t/t4013/diff.log_--root_-p_master, t/t4013/diff.log_--root_master, t/t4013/diff.log_-m_-p_--first-parent_master, t/t4013/diff.log_-m_-p_master, t/t4013/diff.log_-p_--first-parent_master, t/t4013/diff.log_-p_master, t/t4013/diff.log_master, t/t4013/diff.show_--first-parent_master, t/t4013/diff.show_-c_master, t/t4013/diff.show_-m_master, t/t4013/diff.show_master, t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master, t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master, t/t4202-log.sh, t/t6200-fmt-merge-msg.sh, t/t7600-merge.sh, t/t7608-merge-messages.sh

diff --git a/fmt-merge-msg.c b/fmt-merge-msg.c
index 72d32bd73b..cfb8ff2f33 100644
--- a/fmt-merge-msg.c
+++ b/fmt-merge-msg.c
@@ -451,10 +451,7 @@ static void fmt_merge_msg_title(struct strbuf *out,
 			strbuf_addf(out, " of %s", srcs.items[i].string);
 	}
 
-	if (!strcmp("master", current_branch))
-		strbuf_addch(out, '\n');
-	else
-		strbuf_addf(out, " into %s\n", current_branch);
+	strbuf_addf(out, " into %s\n", current_branch);
 }
 
 static void fmt_tag_signature(struct strbuf *tagbuf,
diff --git a/t/t1507-rev-parse-upstream.sh b/t/t1507-rev-parse-upstream.sh
index dfc0d96d8a..f213aa8053 100755
--- a/t/t1507-rev-parse-upstream.sh
+++ b/t/t1507-rev-parse-upstream.sh
@@ -137,7 +137,7 @@ test_expect_success 'merge my-side@{u} records the correct name' '
 	git branch -t new my-side@{u} &&
 	git merge -s ours new@{u} &&
 	git show -s --pretty=tformat:%s >actual &&
-	echo "Merge remote-tracking branch ${SQ}origin/side${SQ}" >expect &&
+	echo "Merge remote-tracking branch ${SQ}origin/side${SQ} into master" >expect &&
 	test_cmp expect actual
 )
 '
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index 3f60f7d96c..43267d6024 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -117,12 +117,12 @@ test_expect_success setup '
 
 : <<\EOF
 ! [initial] Initial
- * [master] Merge branch 'side'
+ * [master] Merge branch 'side' into master
   ! [rearrange] Rearranged lines in dir/sub
    ! [side] Side
 ----
   +  [rearrange] Rearranged lines in dir/sub
- -   [master] Merge branch 'side'
+ -   [master] Merge branch 'side' into master
  * + [side] Side
  *   [master^] Third
  *   [master~2] Second
diff --git a/t/t4013/diff.log_--decorate=full_--all b/t/t4013/diff.log_--decorate=full_--all
index 3f9b872ece..c56783b985 100644
--- a/t/t4013/diff.log_--decorate=full_--all
+++ b/t/t4013/diff.log_--decorate=full_--all
@@ -31,7 +31,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (refs/heads/side)
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--decorate_--all b/t/t4013/diff.log_--decorate_--all
index f5e20e1e14..1cbdc038f4 100644
--- a/t/t4013/diff.log_--decorate_--all
+++ b/t/t4013/diff.log_--decorate_--all
@@ -31,7 +31,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (side)
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_
index a18f1472a9..f5b1b6516b 100644
--- a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_
+++ b/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--patch-with-stat_master b/t/t4013/diff.log_--patch-with-stat_master
index ae425c4672..af23803cdc 100644
--- a/t/t4013/diff.log_--patch-with-stat_master
+++ b/t/t4013/diff.log_--patch-with-stat_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--patch-with-stat_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_master_--_dir_
index d5207cadf4..814098fbf8 100644
--- a/t/t4013/diff.log_--patch-with-stat_master_--_dir_
+++ b/t/t4013/diff.log_--patch-with-stat_master_--_dir_
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master
index 0fc1e8cd71..b927fe4a98 100644
--- a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
  dir/sub | 2 ++
  file0   | 3 +++
diff --git a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_--patch-with-stat_--summary_master
index dffc09dde9..6db3cea329 100644
--- a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.log_--root_--patch-with-stat_--summary_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--root_--patch-with-stat_master b/t/t4013/diff.log_--root_--patch-with-stat_master
index 55aa98012d..98e9c320c3 100644
--- a/t/t4013/diff.log_--root_--patch-with-stat_master
+++ b/t/t4013/diff.log_--root_--patch-with-stat_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master
index 019d85f7de..b61b1117ae 100644
--- a/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
  dir/sub | 2 ++
  file0   | 3 +++
diff --git a/t/t4013/diff.log_--root_-p_master b/t/t4013/diff.log_--root_-p_master
index b42c334439..345bd9e8a9 100644
--- a/t/t4013/diff.log_--root_-p_master
+++ b/t/t4013/diff.log_--root_-p_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--root_master b/t/t4013/diff.log_--root_master
index e8f46159da..db56b1fe6b 100644
--- a/t/t4013/diff.log_--root_master
+++ b/t/t4013/diff.log_--root_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-m_-p_--first-parent_master b/t/t4013/diff.log_-m_-p_--first-parent_master
index 7a0073f529..bcadb50e26 100644
--- a/t/t4013/diff.log_-m_-p_--first-parent_master
+++ b/t/t4013/diff.log_-m_-p_--first-parent_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 diff --git a/dir/sub b/dir/sub
 index cead32e..992913c 100644
diff --git a/t/t4013/diff.log_-m_-p_master b/t/t4013/diff.log_-m_-p_master
index 9ca62a01ed..2acf43a9fb 100644
--- a/t/t4013/diff.log_-m_-p_master
+++ b/t/t4013/diff.log_-m_-p_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 diff --git a/dir/sub b/dir/sub
 index cead32e..992913c 100644
@@ -33,7 +33,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 diff --git a/dir/sub b/dir/sub
 index 7289e35..992913c 100644
diff --git a/t/t4013/diff.log_-p_--first-parent_master b/t/t4013/diff.log_-p_--first-parent_master
index 3fc896d424..c6a5876d80 100644
--- a/t/t4013/diff.log_-p_--first-parent_master
+++ b/t/t4013/diff.log_-p_--first-parent_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-p_master b/t/t4013/diff.log_-p_master
index bf1326dc36..1841cded94 100644
--- a/t/t4013/diff.log_-p_master
+++ b/t/t4013/diff.log_-p_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_master b/t/t4013/diff.log_master
index a8f6ce5abd..f8ec445eb3 100644
--- a/t/t4013/diff.log_master
+++ b/t/t4013/diff.log_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.show_--first-parent_master b/t/t4013/diff.show_--first-parent_master
index 3dcbe473a0..94548f4598 100644
--- a/t/t4013/diff.show_--first-parent_master
+++ b/t/t4013/diff.show_--first-parent_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 diff --git a/dir/sub b/dir/sub
 index cead32e..992913c 100644
diff --git a/t/t4013/diff.show_-c_master b/t/t4013/diff.show_-c_master
index 81aba8da96..1c46ed64fd 100644
--- a/t/t4013/diff.show_-c_master
+++ b/t/t4013/diff.show_-c_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 diff --combined dir/sub
 index cead32e,7289e35..992913c
diff --git a/t/t4013/diff.show_-m_master b/t/t4013/diff.show_-m_master
index 4ea2ee453d..7559fc22f8 100644
--- a/t/t4013/diff.show_-m_master
+++ b/t/t4013/diff.show_-m_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 diff --git a/dir/sub b/dir/sub
 index cead32e..992913c 100644
@@ -33,7 +33,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 diff --git a/dir/sub b/dir/sub
 index 7289e35..992913c 100644
diff --git a/t/t4013/diff.show_master b/t/t4013/diff.show_master
index fb08ce0e46..57091c5d90 100644
--- a/t/t4013/diff.show_master
+++ b/t/t4013/diff.show_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 diff --cc dir/sub
 index cead32e,7289e35..992913c
diff --git a/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master
index 30aae7817b..5f13a71bb5 100644
--- a/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
  dir/sub | 2 ++
  file0   | 3 +++
diff --git a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master
index d1d32bd34c..8acb88267b 100644
--- a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
  dir/sub | 2 ++
  file0   | 3 +++
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index a0930599aa..fd9af658af 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -483,7 +483,7 @@ test_expect_success 'set up merge history' '
 '
 
 cat > expect <<\EOF
-*   Merge branch 'side'
+*   Merge branch 'side' into master
 |\
 | * side-2
 | * side-1
@@ -502,7 +502,7 @@ test_expect_success 'log --graph with merge' '
 '
 
 cat > expect <<\EOF
-| | | *   Merge branch 'side'
+| | | *   Merge branch 'side' into master
 | | | |\
 | | | | * side-2
 | | | | * side-1
@@ -521,7 +521,7 @@ test_expect_success 'log --graph --line-prefix="| | | " with merge' '
 '
 
 cat > expect.colors <<\EOF
-*   Merge branch 'side'
+*   Merge branch 'side' into master
 <BLUE>|<RESET><CYAN>\<RESET>
 <BLUE>|<RESET> * side-2
 <BLUE>|<RESET> * side-1
@@ -555,7 +555,7 @@ cat > expect <<\EOF
 |\  Merge: A B
 | | Author: A U Thor <author@example.com>
 | |
-| |     Merge branch 'side'
+| |     Merge branch 'side' into master
 | |
 | * commit tags/side-2
 | | Author: A U Thor <author@example.com>
@@ -632,11 +632,11 @@ test_expect_success 'set up more tangled history' '
 '
 
 cat > expect <<\EOF
-*   Merge tag 'reach'
+*   Merge tag 'reach' into master
 |\
 | \
 |  \
-*-. \   Merge tags 'octopus-a' and 'octopus-b'
+*-. \   Merge tags 'octopus-a' and 'octopus-b' into master
 |\ \ \
 * | | | seventh
 | | * | octopus-b
@@ -646,14 +646,14 @@ cat > expect <<\EOF
 |/ /
 | * reach
 |/
-*   Merge branch 'tangle'
+*   Merge branch 'tangle' into master
 |\
 | *   Merge branch 'side' (early part) into tangle
 | |\
 | * \   Merge branch 'master' (early part) into tangle
 | |\ \
 | * | | tangle-a
-* | | |   Merge branch 'side'
+* | | |   Merge branch 'side' into master
 |\ \ \ \
 | * | | | side-2
 | | |_|/
@@ -735,16 +735,16 @@ test_expect_success 'log.decorate configuration' '
 
 test_expect_success 'decorate-refs with glob' '
 	cat >expect.decorate <<-\EOF &&
-	Merge-tag-reach
-	Merge-tags-octopus-a-and-octopus-b
+	Merge-tag-reach-into-master
+	Merge-tags-octopus-a-and-octopus-b-into-master
 	seventh
 	octopus-b (octopus-b)
 	octopus-a (octopus-a)
 	reach
 	EOF
 	cat >expect.no-decorate <<-\EOF &&
-	Merge-tag-reach
-	Merge-tags-octopus-a-and-octopus-b
+	Merge-tag-reach-into-master
+	Merge-tags-octopus-a-and-octopus-b-into-master
 	seventh
 	octopus-b
 	octopus-a
@@ -765,8 +765,8 @@ test_expect_success 'decorate-refs with glob' '
 
 test_expect_success 'decorate-refs without globs' '
 	cat >expect.decorate <<-\EOF &&
-	Merge-tag-reach
-	Merge-tags-octopus-a-and-octopus-b
+	Merge-tag-reach-into-master
+	Merge-tags-octopus-a-and-octopus-b-into-master
 	seventh
 	octopus-b
 	octopus-a
@@ -779,8 +779,8 @@ test_expect_success 'decorate-refs without globs' '
 
 test_expect_success 'multiple decorate-refs' '
 	cat >expect.decorate <<-\EOF &&
-	Merge-tag-reach
-	Merge-tags-octopus-a-and-octopus-b
+	Merge-tag-reach-into-master
+	Merge-tags-octopus-a-and-octopus-b-into-master
 	seventh
 	octopus-b (octopus-b)
 	octopus-a (octopus-a)
@@ -794,8 +794,8 @@ test_expect_success 'multiple decorate-refs' '
 
 test_expect_success 'decorate-refs-exclude with glob' '
 	cat >expect.decorate <<-\EOF &&
-	Merge-tag-reach (HEAD -> master)
-	Merge-tags-octopus-a-and-octopus-b
+	Merge-tag-reach-into-master (HEAD -> master)
+	Merge-tags-octopus-a-and-octopus-b-into-master
 	seventh (tag: seventh)
 	octopus-b (tag: octopus-b)
 	octopus-a (tag: octopus-a)
@@ -811,8 +811,8 @@ test_expect_success 'decorate-refs-exclude with glob' '
 
 test_expect_success 'decorate-refs-exclude without globs' '
 	cat >expect.decorate <<-\EOF &&
-	Merge-tag-reach (HEAD -> master)
-	Merge-tags-octopus-a-and-octopus-b
+	Merge-tag-reach-into-master (HEAD -> master)
+	Merge-tags-octopus-a-and-octopus-b-into-master
 	seventh (tag: seventh)
 	octopus-b (tag: octopus-b, octopus-b)
 	octopus-a (tag: octopus-a, octopus-a)
@@ -828,8 +828,8 @@ test_expect_success 'decorate-refs-exclude without globs' '
 
 test_expect_success 'multiple decorate-refs-exclude' '
 	cat >expect.decorate <<-\EOF &&
-	Merge-tag-reach (HEAD -> master)
-	Merge-tags-octopus-a-and-octopus-b
+	Merge-tag-reach-into-master (HEAD -> master)
+	Merge-tags-octopus-a-and-octopus-b-into-master
 	seventh (tag: seventh)
 	octopus-b (tag: octopus-b)
 	octopus-a (tag: octopus-a)
@@ -851,8 +851,8 @@ test_expect_success 'multiple decorate-refs-exclude' '
 
 test_expect_success 'decorate-refs and decorate-refs-exclude' '
 	cat >expect.no-decorate <<-\EOF &&
-	Merge-tag-reach (master)
-	Merge-tags-octopus-a-and-octopus-b
+	Merge-tag-reach-into-master (master)
+	Merge-tags-octopus-a-and-octopus-b-into-master
 	seventh
 	octopus-b
 	octopus-a
@@ -866,8 +866,8 @@ test_expect_success 'decorate-refs and decorate-refs-exclude' '
 
 test_expect_success 'deocrate-refs and log.excludeDecoration' '
 	cat >expect.decorate <<-\EOF &&
-	Merge-tag-reach (master)
-	Merge-tags-octopus-a-and-octopus-b
+	Merge-tag-reach-into-master (master)
+	Merge-tags-octopus-a-and-octopus-b-into-master
 	seventh
 	octopus-b (octopus-b)
 	octopus-a (octopus-a)
@@ -881,10 +881,10 @@ test_expect_success 'deocrate-refs and log.excludeDecoration' '
 
 test_expect_success 'decorate-refs-exclude and simplify-by-decoration' '
 	cat >expect.decorate <<-\EOF &&
-	Merge-tag-reach (HEAD -> master)
+	Merge-tag-reach-into-master (HEAD -> master)
 	reach (tag: reach, reach)
 	seventh (tag: seventh)
-	Merge-branch-tangle
+	Merge-branch-tangle-into-master
 	Merge-branch-side-early-part-into-tangle (tangle)
 	tangle-a (tag: tangle-a)
 	EOF
@@ -1068,7 +1068,7 @@ cat >expect <<\EOF
 |\  Merge: MERGE_PARENTS
 | | Author: A U Thor <author@example.com>
 | |
-| |     Merge branch 'tangle'
+| |     Merge branch 'tangle' into master
 | |
 | *   commit COMMIT_OBJECT_NAME
 | |\  Merge: MERGE_PARENTS
@@ -1102,7 +1102,7 @@ cat >expect <<\EOF
 |\ \ \ \  Merge: MERGE_PARENTS
 | | | | | Author: A U Thor <author@example.com>
 | | | | |
-| | | | |     Merge branch 'side'
+| | | | |     Merge branch 'side' into master
 | | | | |
 | * | | | commit COMMIT_OBJECT_NAME
 | | |_|/  Author: A U Thor <author@example.com>
@@ -1343,7 +1343,7 @@ cat >expect <<\EOF
 *** |\  Merge: MERGE_PARENTS
 *** | | Author: A U Thor <author@example.com>
 *** | |
-*** | |     Merge branch 'tangle'
+*** | |     Merge branch 'tangle' into master
 *** | |
 *** | *   commit COMMIT_OBJECT_NAME
 *** | |\  Merge: MERGE_PARENTS
@@ -1377,7 +1377,7 @@ cat >expect <<\EOF
 *** |\ \ \ \  Merge: MERGE_PARENTS
 *** | | | | | Author: A U Thor <author@example.com>
 *** | | | | |
-*** | | | | |     Merge branch 'side'
+*** | | | | |     Merge branch 'side' into master
 *** | | | | |
 *** | * | | | commit COMMIT_OBJECT_NAME
 *** | | |_|/  Author: A U Thor <author@example.com>
@@ -1540,8 +1540,8 @@ cat >expect <<-\EOF
 * reach
 |
 | A	reach.t
-* Merge branch 'tangle'
-*   Merge branch 'side'
+* Merge branch 'tangle' into master
+*   Merge branch 'side' into master
 |\
 | * side-2
 |
@@ -1562,8 +1562,8 @@ cat >expect <<-\EOF
 * reach
 |
 | reach.t
-* Merge branch 'tangle'
-*   Merge branch 'side'
+* Merge branch 'tangle' into master
+*   Merge branch 'side' into master
 |\
 | * side-2
 |
diff --git a/t/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh
index e4c2a6eca4..2b3fd498d0 100755
--- a/t/t6200-fmt-merge-msg.sh
+++ b/t/t6200-fmt-merge-msg.sh
@@ -79,7 +79,7 @@ test_expect_success GPG 'set up a signed tag' '
 '
 
 test_expect_success 'message for merging local branch' '
-	echo "Merge branch ${apos}left${apos}" >expected &&
+	echo "Merge branch ${apos}left${apos} into master" >expected &&
 
 	git checkout master &&
 	git fetch . left &&
@@ -107,7 +107,7 @@ test_expect_success GPG 'message for merging local tag signed by unknown key' '
 '
 
 test_expect_success 'message for merging external branch' '
-	echo "Merge branch ${apos}left${apos} of $(pwd)" >expected &&
+	echo "Merge branch ${apos}left${apos} of $(pwd) into master" >expected &&
 
 	git checkout master &&
 	git fetch "$(pwd)" left &&
@@ -118,7 +118,7 @@ test_expect_success 'message for merging external branch' '
 
 test_expect_success '[merge] summary/log configuration' '
 	cat >expected <<-EOF &&
-	Merge branch ${apos}left${apos}
+	Merge branch ${apos}left${apos} into master
 
 	# By Another Author (3) and A U Thor (2)
 	# Via Another Committer
@@ -160,7 +160,7 @@ test_expect_success 'setup FETCH_HEAD' '
 
 test_expect_success 'merge.log=3 limits shortlog length' '
 	cat >expected <<-EOF &&
-	Merge branch ${apos}left${apos}
+	Merge branch ${apos}left${apos} into master
 
 	# By Another Author (3) and A U Thor (2)
 	# Via Another Committer
@@ -177,7 +177,7 @@ test_expect_success 'merge.log=3 limits shortlog length' '
 
 test_expect_success 'merge.log=5 shows all 5 commits' '
 	cat >expected <<-EOF &&
-	Merge branch ${apos}left${apos}
+	Merge branch ${apos}left${apos} into master
 
 	# By Another Author (3) and A U Thor (2)
 	# Via Another Committer
@@ -195,7 +195,7 @@ test_expect_success 'merge.log=5 shows all 5 commits' '
 
 test_expect_success '--log=5 with custom comment character' '
 	cat >expected <<-EOF &&
-	Merge branch ${apos}left${apos}
+	Merge branch ${apos}left${apos} into master
 
 	x By Another Author (3) and A U Thor (2)
 	x Via Another Committer
@@ -212,14 +212,14 @@ test_expect_success '--log=5 with custom comment character' '
 '
 
 test_expect_success 'merge.log=0 disables shortlog' '
-	echo "Merge branch ${apos}left${apos}" >expected &&
+	echo "Merge branch ${apos}left${apos} into master" >expected &&
 	git -c merge.log=0 fmt-merge-msg <.git/FETCH_HEAD >actual &&
 	test_cmp expected actual
 '
 
 test_expect_success '--log=3 limits shortlog length' '
 	cat >expected <<-EOF &&
-	Merge branch ${apos}left${apos}
+	Merge branch ${apos}left${apos} into master
 
 	# By Another Author (3) and A U Thor (2)
 	# Via Another Committer
@@ -236,7 +236,7 @@ test_expect_success '--log=3 limits shortlog length' '
 
 test_expect_success '--log=5 shows all 5 commits' '
 	cat >expected <<-EOF &&
-	Merge branch ${apos}left${apos}
+	Merge branch ${apos}left${apos} into master
 
 	# By Another Author (3) and A U Thor (2)
 	# Via Another Committer
@@ -253,13 +253,13 @@ test_expect_success '--log=5 shows all 5 commits' '
 '
 
 test_expect_success '--no-log disables shortlog' '
-	echo "Merge branch ${apos}left${apos}" >expected &&
+	echo "Merge branch ${apos}left${apos} into master" >expected &&
 	git fmt-merge-msg --no-log <.git/FETCH_HEAD >actual &&
 	test_cmp expected actual
 '
 
 test_expect_success '--log=0 disables shortlog' '
-	echo "Merge branch ${apos}left${apos}" >expected &&
+	echo "Merge branch ${apos}left${apos} into master" >expected &&
 	git fmt-merge-msg --no-log <.git/FETCH_HEAD >actual &&
 	test_cmp expected actual
 '
@@ -300,7 +300,7 @@ test_expect_success 'fmt-merge-msg -m' '
 
 test_expect_success 'setup: expected shortlog for two branches' '
 	cat >expected <<-EOF
-	Merge branches ${apos}left${apos} and ${apos}right${apos}
+	Merge branches ${apos}left${apos} and ${apos}right${apos} into master
 
 	# By Another Author (3) and A U Thor (2)
 	# Via Another Committer
@@ -397,7 +397,7 @@ test_expect_success 'merge-msg with nothing to merge' '
 
 test_expect_success 'merge-msg tag' '
 	cat >expected <<-EOF &&
-	Merge tag ${apos}tag-r3${apos}
+	Merge tag ${apos}tag-r3${apos} into master
 
 	* tag ${apos}tag-r3${apos}:
 	  Right #3
@@ -418,7 +418,7 @@ test_expect_success 'merge-msg tag' '
 
 test_expect_success 'merge-msg two tags' '
 	cat >expected <<-EOF &&
-	Merge tags ${apos}tag-r3${apos} and ${apos}tag-l5${apos}
+	Merge tags ${apos}tag-r3${apos} and ${apos}tag-l5${apos} into master
 
 	* tag ${apos}tag-r3${apos}:
 	  Right #3
@@ -448,7 +448,7 @@ test_expect_success 'merge-msg two tags' '
 
 test_expect_success 'merge-msg tag and branch' '
 	cat >expected <<-EOF &&
-	Merge branch ${apos}left${apos}, tag ${apos}tag-r3${apos}
+	Merge branch ${apos}left${apos}, tag ${apos}tag-r3${apos} into master
 
 	* tag ${apos}tag-r3${apos}:
 	  Right #3
@@ -479,7 +479,7 @@ test_expect_success 'merge-msg tag and branch' '
 test_expect_success 'merge-msg lots of commits' '
 	{
 		cat <<-EOF &&
-		Merge branch ${apos}long${apos}
+		Merge branch ${apos}long${apos} into master
 
 		* long: (35 commits)
 		EOF
@@ -516,7 +516,7 @@ test_expect_success 'merge-msg with "merging" an annotated tag' '
 	git fmt-merge-msg <.git/FETCH_HEAD >actual &&
 	{
 		cat <<-\EOF
-		Merge tag '\''annote'\''
+		Merge tag '\''annote'\'' into master
 
 		An annotated one
 
@@ -531,7 +531,7 @@ test_expect_success 'merge-msg with "merging" an annotated tag' '
 	git merge --no-commit --no-ff $annote &&
 	{
 		cat <<-EOF
-		Merge tag '\''$annote'\''
+		Merge tag '\''$annote'\'' into master
 
 		An annotated one
 
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 5883a6adc3..1d45f9a4ed 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -14,9 +14,9 @@ Testing basic merge operations/option parsing.
     ! [c4] c4
      ! [c5] c5
       ! [c6] c6
-       * [master] Merge commit 'c1'
+       * [master] Merge commit 'c1' into master
 --------
-       - [master] Merge commit 'c1'
+       - [master] Merge commit 'c1' into master
  +     * [c1] commit 1
       +  [c6] c6
      +   [c5] c5
@@ -44,8 +44,8 @@ test_write_lines '1 X' 2 '3 X' 4 '5 X' 6 7 8 '9 X' >result.1-3-5-9
 test_write_lines 1 2 3 4 5 6 7 8 '9 Z' >result.9z
 
 create_merge_msgs () {
-	echo "Merge tag 'c2'" >msg.1-5 &&
-	echo "Merge tags 'c2' and 'c3'" >msg.1-5-9 &&
+	echo "Merge tag 'c2' into master" >msg.1-5 &&
+	echo "Merge tags 'c2' and 'c3' into master" >msg.1-5-9 &&
 	{
 		echo "Squashed commit of the following:" &&
 		echo &&
@@ -258,7 +258,7 @@ test_expect_success 'merge c3 with c7 with commit.cleanup = scissors' '
 	git commit --no-edit -a &&
 
 	cat >expect <<-\EOF &&
-	Merge tag '"'"'c7'"'"'
+	Merge tag '"'"'c7'"'"' into master
 
 	# ------------------------ >8 ------------------------
 	# Do not modify or remove the line above.
@@ -808,10 +808,10 @@ test_expect_success 'merge with conflicted --autostash changes' '
 '
 
 cat >expected.branch <<\EOF
-Merge branch 'c5-branch' (early part)
+Merge branch 'c5-branch' (early part) into master
 EOF
 cat >expected.tag <<\EOF
-Merge commit 'c5~1'
+Merge commit 'c5~1' into master
 EOF
 
 test_expect_success 'merge early part of c2' '
diff --git a/t/t7608-merge-messages.sh b/t/t7608-merge-messages.sh
index 8e7e0a5865..2af33f195b 100755
--- a/t/t7608-merge-messages.sh
+++ b/t/t7608-merge-messages.sh
@@ -16,7 +16,7 @@ test_expect_success 'merge local branch' '
 	git checkout master &&
 	test_commit master-2 &&
 	git merge local-branch &&
-	check_oneline "Merge branch Qlocal-branchQ"
+	check_oneline "Merge branch Qlocal-branchQ into master"
 '
 
 test_expect_success 'merge octopus branches' '
@@ -26,7 +26,7 @@ test_expect_success 'merge octopus branches' '
 	test_commit octopus-2 &&
 	git checkout master &&
 	git merge octopus-a octopus-b &&
-	check_oneline "Merge branches Qoctopus-aQ and Qoctopus-bQ"
+	check_oneline "Merge branches Qoctopus-aQ and Qoctopus-bQ into master"
 '
 
 test_expect_success 'merge tag' '
@@ -35,7 +35,7 @@ test_expect_success 'merge tag' '
 	git checkout master &&
 	test_commit master-3 &&
 	git merge tag-1 &&
-	check_oneline "Merge tag Qtag-1Q"
+	check_oneline "Merge tag Qtag-1Q into master"
 '
 
 test_expect_success 'ambiguous tag' '
@@ -44,7 +44,7 @@ test_expect_success 'ambiguous tag' '
 	git checkout master &&
 	test_commit master-4 &&
 	git merge ambiguous &&
-	check_oneline "Merge tag QambiguousQ"
+	check_oneline "Merge tag QambiguousQ into master"
 '
 
 test_expect_success 'remote-tracking branch' '
@@ -54,7 +54,7 @@ test_expect_success 'remote-tracking branch' '
 	git checkout master &&
 	test_commit master-5 &&
 	git merge origin/master &&
-	check_oneline "Merge remote-tracking branch Qorigin/masterQ"
+	check_oneline "Merge remote-tracking branch Qorigin/masterQ into master"
 '
 
 test_done
-- 
gitgitgadget
Đoàn Trần Công Danh· Jun 29, 2020, 16:20 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH v4 1/9] fmt-merge-msg: stop treating `master` specially

On 2020-06-24 14:46:28+0000, Johannes Schindelin via GitGitGadget <gitgitgadget@gmail.com> wrote:
Show 9 quoted lines
> From: Johannes Schindelin <johannes.schindelin@gmx.de>
> 
> In the context of many projects renaming their primary branch names away
> from `master`, Git wants to stop treating the `master` branch specially.
> 
> Let's start with `git fmt-merge-msg`.
> 
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> ---
Hi Dscho,
This change will also affect git-subtree test.
We'll need this patch for subtree:
----------------8<-------------------
From: =?UTF-8?q?=C4=90o=C3=A0n=20Tr=E1=BA=A7n=20C=C3=B4ng=20Danh?=
 <congdanhqx@gmail.com>
Date: Mon, 29 Jun 2020 22:56:37 +0700
Subject: [PATCH] contrib: subtree: adjust test to change in fmt-merge-msg
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

We're starting to stop treating `master' specially in fmt-merge-msg. Adjust the test to reflect that change.

Signed-off-by: Đoàn Trần Công Danh <congdanhqx@gmail.com>
---
 contrib/subtree/t/t7900-subtree.sh | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
Show changes to contrib/subtree/t/t7900-subtree.sh +4 −2
diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh
index 57ff4b25c1..53d7accf94 100755
--- a/contrib/subtree/t/t7900-subtree.sh
+++ b/contrib/subtree/t/t7900-subtree.sh
@@ -196,7 +196,8 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix' '
 		cd "$subtree_test_count" &&
 		git fetch ./"sub proj" master &&
 		git subtree merge --prefix="sub dir" FETCH_HEAD &&
-		check_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\''"
+		check_equal "$(last_commit_message)" \
+			"Merge commit '\''$(git rev-parse FETCH_HEAD)'\'' into master"
 	)
 '
 
@@ -273,7 +274,8 @@ test_expect_success 'merge new subproj history into subdir/ with a slash appende
 		cd "$test_count" &&
 		git fetch ./subproj master &&
 		git subtree merge --prefix=subdir/ FETCH_HEAD &&
-		check_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\''"
+		check_equal "$(last_commit_message)" \
+			"Merge commit '\''$(git rev-parse FETCH_HEAD)'\'' into master"
 	)
 '
 
-- 
2.27.0.111.gc72c7da667
Danh
Johannes Schindelin· Jun 29, 2020, 13:27 UTC · re: Đoàn Trần Công Danh · lore

Re: [PATCH v4 1/9] fmt-merge-msg: stop treating `master` specially

Hi Danh,
On Mon, 29 Jun 2020, Đoàn Trần Công Danh wrote:
Show 14 quoted lines
> On 2020-06-24 14:46:28+0000, Johannes Schindelin via GitGitGadget <gitgitgadget@gmail.com> wrote:
> > From: Johannes Schindelin <johannes.schindelin@gmx.de>
> >
> > In the context of many projects renaming their primary branch names away
> > from `master`, Git wants to stop treating the `master` branch specially.
> >
> > Let's start with `git fmt-merge-msg`.
> >
> > Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> > ---
>
> Hi Dscho,
>
> This change will also affect git-subtree test.

Good point. The patch looks good. I wonder whether we should also address these:

Documentation/git-rebase.txt:* Merge branch 'report-a-bug' Documentation/git-rebase.txt:* | Merge branch 'refactor-button' Documentation/git-switch.txt:HEAD is now at 9fc9555312 Merge branch 'cc/shared-index-permbits' Documentation/howto/using-signed-tag-in-pull-request.txt: Merge tag 'frotz-for-xyzzy' of example.com:/git/froboz.git/ Documentation/howto/using-signed-tag-in-pull-request.txt: Merge tag 'frotz-for-xyzzy' of example.com:/git/froboz.git/ t/t7606-merge-custom.sh:* (HEAD, master) Merge commit 'c3'

The first three matches are in manual pages, the next two in technical documentation, and the last one in a comment in one of the test scripts. So none of them are super critical, but maybe there are different opinions?

Ciao, Dscho

Show 46 quoted lines
> We'll need this patch for subtree:
> ----------------8<-------------------
> From: =?UTF-8?q?=C4=90o=C3=A0n=20Tr=E1=BA=A7n=20C=C3=B4ng=20Danh?=
>  <congdanhqx@gmail.com>
> Date: Mon, 29 Jun 2020 22:56:37 +0700
> Subject: [PATCH] contrib: subtree: adjust test to change in fmt-merge-msg
> MIME-Version: 1.0
> Content-Type: text/plain; charset=UTF-8
> Content-Transfer-Encoding: 8bit
>
> We're starting to stop treating `master' specially in fmt-merge-msg.
> Adjust the test to reflect that change.
>
> Signed-off-by: Đoàn Trần Công Danh <congdanhqx@gmail.com>
> ---
>  contrib/subtree/t/t7900-subtree.sh | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh
> index 57ff4b25c1..53d7accf94 100755
> --- a/contrib/subtree/t/t7900-subtree.sh
> +++ b/contrib/subtree/t/t7900-subtree.sh
> @@ -196,7 +196,8 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix' '
>  		cd "$subtree_test_count" &&
>  		git fetch ./"sub proj" master &&
>  		git subtree merge --prefix="sub dir" FETCH_HEAD &&
> -		check_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\''"
> +		check_equal "$(last_commit_message)" \
> +			"Merge commit '\''$(git rev-parse FETCH_HEAD)'\'' into master"
>  	)
>  '
>
> @@ -273,7 +274,8 @@ test_expect_success 'merge new subproj history into subdir/ with a slash appende
>  		cd "$test_count" &&
>  		git fetch ./subproj master &&
>  		git subtree merge --prefix=subdir/ FETCH_HEAD &&
> -		check_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\''"
> +		check_equal "$(last_commit_message)" \
> +			"Merge commit '\''$(git rev-parse FETCH_HEAD)'\'' into master"
>  	)
>  '
>
> --
> 2.27.0.111.gc72c7da667
> Danh
>
Đoàn Trần Công Danh· Jun 30, 2020, 15:05 UTC · re: Johannes Schindelin · lore

Re: [PATCH v4 1/9] fmt-merge-msg: stop treating `master` specially

Hi Dscho,
On 2020-06-29 15:27:44+0200, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
Show 16 quoted lines
> > This change will also affect git-subtree test.
> 
> Good point. The patch looks good. I wonder whether we should also address
> these:
> 
> Documentation/git-rebase.txt:*   Merge branch 'report-a-bug'
> Documentation/git-rebase.txt:* | Merge branch 'refactor-button'
> Documentation/git-switch.txt:HEAD is now at 9fc9555312 Merge branch 'cc/shared-index-permbits'
> Documentation/howto/using-signed-tag-in-pull-request.txt: Merge tag 'frotz-for-xyzzy' of example.com:/git/froboz.git/
> Documentation/howto/using-signed-tag-in-pull-request.txt:     Merge tag 'frotz-for-xyzzy' of example.com:/git/froboz.git/
> t/t7606-merge-custom.sh:*   (HEAD, master) Merge commit 'c3'
> 
> The first three matches are in manual pages, the next two in technical
> documentation, and the last one in a comment in one of the test scripts.
> So none of them are super critical, but maybe there are different
> opinions?

In _my very opinion_, I don't think it's that critical. We allow git merge --edit and git fmt-merge-msg -m. Someone may have configured their Git to remove branch name already. And some others may always remove the target branch manually. We probably don't want to introduce another master occurence. (For sideline watcher: Please not argue on this, I don't have any opinions about the word: master.)

If there're a consensus on changing those documentation, I won't mind to do that manual work ;)

The test is a different story, since some (or most?) distro enable check (or test) phase for their build infrastructure. And, we shouldn't break their infrastructures.

Show 50 quoted lines
> 
> Ciao,
> Dscho
> 
> > We'll need this patch for subtree:
> > ----------------8<-------------------
> > From: =?UTF-8?q?=C4=90o=C3=A0n=20Tr=E1=BA=A7n=20C=C3=B4ng=20Danh?=
> >  <congdanhqx@gmail.com>
> > Date: Mon, 29 Jun 2020 22:56:37 +0700
> > Subject: [PATCH] contrib: subtree: adjust test to change in fmt-merge-msg
> > MIME-Version: 1.0
> > Content-Type: text/plain; charset=UTF-8
> > Content-Transfer-Encoding: 8bit
> >
> > We're starting to stop treating `master' specially in fmt-merge-msg.
> > Adjust the test to reflect that change.
> >
> > Signed-off-by: Đoàn Trần Công Danh <congdanhqx@gmail.com>
> > ---
> >  contrib/subtree/t/t7900-subtree.sh | 6 ++++--
> >  1 file changed, 4 insertions(+), 2 deletions(-)
> >
> > diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh
> > index 57ff4b25c1..53d7accf94 100755
> > --- a/contrib/subtree/t/t7900-subtree.sh
> > +++ b/contrib/subtree/t/t7900-subtree.sh
> > @@ -196,7 +196,8 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix' '
> >  		cd "$subtree_test_count" &&
> >  		git fetch ./"sub proj" master &&
> >  		git subtree merge --prefix="sub dir" FETCH_HEAD &&
> > -		check_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\''"
> > +		check_equal "$(last_commit_message)" \
> > +			"Merge commit '\''$(git rev-parse FETCH_HEAD)'\'' into master"
> >  	)
> >  '
> >
> > @@ -273,7 +274,8 @@ test_expect_success 'merge new subproj history into subdir/ with a slash appende
> >  		cd "$test_count" &&
> >  		git fetch ./subproj master &&
> >  		git subtree merge --prefix=subdir/ FETCH_HEAD &&
> > -		check_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\''"
> > +		check_equal "$(last_commit_message)" \
> > +			"Merge commit '\''$(git rev-parse FETCH_HEAD)'\'' into master"
> >  	)
> >  '
> >
> > --
> > 2.27.0.111.gc72c7da667
> > Danh
> >
-- 
Danh
Johannes Schindelin· Jul 1, 2020, 10:39 UTC · re: Đoàn Trần Công Danh · lore

Re: [PATCH v4 1/9] fmt-merge-msg: stop treating `master` specially

Hi Danh,
On Tue, 30 Jun 2020, Đoàn Trần Công Danh wrote:
Show 25 quoted lines
> On 2020-06-29 15:27:44+0200, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> > > This change will also affect git-subtree test.
> >
> > Good point. The patch looks good. I wonder whether we should also address
> > these:
> >
> > Documentation/git-rebase.txt:*   Merge branch 'report-a-bug'
> > Documentation/git-rebase.txt:* | Merge branch 'refactor-button'
> > Documentation/git-switch.txt:HEAD is now at 9fc9555312 Merge branch 'cc/shared-index-permbits'
> > Documentation/howto/using-signed-tag-in-pull-request.txt: Merge tag 'frotz-for-xyzzy' of example.com:/git/froboz.git/
> > Documentation/howto/using-signed-tag-in-pull-request.txt:     Merge tag 'frotz-for-xyzzy' of example.com:/git/froboz.git/
> > t/t7606-merge-custom.sh:*   (HEAD, master) Merge commit 'c3'
> >
> > The first three matches are in manual pages, the next two in technical
> > documentation, and the last one in a comment in one of the test scripts.
> > So none of them are super critical, but maybe there are different
> > opinions?
>
> In _my very opinion_, I don't think it's that critical.
> We allow git merge --edit and git fmt-merge-msg -m.
> Someone may have configured their Git to remove branch name already.
> And some others may always remove the target branch manually.
> We probably don't want to introduce another master occurence.
> (For sideline watcher: Please not argue on this,
> I don't have any opinions about the word: master.)
True.
> If there're a consensus on changing those documentation,
> I won't mind to do that manual work ;)
I actually agree that it is not _really_ necessary.
> The test is a different story, since some (or most?) distro enable
> check (or test) phase for their build infrastructure.
> And, we shouldn't break their infrastructures.

Actually, the hit in t7606 is in the initial _comment_. So I highly doubt that it would break any build infrastructure to leave it alone.

Ciao, Dscho

Show 55 quoted lines
> >
> > Ciao,
> > Dscho
> >
> > > We'll need this patch for subtree:
> > > ----------------8<-------------------
> > > From: =?UTF-8?q?=C4=90o=C3=A0n=20Tr=E1=BA=A7n=20C=C3=B4ng=20Danh?=
> > >  <congdanhqx@gmail.com>
> > > Date: Mon, 29 Jun 2020 22:56:37 +0700
> > > Subject: [PATCH] contrib: subtree: adjust test to change in fmt-merge-msg
> > > MIME-Version: 1.0
> > > Content-Type: text/plain; charset=UTF-8
> > > Content-Transfer-Encoding: 8bit
> > >
> > > We're starting to stop treating `master' specially in fmt-merge-msg.
> > > Adjust the test to reflect that change.
> > >
> > > Signed-off-by: Đoàn Trần Công Danh <congdanhqx@gmail.com>
> > > ---
> > >  contrib/subtree/t/t7900-subtree.sh | 6 ++++--
> > >  1 file changed, 4 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh
> > > index 57ff4b25c1..53d7accf94 100755
> > > --- a/contrib/subtree/t/t7900-subtree.sh
> > > +++ b/contrib/subtree/t/t7900-subtree.sh
> > > @@ -196,7 +196,8 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix' '
> > >  		cd "$subtree_test_count" &&
> > >  		git fetch ./"sub proj" master &&
> > >  		git subtree merge --prefix="sub dir" FETCH_HEAD &&
> > > -		check_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\''"
> > > +		check_equal "$(last_commit_message)" \
> > > +			"Merge commit '\''$(git rev-parse FETCH_HEAD)'\'' into master"
> > >  	)
> > >  '
> > >
> > > @@ -273,7 +274,8 @@ test_expect_success 'merge new subproj history into subdir/ with a slash appende
> > >  		cd "$test_count" &&
> > >  		git fetch ./subproj master &&
> > >  		git subtree merge --prefix=subdir/ FETCH_HEAD &&
> > > -		check_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\''"
> > > +		check_equal "$(last_commit_message)" \
> > > +			"Merge commit '\''$(git rev-parse FETCH_HEAD)'\'' into master"
> > >  	)
> > >  '
> > >
> > > --
> > > 2.27.0.111.gc72c7da667
> > > Danh
> > >
>
>
> --
> Danh
>
Junio C Hamano· Jul 1, 2020, 19:54 UTC · re: Johannes Schindelin · lore

Re: [PATCH v4 1/9] fmt-merge-msg: stop treating `master` specially

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
Show 17 quoted lines
>> In _my very opinion_, I don't think it's that critical.
>> We allow git merge --edit and git fmt-merge-msg -m.
>> ...
>
> True.
>
>> If there're a consensus on changing those documentation,
>> I won't mind to do that manual work ;)
>
> I actually agree that it is not _really_ necessary.
>
>> The test is a different story, since some (or most?) distro enable
>> check (or test) phase for their build infrastructure.
>> And, we shouldn't break their infrastructures.
>
> Actually, the hit in t7606 is in the initial _comment_. So I highly doubt
> that it would break any build infrastructure to leave it alone.
I guess it's settled, then.
Thank you to all for being extra careful.
Don Goodman-Wilson via GitGitGadget· Jun 24, 2020, 14:46 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v4 6/9] init: allow setting the default for the initial branch name via the config

From: Don Goodman-Wilson <don@goodman-wilson.com>

We just introduced the command-line option `--initial-branch=<branch-name>` to allow initializing a new repository with a different initial branch than the hard-coded one.

To allow users to override the initial branch name more permanently (i.e. without having to specify the name manually for each and every `git init` invocation), let's introduce the `init.defaultBranch` config setting.

Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Helped-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Don Goodman-Wilson <don@goodman-wilson.com>
---
 Documentation/config/init.txt |  4 ++++
 builtin/init-db.c             |  2 +-
 refs.c                        | 30 ++++++++++++++++++++++++++++++
 refs.h                        |  9 +++++++++
 t/t0001-init.sh               | 13 +++++++++++++
 5 files changed, 57 insertions(+), 1 deletion(-)
Show changes to 5 files +57 −1

Documentation/config/init.txt, builtin/init-db.c, refs.c, refs.h, t/t0001-init.sh

diff --git a/Documentation/config/init.txt b/Documentation/config/init.txt
index 46fa8c6a08..6ae4a38416 100644
--- a/Documentation/config/init.txt
+++ b/Documentation/config/init.txt
@@ -1,3 +1,7 @@
 init.templateDir::
 	Specify the directory from which templates will be copied.
 	(See the "TEMPLATE DIRECTORY" section of linkgit:git-init[1].)
+
+init.defaultBranch::
+	Allows overriding the default branch name when initializing
+	a new repository.
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 8fdfc334ac..cee64823cb 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -269,7 +269,7 @@ static int create_default_files(const char *template_path,
 		char *ref;
 
 		if (!initial_branch)
-			initial_branch = "master";
+			initial_branch = git_default_branch_name();
 
 		ref = xstrfmt("refs/heads/%s", initial_branch);
 		if (check_refname_format(ref, 0) < 0)
diff --git a/refs.c b/refs.c
index 224ff66c7b..b98dea5217 100644
--- a/refs.c
+++ b/refs.c
@@ -560,6 +560,36 @@ void expand_ref_prefix(struct argv_array *prefixes, const char *prefix)
 		argv_array_pushf(prefixes, *p, len, prefix);
 }
 
+char *repo_default_branch_name(struct repository *r)
+{
+	const char *config_key = "init.defaultbranch";
+	const char *config_display_key = "init.defaultBranch";
+	char *ret = NULL, *full_ref;
+
+	if (repo_config_get_string(r, config_key, &ret) < 0)
+		die(_("could not retrieve `%s`"), config_display_key);
+
+	if (!ret)
+		ret = xstrdup("master");
+
+	full_ref = xstrfmt("refs/heads/%s", ret);
+	if (check_refname_format(full_ref, 0))
+		die(_("invalid branch name: %s = %s"), config_display_key, ret);
+	free(full_ref);
+
+	return ret;
+}
+
+const char *git_default_branch_name(void)
+{
+	static char *ret;
+
+	if (!ret)
+		ret = repo_default_branch_name(the_repository);
+
+	return ret;
+}
+
 /*
  * *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 e010f8aec2..f212f8945e 100644
--- a/refs.h
+++ b/refs.h
@@ -154,6 +154,15 @@ 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 default branch name for newly-initialized repositories.
+ *
+ * The return value of `repo_default_branch_name()` is an allocated string. The
+ * return value of `git_default_branch_name()` is a singleton.
+ */
+const char *git_default_branch_name(void);
+char *repo_default_branch_name(struct repository *r);
+
 /*
  * A ref_transaction represents a collection of reference updates that
  * should succeed or fail together.
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index 386c06b5dd..6d2467995e 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -477,4 +477,17 @@ test_expect_success '--initial-branch' '
 	grep hello actual
 '
 
+test_expect_success 'overridden default initial branch name (config)' '
+	test_config_global init.defaultBranch nmb &&
+	git init initial-branch-config &&
+	git -C initial-branch-config symbolic-ref HEAD >actual &&
+	grep nmb actual
+'
+
+test_expect_success 'invalid default branch name' '
+	test_config_global init.defaultBranch "with space" &&
+	test_must_fail git init initial-branch-invalid 2>err &&
+	test_i18ngrep "invalid branch name" err
+'
+
 test_done
-- 
gitgitgadget
Johannes Schindelin via GitGitGadget· Jun 24, 2020, 14:46 UTC · re: Johannes Schindelin via GitGitGadget · lore

[PATCH v4 5/9] init: allow specifying the initial branch name for the new repository

From: Johannes Schindelin <johannes.schindelin@gmx.de>

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).

To change that branch name for new repositories, currently the only way to do that automatically is by copying all of Git's template directory, then hard-coding the desired default branch name into the `.git/HEAD` file, and then configuring `init.templateDir` to point to those copied template files.

To make this process much less cumbersome, let's introduce a new option: `--initial-branch=<branch-name>`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 Documentation/git-init.txt |  7 +++++++
 builtin/clone.c            |  3 ++-
 builtin/init-db.c          | 33 +++++++++++++++++++++++++++------
 cache.h                    |  2 +-
 t/t0001-init.sh            | 13 +++++++++++++
 5 files changed, 50 insertions(+), 8 deletions(-)
Show changes to 5 files +50 −8

Documentation/git-init.txt, builtin/clone.c, builtin/init-db.c, cache.h, t/t0001-init.sh

diff --git a/Documentation/git-init.txt b/Documentation/git-init.txt
index f9467cc6a4..ddfe265da5 100644
--- a/Documentation/git-init.txt
+++ b/Documentation/git-init.txt
@@ -11,6 +11,7 @@ SYNOPSIS
 [verse]
 'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
 	  [--separate-git-dir <git dir>] [--object-format=<format>]
+	  [-b <branch-name> | --initial-branch=<branch-name>]
 	  [--shared[=<permissions>]] [directory]
 
 
@@ -67,6 +68,12 @@ repository.
 +
 If this is reinitialization, the repository will be moved to the specified path.
 
+-b <branch-name::
+--initial-branch=<branch-name>::
+
+Use the specified name for the initial branch in the newly created repository.
+If not specified, fall back to the default name: `master`.
+
 --shared[=(false|true|umask|group|all|world|everybody|0xxx)]::
 
 Specify that the Git repository is to be shared amongst several users.  This
diff --git a/builtin/clone.c b/builtin/clone.c
index 2a8e3aaaed..b751bdf13e 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1111,7 +1111,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		}
 	}
 
-	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, INIT_DB_QUIET);
+	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL,
+		INIT_DB_QUIET);
 
 	if (real_git_dir)
 		git_dir = real_git_dir;
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 0b7222e718..8fdfc334ac 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -203,6 +203,7 @@ void initialize_repository_version(int hash_algo)
 
 static int create_default_files(const char *template_path,
 				const char *original_git_dir,
+				const char *initial_branch,
 				const struct repository_format *fmt)
 {
 	struct stat st1;
@@ -258,15 +259,26 @@ static int create_default_files(const char *template_path,
 		die("failed to set up refs db: %s", err.buf);
 
 	/*
-	 * Create the default symlink from ".git/HEAD" to the "master"
-	 * branch, if it does not exist yet.
+	 * Point the HEAD symref to the initial branch with if HEAD does
+	 * not yet exist.
 	 */
 	path = git_path_buf(&buf, "HEAD");
 	reinit = (!access(path, R_OK)
 		  || readlink(path, junk, sizeof(junk)-1) != -1);
 	if (!reinit) {
-		if (create_symref("HEAD", "refs/heads/master", NULL) < 0)
+		char *ref;
+
+		if (!initial_branch)
+			initial_branch = "master";
+
+		ref = xstrfmt("refs/heads/%s", initial_branch);
+		if (check_refname_format(ref, 0) < 0)
+			die(_("invalid initial branch name: '%s'"),
+			    initial_branch);
+
+		if (create_symref("HEAD", ref, NULL) < 0)
 			exit(1);
+		free(ref);
 	}
 
 	initialize_repository_version(fmt->hash_algo);
@@ -383,7 +395,8 @@ static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash
 }
 
 int init_db(const char *git_dir, const char *real_git_dir,
-	    const char *template_dir, int hash, unsigned int flags)
+	    const char *template_dir, int hash, const char *initial_branch,
+	    unsigned int flags)
 {
 	int reinit;
 	int exist_ok = flags & INIT_DB_EXIST_OK;
@@ -425,7 +438,11 @@ int init_db(const char *git_dir, const char *real_git_dir,
 
 	validate_hash_algorithm(&repo_fmt, hash);
 
-	reinit = create_default_files(template_dir, original_git_dir, &repo_fmt);
+	reinit = create_default_files(template_dir, original_git_dir,
+				      initial_branch, &repo_fmt);
+	if (reinit && initial_branch)
+		warning(_("re-init: ignored --initial-branch=%s"),
+			initial_branch);
 
 	create_object_directory();
 
@@ -528,6 +545,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	const char *template_dir = NULL;
 	unsigned int flags = 0;
 	const char *object_format = NULL;
+	const char *initial_branch = NULL;
 	int hash_algo = GIT_HASH_UNKNOWN;
 	const struct option init_db_options[] = {
 		OPT_STRING(0, "template", &template_dir, N_("template-directory"),
@@ -541,6 +559,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 		OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET),
 		OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
 			   N_("separate git dir from working tree")),
+		OPT_STRING('b', "initial-branch", &initial_branch, N_("name"),
+			   N_("override the name of the initial branch")),
 		OPT_STRING(0, "object-format", &object_format, N_("hash"),
 			   N_("specify the hash algorithm to use")),
 		OPT_END()
@@ -652,5 +672,6 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	UNLEAK(work_tree);
 
 	flags |= INIT_DB_EXIST_OK;
-	return init_db(git_dir, real_git_dir, template_dir, hash_algo, flags);
+	return init_db(git_dir, real_git_dir, template_dir, hash_algo,
+		       initial_branch, flags);
 }
diff --git a/cache.h b/cache.h
index 0f0485ecfe..654426460c 100644
--- a/cache.h
+++ b/cache.h
@@ -628,7 +628,7 @@ int path_inside_repo(const char *prefix, const char *path);
 
 int init_db(const char *git_dir, const char *real_git_dir,
 	    const char *template_dir, int hash_algo,
-	    unsigned int flags);
+	    const char *initial_branch, unsigned int flags);
 void initialize_repository_version(int hash_algo);
 
 void sanitize_stdfds(void);
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index 1edd5aeb8f..386c06b5dd 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -464,4 +464,17 @@ test_expect_success MINGW 'redirect std handles' '
 	grep "Needed a single revision" output.txt
 '
 
+test_expect_success '--initial-branch' '
+	git init --initial-branch=hello initial-branch-option &&
+	git -C initial-branch-option symbolic-ref HEAD >actual &&
+	echo refs/heads/hello >expect &&
+	test_cmp expect actual &&
+
+	: re-initializing should not change the branch name &&
+	git init --initial-branch=ignore initial-branch-option 2>err &&
+	test_i18ngrep "ignored --initial-branch" err &&
+	git -C initial-branch-option symbolic-ref HEAD >actual &&
+	grep hello actual
+'
+
 test_done
-- 
gitgitgadget
Junio C Hamano· Jun 24, 2020, 16:26 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH v4 0/9] Allow overriding the default name of the default branch

"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com> writes:

Show 15 quoted lines
> Changes since v3:
>
>  * We now avoid the phrasing "specify a specific" in the messages.
>    
>    
>  * The git submodule patch has a better commit title now, and it also
>    adjusts the documentation more completely now (thanks, Philippe!).
>    
>    
>  * A code comment in builtin/init-db.c was updated to no longer talk about a 
>    symlink when it comes to HEAD.
>    
>    
>  * Made it the responsibility of the caller to warn about reinit &&
>    initial_branch.
It looked all good to me.  Will replace.
Thanks.  Hopefully we can go 'next' with this round---knock wood...
Johannes Schindelin· Jun 25, 2020, 13:03 UTC · re: Junio C Hamano · lore

Re: [PATCH v4 0/9] Allow overriding the default name of the default branch

Hi Junio,
On Wed, 24 Jun 2020, Junio C Hamano wrote:
Show 22 quoted lines
> "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
> writes:
>
> > Changes since v3:
> >
> >  * We now avoid the phrasing "specify a specific" in the messages.
> >
> >
> >  * The git submodule patch has a better commit title now, and it also
> >    adjusts the documentation more completely now (thanks, Philippe!).
> >
> >
> >  * A code comment in builtin/init-db.c was updated to no longer talk about a
> >    symlink when it comes to HEAD.
> >
> >
> >  * Made it the responsibility of the caller to warn about reinit &&
> >    initial_branch.
>
> It looked all good to me.  Will replace.
>
> Thanks.  Hopefully we can go 'next' with this round---knock wood...
I concur!

Ciao, Dscho

brian m. carlson· Jun 29, 2020, 22:41 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH v4 0/9] Allow overriding the default name of the default branch

On 2020-06-24 at 14:46:27, Johannes Schindelin via GitGitGadget wrote:
Show 33 quoted lines
> A growing number of open source projects aims to avoid the branch name 
> master due to its negative connotation. See [1] for an existing discussion
> on this. The links [2], [3], and [4] describe community-driven ways for
> users to rename their default branches or use template edits to set a new
> default branch name.
> 
> [1] 
> https://lore.kernel.org/git/CAOAHyQwyXC1Z3v7BZAC+Bq6JBaM7FvBenA-1fcqeDV==apdWDg@mail.gmail.com/
> 
> [2] https://twitter.com/mislav/status/1270388510684598272
> 
> [3] 
> https://www.hanselman.com/blog/EasilyRenameYourGitDefaultBranchFromMasterToMain.aspx
> 
> [4] https://github.com/ethomson/retarget_prs
> 
> By necessity, existing repositories require a lot of manual work to move
> away from that branch name, but it should be much easier for new
> repositories.
> 
> This patch series allows overriding the branch name being used for new
> repositories' main branch. This can be configured via init.defaultBranch.
> 
> The initial patch was started by newcomer Don Goodman-Wilson, as well as the
> bigger change that morphed into #655, where we demonstrate how to change
> Git's hard-coded default branch name for new repositories to main based on
> this here patch series, verifying the approach. Thanks for the contribution!
> 
> This series DOES NOT change the default automatically, but only provides an
> opt-in mechanism for interested users. The plan for that is to convert the
> test scripts incrementally (by introducing GIT_TEST_DEFAULT_MAIN_BRANCH_NAME
> , which overrides init.defaultBranch, and then converting the tricky test
> scripts first, one by one, using that environment variable).

I'm very happy with this and the way it's progressed since v1. This seems simpler than earlier designs, and I appreciate the improved focus on avoiding special-casing branches, since I think that will make it easier for folks to choose branch naming that suits them.

Thanks for working on this.
-- 
brian m. carlson: Houston, Texas, US
OpenPGP: https://keybase.io/bk2204
Edward Thomson· Jul 12, 2020, 13:03 UTC · re: brian m. carlson · lore

Re: [PATCH v4 0/9] Allow overriding the default name of the default branch

On Mon, Jun 29, 2020 at 11:42 PM brian m. carlson <sandals@crustytoothpaste.net> wrote:

Show 7 quoted lines
>
> I'm very happy with this and the way it's progressed since v1.  This
> seems simpler than earlier designs, and I appreciate the improved focus
> on avoiding special-casing branches, since I think that will make it
> easier for folks to choose branch naming that suits them.
>
> Thanks for working on this.
I agree, this is an improvement.

One thing that isn't obvious to me, though, is why templates take precedence over the command-line option. I would expect the command-line option to be the highest priority option given, just like configuration values specified on the command-line override values from configuration files.

Cheers- -ed

Johannes Schindelin· Jul 12, 2020, 08:19 UTC · re: Edward Thomson · lore

Re: [PATCH v4 0/9] Allow overriding the default name of the default branch

Hi Ed,
On Sun, 12 Jul 2020, Edward Thomson wrote:
Show 17 quoted lines
> On Mon, Jun 29, 2020 at 11:42 PM brian m. carlson
> <sandals@crustytoothpaste.net> wrote:
> >
> > I'm very happy with this and the way it's progressed since v1.  This
> > seems simpler than earlier designs, and I appreciate the improved focus
> > on avoiding special-casing branches, since I think that will make it
> > easier for folks to choose branch naming that suits them.
> >
> > Thanks for working on this.
>
> I agree, this is an improvement.
>
> One thing that isn't obvious to me, though, is why templates take
> precedence over the command-line option.  I would expect the command-line
> option to be the highest priority option given, just like configuration
> values specified on the command-line override values from configuration
> files.

Side note: I have not tested this, but I trust you did, and my reading of the code agrees that it does this.

The reason why it works that way is that while the `copy_templates()` function is called before the `create_symref()` call that creates the `HEAD` symref, the latter call is guarded by the condition that `HEAD` does not yet exist. Here is a link that highlights both calls (and the code in between): https://github.com/git/git/blob/v2.27.0/builtin/init-db.c#L229-L270

Now, it is probably not the intention of the code to prohibit the config setting from overriding the template files, but instead it intends to guard against overwriting files by running `git init` in an _already-initialized_ repository. And I don't think that it possible, really, to change the logic without making the effect quite hard to explain.

The truth is that overriding the default name via editing the templates is just not a very good strategy, it is fraught with peril, as e.g. `init.templateDir` is a thing that can be easily specified via the command-line (`git -c init.templateDir=/tmp/my-templates init`).

Ciao, Dscho

Ævar Arnfjörð Bjarmason· Jun 16, 2020, 09:47 UTC · re: Johannes Schindelin via GitGitGadget · lore

Re: [PATCH 0/9] Allow overriding the default name of the default branch

On Wed, Jun 10 2020, Johannes Schindelin via GitGitGadget wrote:
Show 5 quoted lines
> This series DOES NOT change the default automatically, but only provides an
> opt-in mechanism for interested users. It also presents a way forward for
> such a transition, if and when we decide to do so. Specifically, the new
> GIT_TEST_DEFAULT_BRANCH_NAME environment variable could be used to update
> test scripts on an individual basis instead of all-at-once.

I don't have much time for review today, but hopefully these comments are useful. These comments are on the series as a whole[1] mainly to save myself time in chasing down individual patches, and I think it's more useful as one E-Mail, hopefully.

I think this change is going in a good technical direction. I'm just commenting on the "how it would be done" aspect, I'm not going to add another voice to the larger "is this a useful endeavor?" discussion vis-a-vis what the larger goal is.

But I do have purely technical concerns about where this is going.

The part where we just make it easier to do what you could do all along with sed(1) or whatever to rename the branch after "git init" is obviously correct (or close enough). That part's easy enough.

The parts I'm concerned about is the behavior of how we make the branch name persistent, which is new "while we're at it" behavior in git unrelated to the convenience of allowing a configuration of the main branch name without "git init --template" or after the fact sed(1) munging.

Specifically:
 1. The special case in fmt-merge-msg we always had for "master" sucked
    in terms of producing more verbose merge messages for those of us
    who had repos where the main branch wasn't "master", but at least it
    was consistent.
    Now we've created a situation where a user's local config impacts
    what we put in the machine-generated commit messages.
    Now, these messages were never "plumbing", and other users could use
    different git frontends than "core git" etc, but it's a really
    useful property we've tried to maintain that a user's local
    configuration doesn't change what we put in these messages. It's why
    we've left them out of the i18n mechanism.
 2. The whole core.mainBranch thing rubs me the wrong way. So now if we
    rename a branch we munge it, but if you've got an older git version
    or whatever you get different results and the config isn't carried
    forward.
    I'd *really* like to avoid having what's essentially a refstore
    side-value if we can.
 3. Whatever we do with the submodule guess-a-name functionality, I
    think it's the wrong path to make it proceed in lockstep with
    MAIN_BRANCH_FOR_INIT.
    When you decide to change your branch names != when the rest of the
    world does it.
    Also, whatever the suckyness of the current hardcoded "master"
    behavior I think it sucks more than different users on the same
    version can fail or succeed to clone a repository depending on a
    config they set for "what branch names do I want on new repos?".
    This is simlar to #1, in that I'd much rather have behavior that
    consistently sucks than one that interacts with the wider world
    (writing commits, cloning random other repos) that differs because
    of my *local* config preferences.
 4. For fast-export I think we should just drop this entire "master"
    special case instead of making it read the config. That's also in
    line with its documentation. Let's just call it ref0.
    Either that or just hardcode whatever passes for the "main" branch
    name, but anything but making the to-be-shared anonymized output
    continue to leak local config, similar to #1 and #3 above.

In summary, I'd like this series much better if we split off the convenience change for "init" from the improved heuristics/guesses for remote "master". Just my 0.02.

1. git diff --stat -p @{u}...pr-656/dscho/default-branch-name-option-v2
Jeff King· Jun 16, 2020, 14:09 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: [PATCH 0/9] Allow overriding the default name of the default branch

On Tue, Jun 16, 2020 at 11:47:10AM +0200, Ævar Arnfjörð Bjarmason wrote:
Show 11 quoted lines
> But I do have purely technical concerns about where this is going.
> 
> The part where we just make it easier to do what you could do all along
> with sed(1) or whatever to rename the branch after "git init" is
> obviously correct (or close enough). That part's easy enough.
> 
> The parts I'm concerned about is the behavior of how we make the branch
> name persistent, which is new "while we're at it" behavior in git
> unrelated to the convenience of allowing a configuration of the main
> branch name without "git init --template" or after the fact sed(1)
> munging.

I've read the whole thing and left some specific comments, but your thinking more or less matches mine, with a few notes below.

Show 15 quoted lines
> Specifically:
> 
>  1. The special case in fmt-merge-msg we always had for "master" sucked
>     in terms of producing more verbose merge messages for those of us
>     who had repos where the main branch wasn't "master", but at least it
>     was consistent.
> 
>     Now we've created a situation where a user's local config impacts
>     what we put in the machine-generated commit messages.
> 
>     Now, these messages were never "plumbing", and other users could use
>     different git frontends than "core git" etc, but it's a really
>     useful property we've tried to maintain that a user's local
>     configuration doesn't change what we put in these messages. It's why
>     we've left them out of the i18n mechanism.

I'm actually tempted to say that "master" should stop being special. It's a little nice, I guess, if merges back to the main branch are a little more terse in their message. But I actually think consistently saying:

  Merge branch 'jk/foo' into main

_even if it's the main branch_ is actually pretty sane. It conveys more information about what happened that could be useful later, and I don't think it makes the result less readable.

Show 7 quoted lines
>  2. The whole core.mainBranch thing rubs me the wrong way. So now if we
>     rename a branch we munge it, but if you've got an older git version
>     or whatever you get different results and the config isn't carried
>     forward.
> 
>     I'd *really* like to avoid having what's essentially a refstore
>     side-value if we can.

I think it's necessary if we're going to have parts of the code that say "this is the special branch in this repo". Because we must leave the unconfigured state as "master is the special branch" in order to avoid regressing existing repositories. It _could_ be a flag that says "I was configured using init.mainBranch, so use that value". But I don't think that solves your fundamental concerns.

However, I wonder if we can get away with saying "there is no special branch" entirely. The things that care about the special branch are:

 - guessing HEAD; but this is guessing what the _remote_ side wants
   anyway, so it really has nothing to do with your local
   core.mainBranch (plus that guess shouldn't even be used much with
   modern git anyway).
 - the default branch for submodules; this is basically the same boat,
   and really ought to just be using the remote HEAD anyway.
 - slightly shorter merge messages. See above.
 - various "perhaps you should specify a branch such as master"
   messages. These could be reworded to avoid mentioning a specific
   branch, or could pick a real branch name.
 - fast-export anonymization. We could probably use HEAD as "ref0"
   instead (or do the output-map thing I mentioned, which is a much
   better solution anyway).

I think with that, we could ditch core.mainBranch entirely, with no notion at all of "this branch is special in this repo". We use HEAD where appropriate, and otherwise avoid any specialness.

Show 6 quoted lines
>  3. Whatever we do with the submodule guess-a-name functionality, I
>     think it's the wrong path to make it proceed in lockstep with
>     MAIN_BRANCH_FOR_INIT.
> 
>     When you decide to change your branch names != when the rest of the
>     world does it.

Yeah, this was my main concern for the whole series: what will break in a world of mixed main-branch names. Thankfully very little, it seems. But as much as possible we should be not just choosing our preferred value, but trying to match possible states. I think teaching the HEAD-guessing to try a few names, plus using HEAD for submodules, will pretty much do it (see my replies to individual patches for more details).

-Peff
Jeff King· Jun 16, 2020, 14:24 UTC · re: Jeff King · lore

Re: [PATCH 0/9] Allow overriding the default name of the default branch

On Tue, Jun 16, 2020 at 10:09:32AM -0400, Jeff King wrote:
> I think with that, we could ditch core.mainBranch entirely, with no
> notion at all of "this branch is special in this repo". We use HEAD
> where appropriate, and otherwise avoid any specialness.

One obvious exception is that third-party tools may want to know the "special" branch for some reason. But I'm inclined to say that they should (in this order):

  - consider whether they really need a special branch at all, or if the
    mechanism can be made more generic
  - consider whether HEAD is the best value for a special branch (e.g.,
    GitHub pull requests default to targeting HEAD)
  - rely on per-tool config for what's special (because it really may
    vary between tools, and that's more flexible anyway)

But I'm open to hearing about cases where some tool really wants to know "what did the user consider the special branch at the time of creation".

-Peff
Johannes Schindelin· Jun 23, 2020, 20:28 UTC · re: Jeff King · lore

Re: [PATCH 0/9] Allow overriding the default name of the default branch

Hi Peff & Ævar,
On Tue, 16 Jun 2020, Jeff King wrote:
Show 15 quoted lines
> On Tue, Jun 16, 2020 at 10:09:32AM -0400, Jeff King wrote:
>
> > I think with that, we could ditch core.mainBranch entirely, with no
> > notion at all of "this branch is special in this repo". We use HEAD
> > where appropriate, and otherwise avoid any specialness.
>
> One obvious exception is that third-party tools may want to know the
> "special" branch for some reason. But I'm inclined to say that they
> should (in this order):
>
>   - consider whether they really need a special branch at all, or if the
>     mechanism can be made more generic
>
>   - consider whether HEAD is the best value for a special branch (e.g.,
>     GitHub pull requests default to targeting HEAD)

Indeed, this is applicable in many circumstances. For example, instead of https://github.com/git/git/blob/master/README.md it is just as easy (and more robust) to write https://github.com/git/git/blob/HEAD/README.md.

The same goes for `git ls-remote origin HEAD` and as a consequence, `git fetch origin HEAD`: it fetches the default branch of the remote repository.

And with that, I could imagine that this is not actually necessary:
Show 5 quoted lines
>   - rely on per-tool config for what's special (because it really may
>     vary between tools, and that's more flexible anyway)
>
> But I'm open to hearing about cases where some tool really wants to know
> "what did the user consider the special branch at the time of creation".

I cannot think of any use cases, apart from essentially creating a new repository, where a tool or a user would want to know of such a preference.

Ciao, Dscho

Junio C Hamano· Jun 17, 2020, 20:28 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: [PATCH 0/9] Allow overriding the default name of the default branch

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
Show 13 quoted lines
>  1. The special case in fmt-merge-msg we always had for "master" sucked
>     in terms of producing more verbose merge messages for those of us
>     who had repos where the main branch wasn't "master", but at least it
>     was consistent.
>
>     Now we've created a situation where a user's local config impacts
>     what we put in the machine-generated commit messages.
>
>     Now, these messages were never "plumbing", and other users could use
>     different git frontends than "core git" etc, but it's a really
>     useful property we've tried to maintain that a user's local
>     configuration doesn't change what we put in these messages. It's why
>     we've left them out of the i18n mechanism.

I doubt the last sentence reflects the reality. As the person who invented the fmt-merge-msg's mechanism (including it special casing of 'master'), I know that it was the sentence lego that made it impossible to localize and left the code pretty much intact since the days it was introduced.

Having said that, I am personally inclined to vote for getting rid of the special casing of any branch by "git fmt-merge-msg" and "git fast-export --anonymize". We still need a mechanism to let users configure the word used by "git init" to give the first branch it creates as its name, but that is merely the first branch created in the repository and does not have to be the primary.

>  2. The whole core.mainBranch thing rubs me the wrong way. So now if we
>     rename a branch we munge it, but if you've got an older git version
>     or whatever you get different results and the config isn't carried
>     forward.
And we can get rid of this worry at the same time by doing so.
Johannes Schindelin· Jul 14, 2020, 14:55 UTC · lore

Re: [PATCH v4 0/9] Allow overriding the default name of the default branch

Hi Ed,
[re-Cc:ing the list, I hope you don't mind]
On Mon, 13 Jul 2020, Edward Thomson wrote:
Show 26 quoted lines
> On Mon, Jul 13, 2020 at 8:38 PM Johannes Schindelin
> <Johannes.Schindelin@gmx.de> wrote:
> > On Sun, 12 Jul 2020, Edward Thomson wrote:
> > > One thing that isn't obvious to me, though, is why templates take
> > > precedence over the command-line option.  I would expect the
> > > command-line option to be the highest priority option given, just
> > > like configuration values specified on the command-line override
> > > values from configuration files.
> >
> > Side note: I have not tested this, but I trust you did, and my reading
> > of the code agrees that it does this.
>
> I was speaking about the notion of configuration options specified with
> `-c` on the command line overridding things in configuration files.
> Like how you override `init.templateDir` on the command line:
>
> > The truth is that overriding the default name via editing the templates is
> > just not a very good strategy, it is fraught with peril, as e.g.
> > `init.templateDir` is a thing that can be easily specified via the
> > command-line (`git -c init.templateDir=/tmp/my-templates init`).
>
> I agree that setting a template that contains `HEAD` is perilous.  But
> it's an established and supported bit of peril.  I think that the question
> of configuration specificity is _also_ an established one (and not nearly
> so perilous).  Just like `-cinit.defaultBranch` overrides the global
> configuration, I would expect it to override the templates as well.

Is it really well-established? If so, it might really be worth doing something like this:

-- snip --
Show changes to builtin/init-db.c +8 −3
diff --git a/builtin/init-db.c b/builtin/init-db.c
index cee64823cbb..9149f9e51f5 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -210,7 +210,7 @@ static int create_default_files(const char *template_path,
 	struct strbuf buf = STRBUF_INIT;
 	char *path;
 	char junk[2];
-	int reinit;
+	int reinit, override_HEAD_in_templates = 0;
 	int filemode;
 	struct strbuf err = STRBUF_INIT;

@@ -218,6 +218,12 @@ static int create_default_files(const char *template_path,
 	init_db_template_dir = NULL; /* re-set in case it was set before */
 	git_config(git_init_db_config, NULL);

+	if (initial_branch) {
+		path = git_path_buf(&buf, "HEAD");
+		override_HEAD_in_templates = access(path, R_OK) ||
+			readlink(path, junk, sizeof(junk)-1) < 0;
+	}
+
 	/*
 	 * First copy the templates -- we might have the default
 	 * config file there, in which case we would want to read
@@ -265,7 +271,7 @@ static int create_default_files(const char *template_path,
 	path = git_path_buf(&buf, "HEAD");
 	reinit = (!access(path, R_OK)
 		  || readlink(path, junk, sizeof(junk)-1) != -1);
-	if (!reinit) {
+	if (!reinit || override_HEAD_in_templates) {
 		char *ref;

 		if (!initial_branch)
-- snap --

Note that I initially considered moving the `reinit = [...]` part to before
the `copy_templates()` call, but `reinit` actually does quite a bit more
than just guard the symref creation of `HEAD`: it also guards the
`core.filemode` test, the `core.symlinks` test and the `core.ignoreCase`
test. There _might_ be legitimate use cases to side-step those by
delivering a `HEAD` in the templates (which is, just as setting the
initial branch using templates, a relatively awkward and fragile way to
override it, but hey, we're trying to address exactly such a scenario).

However, even having written the patch (which would still lack a
regression test), I am not 100% certain that we would want to risk
including it in v2.28.0. It strikes me as such a fringe use case (with
relatively obvious ways out) while the patch is not completely risk free
(I _think_ it should be safe, of course, but it touches a relatively
central part of Git).

Ciao,
Dscho

← back to recent threads