Allow overriding the default name of the default branch

Started by Johannes Schindelin via GitGitGadget on Jun 10, 2020 · 101 messages from 16 authors · Last reply Jul 13, 2020

Series

9 patches, 16 files

+146 −22

Subsystems (2)

Maintainers (2)

STALE2307d SUPERSEDED

Status: Superseded by v4 (posted 2020-06-24). [go to v4]

Revision v1 (4 revisions archived).

Revisions (4)
  1. v1 current
  2. v2 [diff against previous]
  3. v3 [diff against previous]
  4. v4 [diff against previous]

page 1 of 2 · open the first message on its own page

  1. [PATCH 1/9] init: allow overriding the default branch name for new repositories
    Revisions and related patches
    Revisions (4)
    1. v1 current
    2. v2 [diff against previous]
    3. v3 [diff against previous]
    4. v4 [diff against previous]
  2. [PATCH 3/9] send-pack/transport-helper: respect `core.defaultBranchName`
    Revisions and related patches
    Revisions (4)
    1. v1 current
    2. v2 [diff against previous]
    3. v3 [diff against previous]
    4. v4 [diff against previous]
  3. [PATCH 2/9] remote: respect `core.defaultBranchName`
    Revisions and related patches
    Revisions (4)
    1. v1 current
    2. v2 [diff against previous]
    3. v3 [diff against previous]
    4. v4 [diff against previous]
  4. [PATCH 7/9] fmt-merge-msg: learn about the possibly-configured default branch name
    Revisions and related patches
    Revisions (4)
    1. v1 current
    2. v2 [diff against previous]
    3. v3 [diff against previous]
    4. v4 [diff against previous]
  5. [PATCH 6/9] clone: learn about the possibly-configured default branch name
    Revisions and related patches
    Revisions (4)
    1. v1 current
    2. v2 [diff against previous]
    3. v3 [diff against previous]
    4. v4 [diff against previous]
  6. [PATCH 8/9] fast-export: respect the possibly-overridden default branch name
    Revisions and related patches
    Revisions (4)
    1. v1 current
    2. v2 [diff against previous]
    3. v3 [diff against previous]
    4. v4 [diff against previous]
  7. [PATCH 9/9] Document how the default branch name can be overridden
    Revisions and related patches
    Revisions (3)
    1. v1 current
    2. v2 [diff against previous]
    3. v4 [diff against previous]
  8. [PATCH 5/9] submodule: use the (possibly overridden) default branch name
    Revisions and related patches
    Revisions (4)
    1. v1 current
    2. v2 [diff against previous]
    3. v3 [diff against previous]
    4. v4 [diff against previous]
  9. [PATCH 4/9] testsvn: respect `core.defaultBranchName`
    Revisions and related patches
    Revisions (4)
    1. v1 current
    2. v2 [diff against previous]
    3. v3 [diff against previous]
    4. v4 [diff against previous]
  10. [PATCH v2 01/12] fast-export: do anonymize the primary branch name
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 current [diff against previous]
    3. v3 [diff against previous]
    4. v4 [diff against previous]
  11. [PATCH v2 02/12] fmt-merge-msg: introduce a way to override the main branch name
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 current [diff against previous]
    3. v3 [diff against previous]
    4. v4 [diff against previous]
  12. [PATCH v2 05/12] fast-export: handle overridden main branch names correctly
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 current [diff against previous]
    3. v3 [diff against previous]
    4. v4 [diff against previous]
  13. [PATCH v2 04/12] git_main_branch_name(): optionally report the full ref name
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 current [diff against previous]
    3. v3 [diff against previous]
    4. v4 [diff against previous]
  14. [PATCH v2 03/12] send-pack/transport-helper: respect `core.mainBranch`
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 current [diff against previous]
    3. v3 [diff against previous]
    4. v4 [diff against previous]
  15. [PATCH v2 06/12] branch -m: adjust `core.mainBranch` if necessary
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 current [diff against previous]
    3. v3 [diff against previous]
    4. v4 [diff against previous]
  16. [PATCH v2 12/12] testsvn: respect `init.defaultBranch`
    Related patches
  17. [PATCH v2 10/12] remote: learn about the possibly-overridden default main branch name
    Related patches
  18. [PATCH v2 11/12] submodule: use the correct default for the main branch name
    Related patches
  19. [PATCH v2 09/12] clone: handle overridden main branch names
    Revisions and related patches
    Revisions (3)
    1. v1
    2. v2 current [diff against previous]
    3. v4 [diff against previous]
  20. [PATCH v2 08/12] init: allow overriding the default main branch name via the config
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 current [diff against previous]
    3. v3 [diff against previous]
    4. v4 [diff against previous]
  21. [PATCH v2 07/12] init: allow specifying the main branch name for the new repository
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 current [diff against previous]
    3. v3 [diff against previous]
    4. v4 [diff against previous]
  22. [PATCH v3 2/8] send-pack/transport-helper: avoid mentioning a particular branch
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 [diff against previous]
    3. v3 current [diff against previous]
    4. v4 [diff against previous]
  23. [PATCH v3 1/8] fmt-merge-msg: stop treating `master` specially
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 [diff against previous]
    3. v3 current [diff against previous]
    4. v4 [diff against previous]
  24. [PATCH v3 8/8] testsvn: respect `init.defaultBranch`
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 [diff against previous]
    3. v3 current [diff against previous]
    4. v4 [diff against previous]
  25. [PATCH v3 4/8] init: allow specifying the initial branch name for the new repository
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 [diff against previous]
    3. v3 current [diff against previous]
    4. v4 [diff against previous]
  26. [PATCH v3 7/8] remote: use the configured default branch name when appropriate
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 [diff against previous]
    3. v3 current [diff against previous]
    4. v4 [diff against previous]
  27. [PATCH v3 3/8] submodule: use a better fall-back for missing remote.<name>.branch
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 [diff against previous]
    3. v3 current [diff against previous]
    4. v4 [diff against previous]
  28. [PATCH v3 6/8] clone: use configured default branch name when appropriate
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 [diff against previous]
    3. v3 current [diff against previous]
    4. v4 [diff against previous]
  29. [PATCH v3 5/8] init: allow setting the default for the initial branch name via the config
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 [diff against previous]
    3. v3 current [diff against previous]
    4. v4 [diff against previous]
  30. [PATCH v4 2/9] send-pack/transport-helper: avoid mentioning a particular branch
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 [diff against previous]
    3. v3 [diff against previous]
    4. v4 current [diff against previous]
  31. [PATCH v4 7/9] clone: use configured default branch name when appropriate
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 [diff against previous]
    3. v3 [diff against previous]
    4. v4 current [diff against previous]
  32. [PATCH v4 9/9] testsvn: respect `init.defaultBranch`
    Revisions and related patches
    Revisions (3)
    1. v1
    2. v2 [diff against previous]
    3. v4 current [diff against previous]
  33. [PATCH v4 8/9] remote: use the configured default branch name when appropriate
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 [diff against previous]
    3. v3 [diff against previous]
    4. v4 current [diff against previous]
  34. [PATCH v4 4/9] docs: add missing diamond brackets
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 [diff against previous]
    3. v3 [diff against previous]
    4. v4 current [diff against previous]
  35. [PATCH v4 3/9] submodule: fall back to remote's HEAD for missing remote.<name>.branch
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 [diff against previous]
    3. v3 [diff against previous]
    4. v4 current [diff against previous]
  36. [PATCH v4 1/9] fmt-merge-msg: stop treating `master` specially
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 [diff against previous]
    3. v3 [diff against previous]
    4. v4 current [diff against previous]
  37. [PATCH v4 6/9] init: allow setting the default for the initial branch name via the config
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 [diff against previous]
    3. v3 [diff against previous]
    4. v4 current [diff against previous]
  38. [PATCH v4 5/9] init: allow specifying the initial branch name for the new repository
    Revisions and related patches
    Revisions (4)
    1. v1
    2. v2 [diff against previous]
    3. v3 [diff against previous]
    4. v4 current [diff against previous]
Message details and related content
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

36 more lines

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

Message details and related content
From: Don Goodman-Wilson <redacted>

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 [off-list ref]
Helped-by: Derrick Stolee [off-list ref]
Signed-off-by: Don Goodman-Wilson <redacted>
---
 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);
+
+	/* 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

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

Message details and related content
From: Johannes Schindelin <redacted>

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 <redacted>
---
 send-pack.c        | 6 +++++-
 transport-helper.c | 6 +++++-
 2 files changed, 10 insertions(+), 2 deletions(-)
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

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

Message details and related content
From: Johannes Schindelin <redacted>

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 <redacted>
---
 remote.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
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

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

Message details and related content
From: Johannes Schindelin <redacted>

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 <redacted>
---
 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);
 }
 
 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

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

Message details and related content
From: Johannes Schindelin <redacted>

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 <redacted>
---
 builtin/clone.c         | 14 +++++++++++---
 t/t5609-clone-branch.sh |  9 +++++++++
 2 files changed, 20 insertions(+), 3 deletions(-)
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

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

Message details and related content
From: Johannes Schindelin <redacted>

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 <redacted>
---
 builtin/fast-export.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
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

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

Message details and related content
From: Johannes Schindelin <redacted>

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 <redacted>
---
 Documentation/config/core.txt | 4 ++++
 t/README                      | 4 ++++
 2 files changed, 8 insertions(+)
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

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

Message details and related content
From: Johannes Schindelin <redacted>

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 <redacted>
---
 builtin/submodule--helper.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
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

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

Message details and related content
From: Johannes Schindelin <redacted>

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

Signed-off-by: Johannes Schindelin <redacted>
---
 remote-testsvn.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)
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

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

Message details and related content
quoted hunk
-        * 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

-       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

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

Message details and related content
On 2020-06-10 at 21:19:22, Don Goodman-Wilson via GitGitGadget wrote:
quoted hunk
+	/* 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.
quoted hunk
+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

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

Message details and related content
On 2020-06-10 at 21:54:01, Matt Rogers wrote:
quoted
-        * 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
Message details and related content
On 2020-06-10 at 21:19:21, 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 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

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

Message details and related content
On Wed, Jun 10, 2020 at 5:19 PM Don Goodman-Wilson via GitGitGadget
[off-list ref] wrote:
quoted hunk
[...]
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 <redacted>
---
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...
quoted hunk
+               if (from_config)
+                       branch_name = from_config;
+               else
+                       branch_name = "master";
Non-actionable nit: could be written:

    branch_name = from_config ? from_config : "master";
quoted hunk
+       }
+
+       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.
quoted hunk
+       /* 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.
quoted hunk
+/*
+ * 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.

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

Message details and related content
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?
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
Message details and related content
Hi Johannes (and Dan)

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

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

Message details and related content
On 10/06/2020 22:19, Don Goodman-Wilson via GitGitGadget wrote:
From: Don Goodman-Wilson <redacted>

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
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.
quoted hunk
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 [off-list ref]
Helped-by: Derrick Stolee [off-list ref]
Signed-off-by: Don Goodman-Wilson <redacted>
---
 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);

36 more quoted lines

If short_name is set we return without validating the name is that
intentional?
quoted hunk
+
+	/* 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.
quoted hunk
+ */
+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.
quoted hunk
+	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
quoted hunk
+	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

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

Message details and related content
Hi Don & Johannes,

Le 10/06/2020 à 23:19, Don Goodman-Wilson via GitGitGadget a écrit :
From: Don Goodman-Wilson <redacted>

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

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

Message details and related content
Hi Matt,

On Wed, 10 Jun 2020, Matt Rogers wrote:
quoted
-        * 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

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

Message details and related content
Hi Eric,

On Wed, 10 Jun 2020, Eric Sunshine wrote:
On Wed, Jun 10, 2020 at 5:19 PM Don Goodman-Wilson via GitGitGadget
[off-list ref] wrote:
quoted
[...]
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 <redacted>
---
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...
quoted
+               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.
quoted
+       }
+
+       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.
quoted
+       /* 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.
quoted
+/*
+ * 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
Message details and related content
Hi Taylor,

On Wed, 10 Jun 2020, Taylor Blau wrote:
On Wed, Jun 10, 2020 at 09:19:21PM +0000, Johannes Schindelin via GitGitGadget wrote:
quoted
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.
quoted
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 ;-)
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.
quoted
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.
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.
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

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

Message details and related content
Hi Phillip,

On Thu, 11 Jun 2020, Phillip Wood wrote:
On 10/06/2020 22:19, Don Goodman-Wilson via GitGitGadget wrote:
quoted
From: Don Goodman-Wilson <redacted>

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/).
quoted
 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.
quoted
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).
quoted
+
+	/* 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.
quoted
+ */
+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`.
quoted
+	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
Message details and related content
Hi,

On 10/06/20 09:19PM, 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 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

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

Message details and related content
On Wed, Jun 10, 2020 at 09:19:26PM +0000, Johannes Schindelin via GitGitGadget wrote:
From: Johannes Schindelin <redacted>

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 <redacted>
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.
Message details and related content
Hi Pratyush,

On Mon, 15 Jun 2020, Pratyush Yadav wrote:
On 10/06/20 09:19PM, Johannes Schindelin via GitGitGadget wrote:
quoted
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.
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...
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

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

Message details and related content
From: Junio C Hamano <redacted>

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 <redacted>
Signed-off-by: Johannes Schindelin <redacted>
---
 builtin/fast-export.c            | 9 +++++----
 t/t9351-fast-export-anonymize.sh | 9 +++++----
 2 files changed, 10 insertions(+), 8 deletions(-)
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

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

Message details and related content
From: Johannes Schindelin <redacted>

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 <redacted>
---
 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);
+
+	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

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

Message details and related content
From: Johannes Schindelin <redacted>

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 <redacted>
---
 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";
 
 	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

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

Message details and related content
From: Johannes Schindelin <redacted>

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 <redacted>
---
 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);
 
 	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

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

Message details and related content
From: Johannes Schindelin <redacted>

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 <redacted>
---
 send-pack.c             | 6 +++++-
 t/t5528-push-default.sh | 7 +++++++
 transport-helper.c      | 6 +++++-
 3 files changed, 17 insertions(+), 2 deletions(-)
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

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

Message details and related content
From: Johannes Schindelin <redacted>

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 <redacted>
---
 builtin/branch.c  | 9 +++++++++
 t/t3200-branch.sh | 9 +++++++++
 2 files changed, 18 insertions(+)
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

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

Message details and related content
From: Johannes Schindelin <redacted>

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 <redacted>
---
 remote-testsvn.c      | 12 +++++++++---
 t/t9020-remote-svn.sh |  6 ++++++
 2 files changed, 15 insertions(+), 3 deletions(-)
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

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

Message details and related content
From: Johannes Schindelin <redacted>

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 <redacted>
---
 remote.c                 | 15 ++++++++++-----
 t/t5606-clone-options.sh | 11 ++++++++++-
 2 files changed, 20 insertions(+), 6 deletions(-)
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

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

Message details and related content
From: Johannes Schindelin <redacted>

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 <redacted>
---
 builtin/submodule--helper.c | 10 ++++++++--
 t/t7406-submodule-update.sh |  7 +++++++
 2 files changed, 15 insertions(+), 2 deletions(-)
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

[PATCH v2 09/12] clone: handle overridden main branch names

Message details and related content
From: Johannes Schindelin <redacted>

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 <redacted>
---
 Documentation/config/init.txt |  4 ++--
 builtin/clone.c               | 16 +++++++++++++---
 t/t5606-clone-options.sh      | 17 +++++++++++++++++
 3 files changed, 32 insertions(+), 5 deletions(-)
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

[PATCH v2 08/12] init: allow overriding the default main branch name via the config

Message details and related content
From: Don Goodman-Wilson <redacted>

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 [off-list ref]
Helped-by: Derrick Stolee [off-list ref]
Signed-off-by: Don Goodman-Wilson <redacted>
---
 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(-)
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

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

Revisions (4)
  1. v1
  2. v2 current [diff against previous]
  3. v3 [diff against previous]
  4. v4 [diff against previous]
Message details and related content
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

972 more lines

[PATCH v2 07/12] init: allow specifying the main branch name for the new repository

Message details and related content
From: Johannes Schindelin <redacted>

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 <redacted>
---
 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(-)
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

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

Message details and related content
Hi dscho

On 15/06/2020 13:50, Johannes Schindelin via GitGitGadget wrote:
From: Johannes Schindelin <redacted>

There is a growing number of projects and companies desiring to change
the main branch name of their repositories (see e.g.
https://twitter.com/mislav/status/1270388510684598272 for background on
this).
I think this is a good way of phrasing the rationale for the change
However, there are a couple of hard-coded spots in Git's source code
that make this endeavor harder than necessary. For example, when
formatting the commit message for merge commits, Git appends "into
<branch-name>" unless the current branch is the `master` branch.

Clearly, this is not what one wants when already having gone through all
the steps to manually rename the main branch
This didn't quite scan for me maybe s/already having/one has already/ ?
quoted hunk
(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 <redacted>
---
  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;

45 more quoted lines

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.
quoted hunk
+
+	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
quoted hunk
+ * 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}

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

Message details and related content
Hi dscho

On 15/06/2020 13:50, Johannes Schindelin via GitGitGadget wrote:
quoted hunk
From: Johannes Schindelin <redacted>

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

15 more quoted lines

This looks good, we always check the name before returning it and free name if we're returning refs/heads/<name>
quoted hunk
  	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
quoted hunk
-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"

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

Message details and related content
Hi dscho

On 15/06/2020 13:50, Johannes Schindelin via GitGitGadget wrote:
quoted hunk
From: Johannes Schindelin <redacted>

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

1 more quoted lines

This leaks main_branch if it came from git_main_branch_name()

Best Wishes

Phillip
quoted hunk
  	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
Message details and related content
On 2020-06-15 at 10:03:27, Pratyush Yadav 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...
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
Message details and related content
Hi Dscho,

On Mon, Jun 15, 2020 at 12:26:03AM +0200, Johannes Schindelin wrote:
quoted
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

30 more lines

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

Message details and related content
On Mon, Jun 15 2020, Johannes Schindelin via GitGitGadget wrote:
From: Johannes Schindelin <redacted>
quoted hunk
+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.
Message details and related content
On Wed, Jun 10 2020, 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.
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

37 more lines

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

Message details and related content
On Wed, Jun 10, 2020 at 09:19:23PM +0000, Johannes Schindelin via GitGitGadget wrote:
quoted hunk
@@ -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

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

Message details and related content
On Wed, Jun 10, 2020 at 08:16:38PM -0400, Eric Sunshine wrote:
quoted
+/*
+ * 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

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

Message details and related content
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:
quoted
quoted
+/*
+ * 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

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

Message details and related content
On Mon, Jun 15, 2020 at 12:50:05PM +0000, Junio C Hamano via GitGitGadget wrote:
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

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

Message details and related content
On Mon, Jun 15, 2020 at 12:50:06PM +0000, Johannes Schindelin via GitGitGadget wrote:
quoted hunk
+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

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

Message details and related content
On Mon, Jun 15, 2020 at 04:05:52PM +0100, Phillip Wood wrote:
quoted
@@ -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;
[...]
quoted
-	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

Re: [PATCH v2 09/12] clone: handle overridden main branch names

Message details and related content
On Mon, Jun 15, 2020 at 12:50:13PM +0000, Johannes Schindelin via GitGitGadget wrote:
quoted hunk
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

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

Message details and related content
On Mon, Jun 15, 2020 at 12:50:15PM +0000, Johannes Schindelin via GitGitGadget wrote:
From: Johannes Schindelin <redacted>

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"

15 more lines

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

Message details and related content
On Mon, Jun 15, 2020 at 12:50:16PM +0000, Johannes Schindelin via GitGitGadget wrote:
From: Johannes Schindelin <redacted>

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/
Message details and related content
On Tue, Jun 16, 2020 at 11:47:10AM +0200, Ævar Arnfjörð Bjarmason wrote:
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.
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.
 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.
 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
Message details and related content
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

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

Message details and related content
Hi Peff

On 16/06/2020 14:10, Jeff King wrote:
On Mon, Jun 15, 2020 at 04:05:52PM +0100, Phillip Wood wrote:
quoted
quoted
@@ -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;
[...]
quoted
-	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
(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

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

Message details and related content
Am 15.06.20 um 14:50 schrieb Johannes Schindelin via GitGitGadget:
quoted hunk
@@ -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

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

Message details and related content
Hi Peff,

On Tue, 16 Jun 2020, Jeff King wrote:
On Mon, Jun 15, 2020 at 04:05:52PM +0100, Phillip Wood wrote:
quoted
quoted
@@ -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;
[...]
quoted
-	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

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

Message details and related content
Hi Peff,

On Tue, 16 Jun 2020, Jeff King wrote:
On Wed, Jun 10, 2020 at 09:19:23PM +0000, Johannes Schindelin via GitGitGadget wrote:
quoted
@@ -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))

12 more quoted lines

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

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

Message details and related content
On Thu, Jun 18, 2020 at 12:21:30PM +0200, Johannes Schindelin wrote:
quoted
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

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

Message details and related content
Hi Peff,

On Tue, 16 Jun 2020, Jeff King wrote:
On Tue, Jun 16, 2020 at 08:45:02AM -0400, Jeff King wrote:
quoted
On Wed, Jun 10, 2020 at 08:16:38PM -0400, Eric Sunshine wrote:
quoted
quoted
+/*
+ * 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.

3 more quoted lines

Legit.

I will work on this.

Thanks,
Dscho

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

Message details and related content
Hi Phillip,

On Mon, 15 Jun 2020, Phillip Wood wrote:
On 15/06/2020 13:50, Johannes Schindelin via GitGitGadget wrote:
quoted
From: Johannes Schindelin <redacted>

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>`.
quoted
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.
quoted
(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 <redacted>
---
  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;

48 more quoted lines

Right.

But as I am dropping the concept of `core.mainBranch` from v3, this won't
apply anymore.
quoted
+
+	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
Best Wishes

Phillip
quoted
+ * 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}

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

Message details and related content
Hi Phillip,

On Mon, 15 Jun 2020, Phillip Wood wrote:
On 15/06/2020 13:50, Johannes Schindelin via GitGitGadget wrote:
quoted
From: Johannes Schindelin <redacted>

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 <redacted>
---
  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);
  }

50 more quoted lines

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
Best Wishes

Phillip
quoted
-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"

1 more quoted lines

Message details and related content
Hi Denton,

On Mon, 15 Jun 2020, Denton Liu wrote:
On Mon, Jun 15, 2020 at 12:26:03AM +0200, Johannes Schindelin wrote:
quoted
quoted
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.

48 more quoted lines

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
Message details and related content
Hi Peff & Ævar,

On Tue, 16 Jun 2020, Jeff King wrote:
On Tue, Jun 16, 2020 at 10:09:32AM -0400, Jeff King wrote:
quoted
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:
  - 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

Re: [PATCH v2 09/12] clone: handle overridden main branch names

Message details and related content
Hi Peff,

On Tue, 16 Jun 2020, Jeff King wrote:
On Mon, Jun 15, 2020 at 12:50:13PM +0000, Johannes Schindelin via GitGitGadget wrote:
quoted
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`.
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

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

Message details and related content
Hi Peff,

On Tue, 16 Jun 2020, Jeff King wrote:
On Mon, Jun 15, 2020 at 12:50:15PM +0000, Johannes Schindelin via GitGitGadget wrote:
quoted
From: Johannes Schindelin <redacted>

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

14 more quoted lines

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

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

Message details and related content
Hi Peff,

On Tue, 16 Jun 2020, Jeff King wrote:
On Mon, Jun 15, 2020 at 12:50:16PM +0000, Johannes Schindelin via GitGitGadget wrote:
quoted
From: Johannes Schindelin <redacted>

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

[1] https://lore.kernel.org/git/20180818052605.GA241538@aiede.svl.corp.google.com/

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

Message details and related content
Hi Peff,


On Tue, 16 Jun 2020, Jeff King wrote:
On Wed, Jun 10, 2020 at 08:16:38PM -0400, Eric Sunshine wrote:
quoted
quoted
+/*
+ * 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.)
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

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

Message details and related content
On Tue, Jun 23, 2020 at 11:03:57PM +0200, Johannes Schindelin wrote:
quoted
[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

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

Message details and related content
Hi Peff,

On Thu, 18 Jun 2020, Jeff King wrote:
On Thu, Jun 18, 2020 at 12:21:30PM +0200, Johannes Schindelin wrote:
quoted
quoted
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

[PATCH v3 2/8] send-pack/transport-helper: avoid mentioning a particular branch

Message details and related content
From: Johannes Schindelin <redacted>

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 <redacted>
---
 send-pack.c             | 2 +-
 t/t5528-push-default.sh | 6 ++++++
 transport-helper.c      | 2 +-
 3 files changed, 8 insertions(+), 2 deletions(-)
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

[PATCH v3 1/8] fmt-merge-msg: stop treating `master` specially

Message details and related content
From: Johannes Schindelin <redacted>

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 <redacted>
---
 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(-)
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
Keyboard shortcuts
hback out one level
jnext message in thread / next series-diff position
kprevious message in thread / previous series-diff position
ldrill in
Escclose help / fold thread tree
?toggle this help