Skip to contentSkip to conversation

Allow overriding the default name of the default branch

PATCH Superseded Johannes Schindelin via GitGitGadget 18 participants 180 messages Jun 10, 2020 – Jul 14, 2020 1 message not in the archive Documentation Page 1 of 2

lore
Share & tools
lore
#0 lore raw

cover Allow overriding the default name of the default branch

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

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

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

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

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

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

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

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

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

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

Don Goodman-Wilson (1):
init: allow overriding the default branch name for new repositories

Johannes Schindelin (8):
remote: respect core.defaultBranchName send-pack/transport-helper: respect core.defaultBranchName
testsvn: respect core.defaultBranchName
submodule: use the (possibly overridden) default branch name
clone: learn about the possibly-configured default branch name
fmt-merge-msg: learn about the possibly-configured default branch name
fast-export: respect the possibly-overridden default branch name Document how the default branch name can be overridden

 Documentation/config/core.txt |  4 ++++
 builtin/clone.c               | 14 +++++++++++---
 builtin/fast-export.c         | 10 +++++++---
 builtin/init-db.c             |  8 +++++---
 builtin/submodule--helper.c   | 10 ++++++++--
 fmt-merge-msg.c               |  6 ++++--
 refs.c                        | 34 ++++++++++++++++++++++++++++++++++
 refs.h                        |  6 ++++++
 remote-testsvn.c              | 11 ++++++++---
 remote.c                      | 12 ++++++++----
 send-pack.c                   |  6 +++++-
 t/README                      |  4 ++++
 t/t0001-init.sh               | 20 ++++++++++++++++++++
 t/t5609-clone-branch.sh       |  9 +++++++++
 t/t6200-fmt-merge-msg.sh      |  8 ++++++++
 transport-helper.c            |  6 +++++-
 16 files changed, 146 insertions(+), 22 deletions(-)

base-commit: 0313f36c6ebecb3bffe6f15cf25a4883100f0214
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-656%2Fdscho%2Fdefault-branch-name-option-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-656/dscho/default-branch-name-option-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/656

Signature · 1 line
gitgitgadget
#1 lore raw

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

From: Don Goodman-Wilson <[email protected]>

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.

---
 builtin/init-db.c |  8 +++++---
 refs.c            | 34 ++++++++++++++++++++++++++++++++++
 refs.h            |  6 ++++++
 t/t0001-init.sh   | 20 ++++++++++++++++++++
 4 files changed, 65 insertions(+), 3 deletions(-)
builtin/init-db.c +5 -3
index 0b7222e7188..99792adfd43 100644
@@ -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);
refs.c +34 -0
index 224ff66c7bb..8499b3865cb 100644
@@ -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
refs.h +6 -0
index a92d2c74c83..e8d4f6e2f13 100644
@@ -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.
t/t0001-init.sh +20 -0
index 1edd5aeb8f0..b144cd8f46b 100755
@@ -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
Signature · 1 line
gitgitgadget
#2 lore raw

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

refs.c void expand_ref_prefix(struct argv_array *prefixes, const char *prefix) · line 591

Quoted 4 lines · Don Goodman-Wilson via GitGitGadget
refs.c +4 -0
+	/* 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 6 lines
t/t0001-init.sh +6 -0
+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
+'
+
Signature · 2 lines
brian m. carlson: Houston, Texas, US
OpenPGP: https://keybase.io/bk2204
#3 lore raw

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

In reply to Don Goodman-Wilson via GitGitGadget

refs.c void expand_ref_prefix(struct argv_array *prefixes, const char *prefix) · line 560

Quoted 11 lines · Don Goodman-Wilson via GitGitGadget

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

---

refs.c +1 -0
@@ -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...

refs.c void expand_ref_prefix(struct argv_array *prefixes, const char *prefix) · line 582

Quoted 4 lines
refs.c +4 -0
+               if (from_config)
+                       branch_name = from_config;
+               else
+                       branch_name = "master";

Non-actionable nit: could be written:

    branch_name = from_config ? from_config : "master";

refs.c void expand_ref_prefix(struct argv_array *prefixes, const char *prefix) · line 586

Quoted 4 lines
refs.c +4 -0
+       }
+
+       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.

refs.c void expand_ref_prefix(struct argv_array *prefixes, const char *prefix) · line 591

Quoted 4 lines
refs.c +4 -0
+       /* 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.

refs.c void expand_ref_prefix(struct argv_array *prefixes, const char *prefix) · line 577

Quoted 5 lines
refs.c +5 -0
+/*
+ * 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.

#4 lore raw

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

Hi Eric,

Quoted 15 lines · Eric Sunshine

refs.c void expand_ref_prefix(struct argv_array *prefixes, const char *prefix) · line 560

Quoted 11 lines · Don Goodman-Wilson via GitGitGadget

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

---

refs.c +1 -0
@@ -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 8 lines

refs.c void expand_ref_prefix(struct argv_array *prefixes, const char *prefix) · line 582

Quoted 4 lines
refs.c +4 -0
+               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 8 lines

refs.c void expand_ref_prefix(struct argv_array *prefixes, const char *prefix) · line 586

Quoted 4 lines
refs.c +4 -0
+       }
+
+       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 19 lines

refs.c void expand_ref_prefix(struct argv_array *prefixes, const char *prefix) · line 591

Quoted 4 lines
refs.c +4 -0
+       /* 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.

refs.c void expand_ref_prefix(struct argv_array *prefixes, const char *prefix) · line 577

Quoted 5 lines
refs.c +5 -0
+/*
+ * 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:

Quoted 4 lines
    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

#5 lore raw

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

Quoted 9 lines · Johannes Schindelin
Quoted 7 lines

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

    char *git_default_branch_name(void);
    char *git_default_ref_name(void);

but that's subjective.

For such a tiny nuance, I'd rather keep it as one function...

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

#6 lore raw

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

In reply to Eric Sunshine
Quoted 9 lines · Eric Sunshine

refs.h int repo_dwim_log(struct repository *r, const char *str, int len, struct object_ · line 161

Quoted 5 lines
refs.h +5 -0
+/*
+ * 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:

Quoted 4 lines
    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

#7 lore raw

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

Quoted 25 lines · Jeff King
Quoted 9 lines · Eric Sunshine

refs.h int repo_dwim_log(struct repository *r, const char *str, int len, struct object_ · line 161

Quoted 5 lines
refs.h +5 -0
+/*
+ * 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:

Quoted 4 lines
    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)?

Quoted 7 lines

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

#8 lore raw

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

Hi Peff,

Quoted 35 lines · Jeff King
Quoted 25 lines · Jeff King
Quoted 9 lines · Eric Sunshine

refs.h int repo_dwim_log(struct repository *r, const char *str, int len, struct object_ · line 161

Quoted 5 lines
refs.h +5 -0
+/*
+ * 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:

Quoted 4 lines
    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)?

Quoted 7 lines

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

}

Quoted 8 lines

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

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

Legit.

I will work on this.

Thanks,
Dscho

#9 lore raw

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

In reply to Jeff King

Hi Peff,

Quoted 11 lines · Jeff King
Quoted 9 lines · Eric Sunshine

refs.h int repo_dwim_log(struct repository *r, const char *str, int len, struct object_ · line 161

Quoted 5 lines
refs.h +5 -0
+/*
+ * 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:

Quoted 7 lines
Quoted 4 lines
    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.)

Quoted 6 lines

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

Quoted 7 lines

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

#10 lore raw

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

In reply to Don Goodman-Wilson via GitGitGadget
Quoted 4 lines · Don Goodman-Wilson via GitGitGadget

From: Don Goodman-Wilson <[email protected]>

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

Quoted 6 lines

requires manual work. For new repositories, the only way to do that automatically is by copying all of Git's template directory, then hard-coding the desired default branch name into the .git/HEAD file, and then configuring init.templateDir to point to those copied template files.

Quoted 7 lines

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

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 66 lines

in preparation for
adjusting Git's test suite to a more inclusive default branch name. As is common in Git, the GIT_TEST_* variable takes precedence over the config setting.

Note: we use the prefix core. instead of init. because we want to adjust also git clone, git fmt-merge-msg and other commands over the course of the next commits to respect this setting.

---
 builtin/init-db.c |  8 +++++---
 refs.c            | 34 ++++++++++++++++++++++++++++++++++
 refs.h            |  6 ++++++
 t/t0001-init.sh   | 20 ++++++++++++++++++++
 4 files changed, 65 insertions(+), 3 deletions(-)
builtin/init-db.c +5 -3
index 0b7222e7188..99792adfd43 100644
@@ -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);
refs.c +14 -0
index 224ff66c7bb..8499b3865cb 100644
@@ -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)

refs.c void expand_ref_prefix(struct argv_array *prefixes, const char *prefix) · line 586

Quoted 10 lines
refs.c +10 -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?

Quoted 18 lines
refs.c +10 -0
+
+	/* 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
refs.h +0 -0
index a92d2c74c83..e8d4f6e2f13 100644

refs.h int repo_dwim_log(struct repository *r, const char *str, int len, struct object_ · line 159

Quoted 6 lines
refs.h +3 -0
@@ -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 11 lines
refs.h +3 -0
+ */
+char *git_default_branch_name(int short_name);
+
 /*
  * A ref_transaction represents a collection of reference updates that
  * should succeed or fail together.
t/t0001-init.sh +0 -0
index 1edd5aeb8f0..b144cd8f46b 100755

t/t0001-init.sh test_expect_success MINGW 'redirect std handles' ' · line 468

Quoted 5 lines
t/t0001-init.sh +2 -0
@@ -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.

t/t0001-init.sh test_expect_success MINGW 'redirect std handles' ' · line 476

Quoted 8 lines
t/t0001-init.sh +8 -0
+	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 12 lines
t/t0001-init.sh +10 -0
+	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
#11 lore raw

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

Hi Phillip,

Quoted 9 lines · Phillip Wood
Quoted 4 lines · Don Goodman-Wilson via GitGitGadget

From: Don Goodman-Wilson <[email protected]>

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.

Quoted 2 lines

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

Quoted 3 lines

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/[email protected]/).

Quoted 12 lines
Quoted 12 lines

For existing repositories, this
requires manual work. For new repositories, the only way to do that automatically is by copying all of Git's template directory, then hard-coding the desired default branch name into the .git/HEAD file, and then configuring init.templateDir to point to those copied template files.

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

Quoted 5 lines
Quoted 2 lines

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 27 lines
Quoted 27 lines
refs.c +19 -0
index 224ff66c7bb..8499b3865cb 100644
@@ -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
Quoted 8 lines

refs.c void expand_ref_prefix(struct argv_array *prefixes, const char *prefix) · line 586

Quoted 5 lines
refs.c +5 -0
+			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 21 lines
Quoted 21 lines
refs.c +10 -0
+
+	/* 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
refs.h +0 -0
index a92d2c74c83..e8d4f6e2f13 100644
@@ -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);
 
Quoted 6 lines

refs.h int repo_dwim_log(struct repository *r, const char *str, int len, struct object_ · line 159

Quoted 3 lines
refs.h +3 -0
+/*
+ * 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 14 lines
Quoted 14 lines
refs.h +3 -0
+ */
+char *git_default_branch_name(int short_name);
+
 /*
  * A ref_transaction represents a collection of reference updates that
  * should succeed or fail together.
t/t0001-init.sh +0 -0
index 1edd5aeb8f0..b144cd8f46b 100755
@@ -464,4 +464,24 @@ test_expect_success MINGW 'redirect std handles' '
 	grep "Needed a single revision" output.txt
 '
 
Quoted 5 lines

t/t0001-init.sh test_expect_success MINGW 'redirect std handles' ' · line 468

Quoted 2 lines
t/t0001-init.sh +2 -0
+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 10 lines

t/t0001-init.sh test_expect_success MINGW 'redirect std handles' ' · line 476

Quoted 8 lines
t/t0001-init.sh +8 -0
+	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

#12 lore raw

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

Quoted 4 lines · Johannes Schindelin

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

Sensible.

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

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

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

#13 lore raw

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

Quoted 7 lines · Junio C Hamano
Quoted 4 lines · Johannes Schindelin

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.

Quoted 8 lines

[...]

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

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

Quoted 3 lines

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

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

Best Wishes

Phillip

#14 lore raw

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

In reply to Junio C Hamano

Hi Junio,

Quoted 11 lines · Junio C Hamano
Quoted 4 lines · Johannes Schindelin

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

Sensible.

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

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

Quoted 4 lines

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

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

I picked the names "master" (and "origin") in the early Git tooling back in 2005.

(this probably means you shouldn't give much weight to my name preferences :) )

I have wished many times I would have named them "main" (and "upstream") instead.

Quoted 5 lines

In other words, we do not have to explain why 'master' was bad, as it does not have to be bad for everybody to be replaced.

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

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

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

Ciao,
Dscho

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

#15 lore raw

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

In reply to Don Goodman-Wilson via GitGitGadget

Hi Don & Johannes,

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

Quoted 15 lines

From: Don Goodman-Wilson <[email protected]>

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.

Quoted 6 lines

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

#16 lore raw

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

Quoted 5 lines · Alban Gruin

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

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

And no,

    git () { command git -c core.defaultBranchName=master "$@" }

is not an acceptable solution.

#17 lore raw

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

Quoted 13 lines · Junio C Hamano
Quoted 5 lines · Alban Gruin

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

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

Quoted 5 lines

And no,

    git () { command git -c core.defaultBranchName=master "$@" }

is not an acceptable solution.

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

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

Signature · 2 lines
brian m. carlson: Houston, Texas, US
OpenPGP: https://keybase.io/bk2204
#18 lore raw

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

Hi brian,

Quoted 18 lines · brian m. carlson
Quoted 17 lines · Junio C Hamano
Quoted 5 lines · Alban Gruin

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

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

And no,

    git () { command git -c core.defaultBranchName=master "$@" }
Quoted 7 lines
Quoted 1 line

is not an acceptable solution.

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

That's a valid point, indeed.

Quoted 4 lines

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

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

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

But I agree that few test scripts use it:

	$ git grep 'git init' v2.27.0 -- t/ | wc -l
	765
	$ git grep 'test_create_repo' v2.27.0 -- t/ | wc -l
	296

Ciao,
Dscho

#19 lore raw

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

In reply to Junio C Hamano

Hi Junio,

Le 12/06/2020 à 01:14, Junio C Hamano a écrit :

Quoted 13 lines
Quoted 5 lines · Alban Gruin

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

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

Quoted 6 lines

And no,

    git () { command git -c core.defaultBranchName=master "$@" }

is not an acceptable solution.

I wanted to to do something like this:

if test -n "$GIT_TEST_DEFAULT_BRANCH_NAME";
then
git config core.defaultBranchName "$GIT_TEST_DEFAULT_BRANCH_NAME"
fi

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

Alban

#20 lore raw

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

Hi Alban,

Quoted 25 lines · Alban Gruin

Hi Junio,

Le 12/06/2020 à 01:14, Junio C Hamano a écrit :

Quoted 13 lines
Quoted 5 lines · Alban Gruin

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

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

Quoted 6 lines

And no,

    git () { command git -c core.defaultBranchName=master "$@" }

is not an acceptable solution.

I wanted to to do something like this:

Quoted 7 lines

if test -n "$GIT_TEST_DEFAULT_BRANCH_NAME";
then
git config core.defaultBranchName "$GIT_TEST_DEFAULT_BRANCH_NAME"
fi

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

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

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

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

Ciao,
Dscho

#21 lore raw

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

Quoted 25 lines · Johannes Schindelin
Quoted 25 lines
Quoted 11 lines
Quoted 5 lines

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

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

Quoted 6 lines

And no,

    git () { command git -c core.defaultBranchName=master "$@" }

is not an acceptable solution.

I wanted to to do something like this:

if test -n "$GIT_TEST_DEFAULT_BRANCH_NAME";
then
git config core.defaultBranchName "$GIT_TEST_DEFAULT_BRANCH_NAME"
fi

Quoted 8 lines
Quoted 2 lines

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

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

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

Putting:

GIT_CONFIG_PARAMETERS="'core.defaultBranchName=...'"

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

- there are a few tests which explicitly tweak that variable

- it technically changes any tests of "-c" because now we'd never cover the case where we start without the variable defined

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

-Peff

#22 lore raw

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

Hi Peff,

Quoted 40 lines · Jeff King
Quoted 25 lines · Johannes Schindelin
Quoted 25 lines
Quoted 11 lines
Quoted 5 lines

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

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

Quoted 6 lines

And no,

    git () { command git -c core.defaultBranchName=master "$@" }

is not an acceptable solution.

I wanted to to do something like this:

if test -n "$GIT_TEST_DEFAULT_BRANCH_NAME";
then
git config core.defaultBranchName "$GIT_TEST_DEFAULT_BRANCH_NAME"
fi

Quoted 8 lines
Quoted 2 lines

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

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

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

Putting:

GIT_CONFIG_PARAMETERS="'core.defaultBranchName=...'"

Quoted 8 lines

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

- there are a few tests which explicitly tweak that variable

- it technically changes any tests of "-c" because now we'd never cover the case where we start without the variable defined

Indeed.

Quoted 9 lines

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

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

Thanks,
Dscho

#23 lore raw

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

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

---
 remote.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
remote.c +8 -4
index 534c6426f1e..95fa8cc78e0 100644
@@ -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);
 	}
Signature · 1 line
gitgitgadget
#24 lore raw

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

remote.c struct ref *guess_remote_head(const struct ref *head, · line 2109

Quoted 12 lines · Johannes Schindelin via GitGitGadget
remote.c +4 -1
@@ -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

#25 lore raw

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

Hi Peff,

Quoted 48 lines · Jeff King

remote.c struct ref *guess_remote_head(const struct ref *head, · line 2109

Quoted 12 lines · Johannes Schindelin via GitGitGadget
remote.c +4 -1
@@ -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".

Quoted 4 lines

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

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

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

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

Ciao,
Dscho

#26 lore raw

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

Quoted 11 lines · Johannes Schindelin
Quoted 4 lines

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

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

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

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

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

-Peff

#27 lore raw

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

Hi Peff,

Quoted 19 lines · Jeff King
Quoted 11 lines · Johannes Schindelin
Quoted 4 lines

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

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

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

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

Quoted 6 lines

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

#28 lore raw

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

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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

---
 send-pack.c        | 6 +++++-
 transport-helper.c | 6 +++++-
 2 files changed, 10 insertions(+), 2 deletions(-)
send-pack.c +5 -1
index 0abee22283d..f7747bed1c9 100644
@@ -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)
transport-helper.c +5 -1
index a46afcb69db..cc8ae5c67ca 100644
@@ -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;
 	}
 
Signature · 1 line
gitgitgadget
#29 lore raw

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

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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

---
 remote-testsvn.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)
remote-testsvn.c +8 -3
index 3af708c5b67..a48d74f35cd 100644
@@ -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);
Signature · 1 line
gitgitgadget
#30 lore raw

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

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

---
 builtin/submodule--helper.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
builtin/submodule--helper.c +8 -2
index 46c03d2a126..0b4abb5a64b 100644
@@ -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);
Signature · 1 line
gitgitgadget
#31 lore raw

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

Quoted 7 lines · Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

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.

#32 lore raw

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

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

---
 builtin/clone.c         | 14 +++++++++++---
 t/t5609-clone-branch.sh |  9 +++++++++
 2 files changed, 20 insertions(+), 3 deletions(-)
builtin/clone.c +11 -3
index cb48a291caf..a21d3e99f82 100644
@@ -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,
t/t5609-clone-branch.sh +9 -0
index 6e7a7be0522..66af3ac2669 100755
@@ -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
Signature · 1 line
gitgitgadget
#33 lore raw

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

"Johannes Schindelin via GitGitGadget" <[email protected]>

Quoted 8 lines · writes:
builtin/clone.c +1 -3
@@ -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) {

builtin/clone.c int cmd_clone(int argc, const char **argv, const char *prefix) · line 1276

Quoted 10 lines
builtin/clone.c +10 -0
+			char *default_branch = git_default_branch_name(0);
+			const char *nick;
+
+			if (!skip_prefix(default_branch, "refs/heads/", &nick))
+				BUG("unexpected default branch '%s'",
+				    default_branch);
+			install_branch_config(0, nick, option_origin,
+					      default_branch);
+			free(default_branch);
+		}

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

Quoted 19 lines
builtin/clone.c +0 -0
 	write_refspec_config(src_ref_prefix, our_head_points_at,
t/t5609-clone-branch.sh +9 -0
index 6e7a7be0522..66af3ac2669 100755
@@ -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
#34 lore raw

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

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

---
 fmt-merge-msg.c          | 6 ++++--
 t/t6200-fmt-merge-msg.sh | 8 ++++++++
 2 files changed, 12 insertions(+), 2 deletions(-)
fmt-merge-msg.c +4 -2
index 72d32bd73b1..5e5c1d86f1c 100644
@@ -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,
t/t6200-fmt-merge-msg.sh +8 -0
index e4c2a6eca43..a23cd157ffd 100755
@@ -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}
Signature · 1 line
gitgitgadget
#35 lore raw

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

"Johannes Schindelin via GitGitGadget" <[email protected]>

Quoted 30 lines · writes:

From: Johannes Schindelin <[email protected]>

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.

---
 fmt-merge-msg.c          | 6 ++++--
 t/t6200-fmt-merge-msg.sh | 8 ++++++++
 2 files changed, 12 insertions(+), 2 deletions(-)
fmt-merge-msg.c +1 -1
index 72d32bd73b1..5e5c1d86f1c 100644
@@ -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);

fmt-merge-msg.c static void fmt_merge_msg_title(struct strbuf *out, · line 460

Quoted 10 lines
fmt-merge-msg.c +3 -1
 	}
 
-	if (!strcmp("master", current_branch))
+	default_branch_name = git_default_branch_name(1);
+	if (!strcmp(default_branch_name, current_branch))
 		strbuf_addch(out, '\n');
 	else
 		strbuf_addf(out, " into %s\n", current_branch);
+	free(default_branch_name);
 }

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

Quoted 20 lines
fmt-merge-msg.c +0 -0
 static void fmt_tag_signature(struct strbuf *tagbuf,
t/t6200-fmt-merge-msg.sh +8 -0
index e4c2a6eca43..a23cd157ffd 100755
@@ -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}
#36 lore raw

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

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

---
 builtin/fast-export.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
builtin/fast-export.c +7 -3
index 85868162eec..028dd9969a2 100644
@@ -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);
Signature · 1 line
gitgitgadget
#37 lore raw

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

builtin/fast-export.c static const char *anonymize_refname(const char *refname) · line 524

Quoted 5 lines
builtin/fast-export.c +2 -2
-        * 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

Quoted 11 lines
builtin/fast-export.c +4 -2
-       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

Signature · 1 line
Matthew Rogers
#38 lore raw

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

Quoted 5 lines · Matt Rogers

builtin/fast-export.c static const char *anonymize_refname(const char *refname) · line 524

Quoted 5 lines
builtin/fast-export.c +2 -2
-        * 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.
         */
Quoted 7 lines

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

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

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

Thanks.

Quoted 11 lines
Quoted 11 lines
builtin/fast-export.c +4 -2
-       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

#39 lore raw

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

In reply to Matt Rogers
Quoted 5 lines · Matt Rogers

builtin/fast-export.c static const char *anonymize_refname(const char *refname) · line 524

Quoted 5 lines
builtin/fast-export.c +2 -2
-        * 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.
         */
Quoted 7 lines

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.

Signature · 2 lines
brian m. carlson: Houston, Texas, US
OpenPGP: https://keybase.io/bk2204
#40 lore raw

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

Quoted 6 lines

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

Quoted 8 lines

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?

Quoted 7 lines

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

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

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

Quoted 3 lines

--
brian m. carlson: Houston, Texas, US
OpenPGP: https://keybase.io/bk2204

Signature · 1 line
Matthew Rogers
#41 lore raw

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

Quoted 2 lines · Matt Rogers

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

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

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

#42 lore raw

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

Hi,

Quoted 10 lines · Junio C Hamano
Quoted 2 lines · Matt Rogers

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

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

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

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

Quoted 9 lines

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

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

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

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

Ciao,
Dscho

#43 lore raw

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

Quoted 6 lines · Johannes Schindelin
Quoted 5 lines

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

Quoted 6 lines

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

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

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

Quoted 9 lines

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

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

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

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

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

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

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

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

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

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

---
 builtin/fast-export.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
builtin/fast-export.c +2 -2
index 85868162ee..a306a60d25 100644
@@ -497,7 +497,7 @@ static void *anonymize_ref_component(const void *old, size_t *len)
 {
 	static int counter;
 	struct strbuf out = STRBUF_INIT;
-	strbuf_addf(&out, "ref%d", counter++);
+	strbuf_addf(&out, "ref%d", ++counter);
 	return strbuf_detach(&out, len);
 }
 
@@ -522,7 +522,7 @@ static const char *anonymize_refname(const char *refname)
 	 * anything interesting.
 	 */
 	if (!strcmp(refname, "refs/heads/master"))
-		return refname;
+		return "ref0";
 
 	strbuf_reset(&anon);
 	for (i = 0; i < ARRAY_SIZE(prefixes); i++) {
#44 lore raw

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

Quoted 25 lines · Junio C Hamano

But because the old solution would not work in the new world order this topic created, a new solution needs to be found when you move the world to the new order.

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

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

builtin/fast-export.c +1 -1
index 85868162ee..a306a60d25 100644
@@ -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);
 }
 

builtin/fast-export.c static const char *anonymize_refname(const char *refname) · line 525

Quoted 5 lines
builtin/fast-export.c +1 -1
@@ -522,7 +522,7 @@ static const char *anonymize_refname(const char *refname)
 	 * anything interesting.
 	 */
 	if (!strcmp(refname, "refs/heads/master"))
-		return refname;
+		return "ref0";

This is obviously wrong. It should return "refs/heads/ref0".

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

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

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

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

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

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

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

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

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

#45 lore raw

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

Quoted 13 lines · Junio C Hamano
Quoted 13 lines
builtin/fast-export.c +1 -1
index 85868162ee..a306a60d25 100644
@@ -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);
 }
 
Quoted 12 lines

builtin/fast-export.c static const char *anonymize_refname(const char *refname) · line 525

Quoted 6 lines
builtin/fast-export.c +1 -1
@@ -522,7 +522,7 @@ static const char *anonymize_refname(const char *refname)
 	 * anything interesting.
 	 */
 	if (!strcmp(refname, "refs/heads/master"))
-		return refname;
+		return "ref0";

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

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

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

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

#46 lore raw

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

Hi Junio,

Quoted 28 lines · Junio C Hamano
Quoted 13 lines · Junio C Hamano
Quoted 13 lines
builtin/fast-export.c +1 -1
index 85868162ee..a306a60d25 100644
@@ -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);
 }
 
Quoted 12 lines

builtin/fast-export.c static const char *anonymize_refname(const char *refname) · line 525

Quoted 6 lines
builtin/fast-export.c +1 -1
@@ -522,7 +522,7 @@ static const char *anonymize_refname(const char *refname)
 	 * anything interesting.
 	 */
 	if (!strcmp(refname, "refs/heads/master"))
-		return refname;
+		return "ref0";

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

Quoted 7 lines

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

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

Right.

Quoted 8 lines

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

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

So I think we're on the same page.

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

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

Ciao,
Dscho

#47 lore raw

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

Quoted 7 lines · Johannes Schindelin

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

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

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

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

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

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

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

#48 lore raw

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

In reply to Junio C Hamano

Hi Junio,

Quoted 31 lines · Junio C Hamano
Quoted 6 lines · Johannes Schindelin
Quoted 5 lines

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

Quoted 6 lines

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

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

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

Quoted 9 lines

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

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

Quoted 3 lines

I think after writing the message about your "two variable" approach, you would retract the "something non-generic" part in the above sentence.

You are absolutely correct!

Quoted 3 lines

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

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

Ciao,
Dscho

#49 lore raw

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

Quoted 4 lines · Johannes Schindelin
Quoted 1 line

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

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

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

I'd say that we should take <[email protected]> with two changes,

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

- if matches return "refs/heads/ref0" instead of "ref0".

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

Thanks.

#50 lore raw

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

In reply to Junio C Hamano

Hi Junio,

builtin/fast-export.c static const char *anonymize_refname(const char *refname) · line 525

Quoted 10 lines · Junio C Hamano
builtin/fast-export.c +1 -1
index 85868162ee..a306a60d25 100644
@@ -522,7 +522,7 @@ static const char *anonymize_refname(const char *refname)
 	 * anything interesting.
 	 */
 	if (!strcmp(refname, "refs/heads/master"))
-		return refname;
+		return "ref0";

I just realized that the comment above reads:

/*
* We also leave "master" as a special case, since it does not reveal
* anything interesting.
*/

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

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

Ciao,
Dscho

Quoted 4 lines
builtin/fast-export.c +0 -0
 	strbuf_reset(&anon);
 	for (i = 0; i < ARRAY_SIZE(prefixes); i++) {
 
#51 lore raw

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

Hi Junio,

Quoted 21 lines · Johannes Schindelin

builtin/fast-export.c static const char *anonymize_refname(const char *refname) · line 525

Quoted 10 lines · Junio C Hamano
builtin/fast-export.c +1 -1
index 85868162ee..a306a60d25 100644
@@ -522,7 +522,7 @@ static const char *anonymize_refname(const char *refname)
 	 * anything interesting.
 	 */
 	if (!strcmp(refname, "refs/heads/master"))
-		return refname;
+		return "ref0";

I just realized that the comment above reads:

/*
* We also leave "master" as a special case, since it does not reveal
* anything interesting.
*/

Quoted 6 lines

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

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

Also, t9351 obviously needs to be adjusted. This one works for me:

-- snipsnap --
From: Junio C Hamano <[email protected]>
Date: Thu, 11 Jun 2020 08:05:38 -0700
Subject: [PATCH] fast-export: do anonymize the primary branch name

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

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

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

---
 builtin/fast-export.c            | 7 +++----
 t/t9351-fast-export-anonymize.sh | 9 +++++----
 2 files changed, 8 insertions(+), 8 deletions(-)
builtin/fast-export.c +3 -4
index 85868162eec..f10e3b35e5b 100644
@@ -497,7 +497,7 @@ static void *anonymize_ref_component(const void *old, size_t *len)
 {
 	static int counter;
 	struct strbuf out = STRBUF_INIT;
-	strbuf_addf(&out, "ref%d", counter++);
+	strbuf_addf(&out, "ref%d", ++counter);
 	return strbuf_detach(&out, len);
 }
 
@@ -518,11 +518,10 @@ static const char *anonymize_refname(const char *refname)
 	int i;
 
 	/*
-	 * We also leave "master" as a special case, since it does not reveal
-	 * anything interesting.
+	 * We special-case the main branch, anonymizing it to `ref0`.
 	 */
 	if (!strcmp(refname, "refs/heads/master"))
-		return refname;
+		return "refs/heads/ref0";
 
 	strbuf_reset(&anon);
 	for (i = 0; i < ARRAY_SIZE(prefixes); i++) {
t/t9351-fast-export-anonymize.sh +5 -4
index 897dc509075..2415f0ec213 100755
@@ -26,8 +26,9 @@ test_expect_success 'stream omits path names' '
 	! grep xyzzy stream
 '
 
-test_expect_success 'stream allows master as refname' '
-	grep master stream
+test_expect_success 'stream translates master to ref0' '
+	grep refs/heads/ref0 stream &&
+	! grep master stream
 '
 
 test_expect_success 'stream omits other refnames' '
@@ -57,7 +58,7 @@ test_expect_success 'import stream to new repository' '
 test_expect_success 'result has two branches' '
 	git for-each-ref --format="%(refname)" refs/heads >branches &&
 	test_line_count = 2 branches &&
-	other_branch=$(grep -v refs/heads/master branches)
+	other_branch=$(grep -v refs/heads/ref0 branches)
 '
 
 test_expect_success 'repo has original shape and timestamps' '
@@ -65,7 +66,7 @@ test_expect_success 'repo has original shape and timestamps' '
 		git log --format="%m %ct" --left-right --boundary "$@"
 	} &&
 	(cd .. && shape master...other) >expect &&
-	shape master...$other_branch >actual &&
+	shape ref0...$other_branch >actual &&
 	test_cmp expect actual
 '
 

--
2.26.0.windows.1

#52 lore raw

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

Quoted 23 lines · Johannes Schindelin

Also, t9351 obviously needs to be adjusted. This one works for me:

-- snipsnap --
From: Junio C Hamano <[email protected]>
Date: Thu, 11 Jun 2020 08:05:38 -0700
Subject: [PATCH] fast-export: do anonymize the primary branch name

In a fast-export stream with --anonymize option, all the end-user data including refnames are munged to prevent exposure, but the 'master' branch is left intact.
...
This is in preparation for introducing a mechanism to affect the name of the primary branch used in the repository. Once the mechanism is in use, the name of the primary branch won't be 'master', and may not be allowed to be exposed.

---
 builtin/fast-export.c            | 7 +++----
 t/t9351-fast-export-anonymize.sh | 9 +++++----
 2 files changed, 8 insertions(+), 8 deletions(-)

...

builtin/fast-export.c static const char *anonymize_refname(const char *refname) · line 524

Quoted 3 lines
builtin/fast-export.c +1 -1
 	if (!strcmp(refname, "refs/heads/master"))
-		return refname;
+		return "refs/heads/ref0";

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

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

Thanks.

#53 lore raw

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

Quoted 6 lines · Junio C Hamano

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

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

Quoted 4 lines

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

Thanks.

#54 lore raw

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

Hi Junio,

Quoted 9 lines · Junio C Hamano
Quoted 6 lines · Junio C Hamano

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

Quoted 6 lines

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

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

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

Thanks,
Dscho

#55 lore raw

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

In reply to Johannes Schindelin
Quoted 8 lines · Johannes Schindelin

I just realized that the comment above reads:

/*
* We also leave "master" as a special case, since it does not reveal
* anything interesting.
*/

Quoted 6 lines

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

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

If you are going to update it, why not make it useful?

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

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

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

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

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

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

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

Thanks.

#56 lore raw

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

Am 12.06.20 um 17:14 schrieb Junio C Hamano:

Quoted 9 lines

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

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

Quoted 7 lines

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

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

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

-- Hannes

#57 lore raw

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

Quoted 15 lines · Johannes Sixt

Am 12.06.20 um 17:14 schrieb Junio C Hamano:

Quoted 14 lines

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

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

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

Quoted 7 lines
Quoted 2 lines

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

IMO, making the primary branch identifiable is a reasonable justification to treat it specially. But then, why does it have to be renamed to 'ref0'? Couldn't it just be renamed to Git's default primary branch name, be it 'master' today or 'main' or whatever in the future?

That comes from https://lore.kernel.org/git/[email protected]/

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

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

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

Thanks.

#58 lore raw

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

Hi Junio & Hannes,

Quoted 38 lines · Junio C Hamano
Quoted 15 lines · Johannes Sixt

Am 12.06.20 um 17:14 schrieb Junio C Hamano:

Quoted 14 lines

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

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

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

Quoted 7 lines
Quoted 2 lines

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

IMO, making the primary branch identifiable is a reasonable justification to treat it specially. But then, why does it have to be renamed to 'ref0'? Couldn't it just be renamed to Git's default primary branch name, be it 'master' today or 'main' or whatever in the future?

That comes from https://lore.kernel.org/git/[email protected]/

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

(quoted diff) +2 -2
-	if (!strcmp(refname, "refs/heads/master"))
-		return refname;
+	if (!strcmp(refname, get_primary_branch_name(DO_NOT_ABBREV)))
+		return get_default_branch_name(DO_NOT_ABBREV);
Quoted 4 lines

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

I like ref0 better, for two reasons:

- it is more consistent to just have all anonymized branches be named ref<N>, and

- using main both for an original main and an original master can be a bit confusing, as the reader might assume that this branch name (as it does not follow the ref<N> convention) was _not_ anonymized, when it very well might have been.

Ciao,
Dscho

#59 lore raw

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

Quoted 7 lines · Johannes Schindelin
Quoted 4 lines

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

I like ref0 better, for two reasons:

Quoted 7 lines

- it is more consistent to just have all anonymized branches be named ref<N>, and

- using main both for an original main and an original master can be a bit confusing, as the reader might assume that this branch name (as it does not follow the ref<N> convention) was _not_ anonymized, when it very well might have been.

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

I am personally OK either way.

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

It might roughly go like:

1. We introduce core.defaultBranchName; when it is not set, its value defaults to 'master' in the 1st phase of the transition. "git init" and "git clone" however issue a warning that says "unless you configure core.defaultBranchName, we use 'master' for now for backward compatibility but we will start using 'main' in three major releases of Git in the future". These commands use the default branch name when creating a new repository in the 1st phase, and set core.primaryBranchName to that name in the resulting repository.

This is to encourage early adopters to set it to 'maint'^W'main' (eek, see, I again made that typo), while allowing those who have toolset that depends more heavily on the current default branch name than other people to set it to 'master' for stability.

In the 1st phase, a few commands that care about what the primary branch is in a repository (i.e. fmt-merge-msg and fast-export are the two we have identified so far) pay attention to the core.primaryBranchName configuration, and default to 'master' if the configuration does not exist.

These commands issue a warning that says "unless you configure core.primaryBranchName in the repository, we use 'master' for now but we will start using 'main' in three major releases of Git in the future".

The above two warning messages will be squelched once the user sets respective configuration variable.

2. We flip the default for the two variables from 'master' to 'main' in three major releases of Git (i.e. 24-30 weeks from the 1st phase). The two warning messages added for the 1st phase will be reworded for the updated default. We no longer need to say "in three major releases" in there.

3. After long time passes, remove the warning.

#60 lore raw

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

Hi Junio,

Quoted 24 lines · Junio C Hamano
Quoted 7 lines · Johannes Schindelin
Quoted 4 lines

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

I like ref0 better, for two reasons:

Quoted 7 lines

- it is more consistent to just have all anonymized branches be named ref<N>, and

- using main both for an original main and an original master can be a bit confusing, as the reader might assume that this branch name (as it does not follow the ref<N> convention) was _not_ anonymized, when it very well might have been.

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

Quoted 7 lines

I am personally OK either way.

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

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

Quoted 32 lines

It might roughly go like:

1. We introduce core.defaultBranchName; when it is not set, its value defaults to 'master' in the 1st phase of the transition. "git init" and "git clone" however issue a warning that says "unless you configure core.defaultBranchName, we use 'master' for now for backward compatibility but we will start using 'main' in three major releases of Git in the future". These commands use the default branch name when creating a new repository in the 1st phase, and set core.primaryBranchName to that name in the resulting repository.

This is to encourage early adopters to set it to 'maint'^W'main' (eek, see, I again made that typo), while allowing those who have toolset that depends more heavily on the current default branch name than other people to set it to 'master' for stability.

In the 1st phase, a few commands that care about what the primary branch is in a repository (i.e. fmt-merge-msg and fast-export are the two we have identified so far) pay attention to the core.primaryBranchName configuration, and default to 'master' if the configuration does not exist.

These commands issue a warning that says "unless you configure core.primaryBranchName in the repository, we use 'master' for now but we will start using 'main' in three major releases of Git in the future".

The above two warning messages will be squelched once the user sets respective configuration variable.

Quoted 7 lines

2. We flip the default for the two variables from 'master' to 'main' in three major releases of Git (i.e. 24-30 weeks from the 1st phase). The two warning messages added for the 1st phase will be reworded for the updated default. We no longer need to say "in three major releases" in there.

3. After long time passes, remove the warning.

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

Thank you,
Dscho

#61 lore raw

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

Quoted 2 lines · Johannes Schindelin

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

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

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

#62 lore raw

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

Hi Junio,

Quoted 11 lines · Junio C Hamano
Quoted 2 lines · Johannes Schindelin

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

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

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

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

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

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

:-)

Ciao,
Dscho

#63 lore raw

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

Quoted 8 lines · Johannes Schindelin

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

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

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

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

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

#64 lore raw

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

In reply to Junio C Hamano

Hi Junio,

Quoted 17 lines · Junio C Hamano
Quoted 8 lines · Johannes Schindelin

I just realized that the comment above reads:

/*
* We also leave "master" as a special case, since it does not reveal
* anything interesting.
*/

Quoted 6 lines

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

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

If you are going to update it, why not make it useful?

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

True. Sorry about forgetting that when adjusting the code comment.

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

Quoted 9 lines

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

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

That is indeed an improvement, thank you so much.

Quoted 10 lines

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

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

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

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

Quoted 3 lines

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

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

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

Ciao,
Dscho

#65 lore raw

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

In reply to Matt Rogers

Hi Matt,

Quoted 5 lines · Matt Rogers

builtin/fast-export.c static const char *anonymize_refname(const char *refname) · line 524

Quoted 5 lines
builtin/fast-export.c +2 -2
-        * 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.
         */
Quoted 7 lines

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

#66 lore raw

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

Quoted 17 lines · Johannes Schindelin

Hi Matt,

Quoted 5 lines · Matt Rogers

builtin/fast-export.c static const char *anonymize_refname(const char *refname) · line 524

Quoted 5 lines
builtin/fast-export.c +2 -2
-        * 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.
         */
Quoted 7 lines

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

Quoted 2 lines

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

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

Thanks.

#67 lore raw

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

Hi Junio,

Quoted 19 lines · Junio C Hamano
Quoted 17 lines · Johannes Schindelin

Hi Matt,

Quoted 12 lines · Matt Rogers

builtin/fast-export.c static const char *anonymize_refname(const char *refname) · line 524

Quoted 5 lines
builtin/fast-export.c +2 -2
-        * 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

Quoted 7 lines
Quoted 2 lines

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

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

Yep, absolutely.

Thanks,
Dscho

#68 lore raw

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

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

---
 Documentation/config/core.txt | 4 ++++
 t/README                      | 4 ++++
 2 files changed, 8 insertions(+)
Documentation/config/core.txt +4 -0
index 74619a9c03b..a11e1abdf59 100644
@@ -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.
t/README +4 -0
index cf863837ab9..b32f520a27f 100644
@@ -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
 ------------
 
Signature · 1 line
gitgitgadget
#69 lore raw

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

"Johannes Schindelin via GitGitGadget" <[email protected]>

Documentation/config/core.txt core.abbrev:: · line 632

Quoted 12 lines · writes:
Documentation/config/core.txt +4 -0
index 74619a9c03b..a11e1abdf59 100644
@@ -626,3 +626,7 @@ core.abbrev::
 	in your repository, which hopefully is enough for
 	abbreviated object names to stay unique for some time.
 	The minimum length is 4.
+
+core.defaultBranchName::
+	Allows overriding the default branch name e.g. when initializing
+	a new repository or when cloning an empty repository.

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

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

Quoted 14 lines
t/README +4 -0
index cf863837ab9..b32f520a27f 100644
@@ -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
 ------------
#70 lore raw
In reply to Johannes Schindelin via GitGitGadget

"Johannes Schindelin via GitGitGadget" <[email protected]>

Quoted 5 lines · writes:

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

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

Quoted 5 lines

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

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

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

- look at config.defaultBranchName in /etc/gitconfig or ~/.gitconfig before initializing the per-repository config in $GIT_DIR/config it just created (or it is about to create).

- if there is no config.defaultBranchName configured, then set the per-repository configuration to 'main' in the per-repository configuration. Otherwise do not do anything.

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

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

(1) otherwise use 'master' (not 'main').

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

#71 lore raw
Quoted 36 lines · Junio C Hamano

"Johannes Schindelin via GitGitGadget" <[email protected]> writes:
...

Quoted 5 lines

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

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

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

- look at config.defaultBranchName in /etc/gitconfig or ~/.gitconfig before initializing the per-repository config in $GIT_DIR/config it just created (or it is about to create).

- if there is no config.defaultBranchName configured, then set the per-repository configuration to 'main' in the per-repository configuration. Otherwise do not do anything.

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

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

Quoted 7 lines

(1) otherwise use 'master' (not 'main').

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

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

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

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

    name=$(git var defaultBranchName)

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

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

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

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

#72 lore raw
In reply to Junio C Hamano

Hi Junio,

Quoted 9 lines · Junio C Hamano

"Johannes Schindelin via GitGitGadget" <[email protected]>

Quoted 5 lines · writes:

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

Quoted 3 lines

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

Thanks!

Quoted 34 lines
Quoted 6 lines

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

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

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

- look at config.defaultBranchName in /etc/gitconfig or ~/.gitconfig before initializing the per-repository config in $GIT_DIR/config it just created (or it is about to create).

- if there is no config.defaultBranchName configured, then set the per-repository configuration to 'main' in the per-repository configuration. Otherwise do not do anything.

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

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

Quoted 7 lines

(1) otherwise use 'master' (not 'main').

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

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

- One setting to specify the default branch name for newly-initialized repositories (such as git init, unless it re-initializes, and git clone when the cloned repository does not yet contain any branches).

This should probably be called init.defaultBranchName (even if git clone picks it up, too), and be overrideable by GIT_TEST_DEFAULT_BRANCH_NAME.

- And another one, to define the default branch name for the _current_ repository. This setting would be configured implicitly upon git init and git clone. For repositories where it is not set, we would assume master for backwards-compatibility.

Technically, this should probably not even be a config option because it is _strictly_ per-repo. But maybe it is not _so_ much per-repo: if I want to rename all my main branches in all of my local repositories, I might opt to configure this in ~/.gitconfig.

Maybe a good name for this would be repo.mainBranch (and it would contain the full ref name, e.g. refs/heads/main, not just main).

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

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

Does that sound like a plan?

Ciao,
Dscho

#73 lore raw
Quoted 5 lines · Johannes Schindelin

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

Quoted 7 lines

- One setting to specify the default branch name for newly-initialized repositories (such as git init, unless it re-initializes, and git clone when the cloned repository does not yet contain any branches).

This should probably be called init.defaultBranchName (even if git clone picks it up, too), and be overrideable by GIT_TEST_DEFAULT_BRANCH_NAME.

Yes.

Quoted 2 lines

- And another one, to define the default branch name for the _current_ repository. This setting would be configured implicitly upon git init

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

Quoted 10 lines

and git clone. For repositories where it is not set, we would assume master for backwards-compatibility.

Technically, this should probably not even be a config option because it is _strictly_ per-repo. But maybe it is not _so_ much per-repo: if I want to rename all my main branches in all of my local repositories, I might opt to configure this in ~/.gitconfig.

Maybe a good name for this would be repo.mainBranch (and it would contain the full ref name, e.g. refs/heads/main, not just main).

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

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

Quoted 2 lines

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

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

Quoted 5 lines

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

Does that sound like a plan?

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

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

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

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

Thanks.

#74 lore raw
In reply to Johannes Schindelin via GitGitGadget
Quoted 29 lines · Johannes Schindelin via GitGitGadget

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

Quoted 8 lines

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.

Signature · 2 lines
brian m. carlson: Houston, Texas, US
OpenPGP: https://keybase.io/bk2204
#75 lore raw
In reply to Johannes Schindelin via GitGitGadget

Hi Johannes (and Dan)

Quoted 11 lines · Johannes Schindelin via GitGitGadget

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

Quoted 8 lines

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

Quoted 4 lines

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

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

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.

Quoted 4 lines

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

Quoted 8 lines

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.

Quoted 32 lines

Don Goodman-Wilson (1):
init: allow overriding the default branch name for new repositories

Johannes Schindelin (8):
remote: respect core.defaultBranchName send-pack/transport-helper: respect core.defaultBranchName
testsvn: respect core.defaultBranchName
submodule: use the (possibly overridden) default branch name
clone: learn about the possibly-configured default branch name
fmt-merge-msg: learn about the possibly-configured default branch name
fast-export: respect the possibly-overridden default branch name Document how the default branch name can be overridden

 Documentation/config/core.txt |  4 ++++
 builtin/clone.c               | 14 +++++++++++---
 builtin/fast-export.c         | 10 +++++++---
 builtin/init-db.c             |  8 +++++---
 builtin/submodule--helper.c   | 10 ++++++++--
 fmt-merge-msg.c               |  6 ++++--
 refs.c                        | 34 ++++++++++++++++++++++++++++++++++
 refs.h                        |  6 ++++++
 remote-testsvn.c              | 11 ++++++++---
 remote.c                      | 12 ++++++++----
 send-pack.c                   |  6 +++++-
 t/README                      |  4 ++++
 t/t0001-init.sh               | 20 ++++++++++++++++++++
 t/t5609-clone-branch.sh       |  9 +++++++++
 t/t6200-fmt-merge-msg.sh      |  8 ++++++++
 transport-helper.c            |  6 +++++-
 16 files changed, 146 insertions(+), 22 deletions(-)
Quoted 6 lines

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

#76 lore raw

Hi Taylor,

Quoted 21 lines · Taylor Blau
Quoted 11 lines · Johannes Schindelin via GitGitGadget

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

Quoted 8 lines

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

Quoted 8 lines

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 7 lines
Quoted 4 lines

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

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

Sorry, my typo: it's Don, not Dan ;-)

Quoted 5 lines

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

Well, go back enjoying your road trip! :-P See you on Monday.

Quoted 13 lines
Quoted 4 lines

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

Quoted 8 lines

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.

Quoted 4 lines

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.

Quoted 4 lines

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.

Quoted 7 lines

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

My personal preference was "default" on Monday, and "main" ever since.

Quoted 7 lines

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

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

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

Ciao,
Dscho

#77 lore raw
In reply to Johannes Schindelin via GitGitGadget

Hi,

Quoted 29 lines · Johannes Schindelin via GitGitGadget

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

Quoted 8 lines

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

Signature · 2 lines
Regards,
Pratyush Yadav
#78 lore raw

Hi Pratyush,

Quoted 9 lines · Pratyush Yadav
Quoted 5 lines · Johannes Schindelin via GitGitGadget

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.

Quoted 9 lines

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

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

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

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

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

So I think this example...

Quoted 10 lines

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

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

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

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

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

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

GitHub CLI changed their main branch name to trunk.

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

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

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

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

Ciao,
Johannes

#79 lore raw

Hi Dscho,

Quoted 11 lines · Johannes Schindelin
Quoted 10 lines

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

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

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

Quoted 6 lines

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

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

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

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

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

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

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

I think I see three possible solutions to this:

1. Special case 'master' in submodules to retain backwards compatibility.

I don't think this is very appealing as if the change is made to use another default branch name, then the "default" branch for submodules would be "master" even though the new default everywhere else would be different. And in the future, someone who doesn't know the context behind all of this would be very confused where there are two different default branch names.

2. Disable 'update --remote' support for submodules that don't specify a branch.

If Git detects that a branch key is missing when trying to do an 'update --remote', it should just quit out and refuse to do anything. Of course, this a very backwards incompatible change and it would require several release cycles to implement where we warn users about this impending change before we actually make it happen.

3. Make 'update --remote' get HEAD.

I argue that this is how it always should've been implemented but, alas, I can't go back in time and fix it. Regardless, it might be good to flip this to be the default if we're going to be making the change anyway.

Unfortunately, this suffers from both the problems of 1 and 2. As with 1, we'll end up in a situation where users with different versions of Git may experience different behaviours given the same public repository and I think this is definitely undesirable. With 2, this change will also require a long deprecation period which I don't think it compatible with how people seem to want the default branch switch to happen this release.

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

Thoughts?

#80 lore raw

Hi Denton,

Quoted 83 lines · Denton Liu
Quoted 11 lines · Johannes Schindelin
Quoted 10 lines

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

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

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

Quoted 6 lines

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

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

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

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

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

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

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

I think I see three possible solutions to this:

1. Special case 'master' in submodules to retain backwards compatibility.

I don't think this is very appealing as if the change is made to use another default branch name, then the "default" branch for submodules would be "master" even though the new default everywhere else would be different. And in the future, someone who doesn't know the context behind all of this would be very confused where there are two different default branch names.

2. Disable 'update --remote' support for submodules that don't specify a branch.

If Git detects that a branch key is missing when trying to do an 'update --remote', it should just quit out and refuse to do anything. Of course, this a very backwards incompatible change and it would require several release cycles to implement where we warn users about this impending change before we actually make it happen.

3. Make 'update --remote' get HEAD.

I argue that this is how it always should've been implemented but, alas, I can't go back in time and fix it. Regardless, it might be good to flip this to be the default if we're going to be making the change anyway.

Unfortunately, this suffers from both the problems of 1 and 2. As with 1, we'll end up in a situation where users with different versions of Git may experience different behaviours given the same public repository and I think this is definitely undesirable. With 2, this change will also require a long deprecation period which I don't think it compatible with how people seem to want the default branch switch to happen this release.

Quoted 5 lines

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

Thoughts?

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

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

Ciao,
Dscho

#81 lore raw
In reply to Pratyush Yadav
Quoted 10 lines · Pratyush Yadav

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.

Signature · 2 lines
brian m. carlson: Houston, Texas, US
OpenPGP: https://keybase.io/bk2204
#82 lore raw

v2 cover Allow overriding the default name of the default branch

In reply to Johannes Schindelin via GitGitGadget

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

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

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

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

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

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

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

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

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

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

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

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

Changes since v1:

* The modifications to respect GIT_TEST_DEFAULT_BRANCH_NAME have been backed out from this patch series, as they are only relevant once we start converting the test suite to accommodate for a new default main branch name.

* An error message that started with an upper-case letter was downcased.

* git_default_branch_name()'s logic was simplified by replacing an if ... else ... by a ternary assignment.

* The git_default_branch_name() function was renamed to git_main_branch_name() and a corresponding repo_main_branch_name() was introduced.

* The "init" commit message's first paragraph now elaborates a little bit on the reasoning why projects want to move away from the current default branch name.

* The "init" commit was split into two.

* There are now two config settings: init.defaultBranch (defining the branch name to use when initializing new repositories) and core.mainBranch (which is now configured by init_db(), declaring what the name of the main branch is in this repository).

* The commits were re-ordered to introduce the concept of core.mainBranch first because technically, this is something that we could do even without changing git init at all.

* git fast-export --anonymize now always uses the ref name ref0 for the main branch, no matter whether it was overridden or whether the fall-back is in effect.

* The code comment regarding anonymizing the main branch to ref0 in git fast-export --anonymize was enhanced.

* A new patch was added to rename core.mainBranch if the main branch is renamed via git branch -m.

* Added a patch that introduces support for git init --main-branch=<branch-name>.

* Where possible, I added tests (although I did not try to extend test coverage to all changes: the send-pack.c/transport-helper.c patch only adds a test for the send-pack.c adjustment, for example).

Don Goodman-Wilson (1):
init: allow overriding the default main branch name via the config

Johannes Schindelin (10):
fmt-merge-msg: introduce a way to override the main branch name send-pack/transport-helper: respect core.mainBranch git_main_branch_name(): optionally report the full ref name
fast-export: handle overridden main branch names correctly branch -m: adjust core.mainBranch if necessary
init: allow specifying the main branch name for the new repository
clone: handle overridden main branch names
remote: learn about the possibly-overridden default main branch name
submodule: use the correct default for the main branch name
testsvn: respect init.defaultBranch

Junio C Hamano (1):
fast-export: do anonymize the primary branch name

 Documentation/config/core.txt    |  5 +++++
 Documentation/config/init.txt    |  4 ++++
 Documentation/git-init.txt       |  7 +++++++
 builtin/branch.c                 |  9 ++++++++
 builtin/clone.c                  | 19 +++++++++++++----
 builtin/fast-export.c            | 20 +++++++++++++-----
 builtin/init-db.c                | 36 +++++++++++++++++++++++++-------
 builtin/submodule--helper.c      | 10 +++++++--
 cache.h                          |  2 +-
 fmt-merge-msg.c                  |  6 ++++--
 refs.c                           | 34 ++++++++++++++++++++++++++++++
 refs.h                           | 15 +++++++++++++
 remote-testsvn.c                 | 12 ++++++++---
 remote.c                         | 15 ++++++++-----
 send-pack.c                      |  6 +++++-
 t/t0001-init.sh                  | 31 +++++++++++++++++++++++++++
 t/t3200-branch.sh                |  9 ++++++++
 t/t5528-push-default.sh          |  7 +++++++
 t/t5606-clone-options.sh         | 26 +++++++++++++++++++++++
 t/t6200-fmt-merge-msg.sh         |  7 +++++++
 t/t7406-submodule-update.sh      |  7 +++++++
 t/t9020-remote-svn.sh            |  6 ++++++
 t/t9351-fast-export-anonymize.sh | 15 +++++++++----
 transport-helper.c               |  6 +++++-
 24 files changed, 279 insertions(+), 35 deletions(-)

base-commit: 0313f36c6ebecb3bffe6f15cf25a4883100f0214
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-656%2Fdscho%2Fdefault-branch-name-option-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-656/dscho/default-branch-name-option-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/656

Range-diff vs v1:

  -:  ----------- >  1:  ebd10f73cd7 fast-export: do anonymize the primary branch name
  7:  e849def4a8c !  2:  f4d54739153 fmt-merge-msg: learn about the possibly-configured default branch name
     @@ Metadata
      Author: Johannes Schindelin <[email protected]>
      
       ## Commit message ##
     -    fmt-merge-msg: learn about the possibly-configured default branch name
     +    fmt-merge-msg: introduce a way to override the main branch name
      
     -    When formatting the commit message for merge commits, Git appends "into
     -    <branch-name>" unless the current branch is the default branch.
     +    There is a growing number of projects and companies desiring to change
     +    the main branch name of their repositories (see e.g.
     +    https://twitter.com/mislav/status/1270388510684598272 for background on
     +    this).
      
     -    Now that we can configure what the default branch name should be, we
     -    will want to respect that setting in that scenario rather than using the
     -    compiled-in default branch name.
     +    However, there are a couple of hard-coded spots in Git's source code
     +    that make this endeavor harder than necessary. For example, when
     +    formatting the commit message for merge commits, Git appends "into
     +    <branch-name>" unless the current branch is the `master` branch.
     +
     +    Clearly, this is not what one wants when already having gone through all
     +    the steps to manually rename the main branch (and taking care of all the
     +    fall-out such as re-targeting existing Pull Requests).
     +
     +    Let's introduce a way to override Git's hard-coded default:
     +    `core.mainBranch`.
     +
     +    We will start supporting this config option in the `git fmt-merge-msg`
     +    command and successively adjust all other places where the main branch
     +    name is hard-coded.
      
          Signed-off-by: Johannes Schindelin <[email protected]>
      
     + ## Documentation/config/core.txt ##
     +@@ Documentation/config/core.txt: core.abbrev::
     + 	in your repository, which hopefully is enough for
     + 	abbreviated object names to stay unique for some time.
     + 	The minimum length is 4.
     ++
     ++core.mainBranch::
     ++	The name of the main (or: primary) branch in the current repository.
     ++	For historical reasons, `master` is used as the fall-back for this
     ++	setting.
     +
       ## fmt-merge-msg.c ##
      @@ fmt-merge-msg.c: static void fmt_merge_msg_title(struct strbuf *out,
       				const char *current_branch)
       {
       	int i = 0;
      -	char *sep = "";
     -+	char *sep = "", *default_branch_name;
     ++	char *sep = "", *main_branch;
       
       	strbuf_addstr(out, "Merge ");
       	for (i = 0; i < srcs.nr; i++) {
     @@ fmt-merge-msg.c: static void fmt_merge_msg_title(struct strbuf *out,
       	}
       
      -	if (!strcmp("master", current_branch))
     -+	default_branch_name = git_default_branch_name(1);
     -+	if (!strcmp(default_branch_name, current_branch))
     ++	main_branch = git_main_branch_name();
     ++	if (!strcmp(main_branch, current_branch))
       		strbuf_addch(out, '\n');
       	else
       		strbuf_addf(out, " into %s\n", current_branch);
     -+	free(default_branch_name);
     ++	free(main_branch);
       }
       
       static void fmt_tag_signature(struct strbuf *tagbuf,
      
     + ## refs.c ##
     +@@ refs.c: void expand_ref_prefix(struct argv_array *prefixes, const char *prefix)
     + 		argv_array_pushf(prefixes, *p, len, prefix);
     + }
     + 
     ++char *repo_main_branch_name(struct repository *r)
     ++{
     ++	const char *config_key = "core.mainbranch";
     ++	const char *config_display_key = "core.mainBranch";
     ++	const char *fall_back = "master";
     ++	char *name = NULL, *ret;
     ++
     ++	if (repo_config_get_string(r, config_key, &name) < 0)
     ++		die(_("could not retrieve `%s`"), config_display_key);
     ++
     ++	ret = name ? name : xstrdup(fall_back);
     ++
     ++	if (check_refname_format(ret, REFNAME_ALLOW_ONELEVEL))
     ++		die(_("invalid branch name: %s = %s"),
     ++		    config_display_key, name);
     ++
     ++	if (name != ret)
     ++		free(name);
     ++
     ++	return ret;
     ++}
     ++
     ++char *git_main_branch_name(void)
     ++{
     ++	return repo_main_branch_name(the_repository);
     ++}
     ++
     + /*
     +  * *string and *len will only be substituted, and *string returned (for
     +  * later free()ing) if the string passed in is a magic short-hand form
     +
     + ## refs.h ##
     +@@ refs.h: int repo_dwim_log(struct repository *r, const char *str, int len, struct object_
     + int dwim_ref(const char *str, int len, struct object_id *oid, char **ref);
     + int dwim_log(const char *str, int len, struct object_id *oid, char **ref);
     + 
     ++/*
     ++ * Retrieves the name of the main (or: primary) branch of the given
     ++ * repository.
     ++ */
     ++char *git_main_branch_name(void);
     ++char *repo_main_branch_name(struct repository *r);
     ++
     + /*
     +  * A ref_transaction represents a collection of reference updates that
     +  * should succeed or fail together.
     +
       ## t/t6200-fmt-merge-msg.sh ##
      @@ t/t6200-fmt-merge-msg.sh: test_expect_success 'setup FETCH_HEAD' '
       	git fetch . left
       '
       
      +test_expect_success 'with overridden default branch name' '
     -+	test_config core.defaultBranchName default &&
      +	test_when_finished "git switch master" &&
      +	git switch -c default &&
     -+	git fmt-merge-msg <.git/FETCH_HEAD >actual &&
     ++	git -c core.mainBranch=default fmt-merge-msg <.git/FETCH_HEAD >actual &&
      +	! grep "into default" actual
      +'
      +

3: c9c9c81068e ! 3: bd8af3755ad send-pack/transport-helper: respect core.defaultBranchName
@@ Metadata
Author: Johannes Schindelin <[email protected]>

## Commit message ##
- send-pack/transport-helper: respect core.defaultBranchName
+ send-pack/transport-helper: respect core.mainBranch

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

@@ send-pack.c: int send_pack(struct send_pack_args *args,
}

if (!remote_refs) {
-+ char *branch_name = git_default_branch_name(1);
++ char *branch_name = git_main_branch_name();
+
fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
- "Perhaps you should specify a branch such as 'master'.\n");
@@ send-pack.c: int send_pack(struct send_pack_args *args,
}
if (args->atomic && !atomic_supported)

+ ## t/t5528-push-default.sh ##
+@@ t/t5528-push-default.sh: test_expect_success 'push from/to new branch with upstream, matching and simple'
+ test_push_failure upstream
+ '
+
++test_expect_success '"matching" fails if none match' '
++ git init --bare empty &&
++ test_must_fail git -c core.mainBranch=unmatch push empty : 2>actual &&
++ needle="Perhaps you should specify a branch such as '\''unmatch'\''" &&
++ test_i18ngrep "$needle" actual
++'
++
+ test_expect_success 'push ambiguously named branch with upstream, matching and simple' '
+ git checkout -b ambiguous &&
+ test_config branch.ambiguous.remote parent1 &&
+
## transport-helper.c ##
@@ transport-helper.c: static int push_refs(struct transport *transport,
}

if (!remote_refs) {
-+ char *branch_name = git_default_branch_name(1);
++ char *branch_name = git_main_branch_name();
+
fprintf(stderr,
_("No refs in common and none specified; doing nothing.\n"

  -:  ----------- >  4:  ca1c63c3e01 git_main_branch_name(): optionally report the full ref name
  8:  1efe848f2b0 !  5:  a3be4f39aa2 fast-export: respect the possibly-overridden default branch name

@@ Metadata
Author: Johannes Schindelin <[email protected]>

## Commit message ##
- fast-export: respect the possibly-overridden default branch name
+ fast-export: handle overridden main branch names correctly

- When anonymizing commit history, we are careful to leave the branch name
- of the default branch alone.
+ When anonymizing commit history, we are careful to translate the main
+ branch name to ref0.

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

@@ builtin/fast-export.c: static const char *anonymize_refname(const char *refname)
};
static struct hashmap refs;
static struct strbuf anon = STRBUF_INIT;
-+ static char *default_branch_name;
++ static char *main_branch;
int i;

/*
-- * We also leave "master" as a special case, since it does not reveal
-- * anything interesting.
-+ * We also leave the default branch name as a special case, since it
-+ * does not reveal anything interesting.
+ * In certain circumstances, it might be interesting to be able to
+ * identify the main branch. For that reason, let's force its name to
+ * be anonymized to ref0.
++ *
++ * While the main branch name might often be main for new
++ * repositories (and master for aged ones), and such well-known names
++ * may not necessarily need anonymizing, it could be configured to use
++ * a secret word that the user may not want to reveal.
*/
- if (!strcmp(refname, "refs/heads/master"))
-+ if (!default_branch_name)
-+ default_branch_name = git_default_branch_name(0);
++ if (!main_branch)
++ main_branch = git_main_branch_name(MAIN_BRANCH_FULL_NAME);
+
-+ if (!strcmp(refname, default_branch_name))
- return refname;
++ if (!strcmp(refname, main_branch))
+ return "refs/heads/ref0";

strbuf_reset(&anon);
+
+ ## t/t9351-fast-export-anonymize.sh ##
+@@ t/t9351-fast-export-anonymize.sh: test_expect_success 'stream translates master to ref0' '
+ ! grep master stream
+ '
+
++test_expect_success 'respects configured main branch' '
++ git -c core.mainBranch=does-not-exist \
++ fast-export --anonymize --all >stream-without-ref0 &&
++ ! grep ref0 stream-without-ref0
++'
++
+ test_expect_success 'stream omits other refnames' '
+ ! grep other stream &&
+ ! grep mytag stream

  -:  ----------- >  6:  933e314813d branch -m: adjust `core.mainBranch` if necessary
  1:  90912e32da1 !  7:  0ec04b2086e init: allow overriding the default branch name for new repositories

@@
## Metadata ##
-Author: Don Goodman-Wilson <[email protected]> +Author: Johannes Schindelin <[email protected]>

## Commit message ##
- init: allow overriding the default branch name for new repositories
+ init: allow specifying the main branch name for the new repository

There is a growing number of projects trying to avoid the non-inclusive
- name master in their repositories. For existing repositories, this
- requires manual work. For new repositories, the only way to do that
- automatically is by copying all of Git's template directory, then
- hard-coding the desired default branch name into the .git/HEAD file,
- and then configuring init.templateDir to point to those copied
+ name master in their repositories: The master/slave terminology is
+ insensitive and perpetuates injustice. This master/slave idea is
+ actually where Git's naming comes from, as it was inherited from
+ BitKeeper which uses the term in exactly this way, see
+ https://mail.gnome.org/archives/desktop-devel-list/2019-May/msg00066.html
+
+ To change that branch name for new repositories, currently the only way
+ to do that automatically is by copying all of Git's template directory,
+ then hard-coding the desired default branch name into the .git/HEAD
+ file, and then configuring init.templateDir to point to those copied
template files.

- To make this process much less cumbersome, let's introduce support for
- core.defaultBranchName. That way, users won't need to keep their
- copied template files up to date, and won't interfere with default hooks
- installed by their administrators.
+ To make this process much less cumbersome, let's introduce a new option:
+ --main-branch=<branch-name>.

- While at it, also let users set the default branch name via the
- environment variable GIT_TEST_DEFAULT_BRANCH_NAME, in preparation for
- adjusting Git's test suite to a more inclusive default branch name. As
- is common in Git, the GIT_TEST_* variable takes precedence over the
- config setting.
+ This will not only initialize the repository with the specified initial
+ branch; It will also record that branch name in core.mainBranch.

- Note: we use the prefix core. instead of init. because we want to
- adjust also git clone, git fmt-merge-msg and other commands over the
- course of the next commits to respect this setting.
+ Signed-off-by: Johannes Schindelin <[email protected]>

- Helped-by: Johannes Schindelin <[email protected]>
- Helped-by: Derrick Stolee <[email protected]>
- Signed-off-by: Don Goodman-Wilson <[email protected]>
+ ## Documentation/git-init.txt ##
+@@ Documentation/git-init.txt: SYNOPSIS
+ [verse]
+ 'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
+ [--separate-git-dir <git dir>] [--object-format=<format]
++ [-b <branch-name> | --main-branch=<branch-name>]
+ [--shared[=<permissions>]] [directory]
+
+
+@@ Documentation/git-init.txt: repository.
+ +
+ If this is reinitialization, the repository will be moved to the specified path. +
++-b <branch-name::
++--main-branch=<branch-name>::
++
++Use the specified name for the main (or: initial) branch in the newly created ++repository. If not specified, fall back to the default name: master. ++
+ --shared[=(false|true|umask|group|all|world|everybody|0xxx)]::
+
+ Specify that the Git repository is to be shared amongst several users. This +
+ ## builtin/clone.c ##
+@@ builtin/clone.c: int cmd_clone(int argc, const char **argv, const char *prefix)
+ }
+ }
+
+- init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, INIT_DB_QUIET);
++ init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL,
++ INIT_DB_QUIET);
+
+ if (real_git_dir)
+ git_dir = real_git_dir;

## builtin/init-db.c ##
+@@ builtin/init-db.c: void initialize_repository_version(int hash_algo) +
+ static int create_default_files(const char *template_path,
+ const char *original_git_dir,
++ const char *main_branch,
+ const struct repository_format *fmt)
+ {
+ struct stat st1;
@@ builtin/init-db.c: static int create_default_files(const char *template_path,
die("failed to set up refs db: %s", err.buf);

@@ builtin/init-db.c: static int create_default_files(const char *template_path,
|| readlink(path, junk, sizeof(junk)-1) != -1);
if (!reinit) {
- if (create_symref("HEAD", "refs/heads/master", NULL) < 0)
-+ char *default_ref = git_default_branch_name(0);
-+ if (create_symref("HEAD", default_ref, NULL) < 0)
++ char *ref;
++
++ if (!main_branch)
++ main_branch = "master";
++
++ ref = xstrfmt("refs/heads/%s", main_branch);
++ if (check_refname_format(ref, 0) < 0)
++ die(_("invalid main branch name: '%s'"), main_branch);
++
++ if (create_symref("HEAD", ref, NULL) < 0)
exit(1);
-+ free(default_ref);
- }
+- }
++ free(ref);
++
++ git_config_set("core.mainbranch", main_branch);
++ } else if (main_branch)
++ warning(_("re-init: ignoring --main-branch=%s"), main_branch);

initialize_repository_version(fmt->hash_algo);
-
- ## refs.c ##
-@@ refs.c: void expand_ref_prefix(struct argv_array *prefixes, const char *prefix)
- argv_array_pushf(prefixes, *p, len, prefix);
+
+@@ builtin/init-db.c: static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash
}

-+char *git_default_branch_name(int short_name)
-+{
-+ const char *branch_name = getenv("GIT_TEST_DEFAULT_BRANCH_NAME");
-+ char *from_config = NULL, *prefixed;
-+
-+ /*
-+ * If the default branch name was not specified via the environment
-+ * variable GIT_TEST_DEFAULT_BRANCH_NAME, retrieve it from the config
-+ * setting core.defaultBranchName. If neither are set, fall back to the
-+ * hard-coded default.
-+ */
-+ if (!branch_name || !*branch_name) {
-+ if (git_config_get_string("core.defaultbranchname",
-+ &from_config) < 0)
-+ die(_("Could not retrieve core.defaultBranchName"));
-+
-+ if (from_config)
-+ branch_name = from_config;
-+ else
-+ branch_name = "master";
-+ }
-+
-+ if (short_name)
-+ return from_config ? from_config : xstrdup(branch_name);
-+
-+ /* prepend "refs/heads/" to the branch name */
-+ prefixed = xstrfmt("refs/heads/%s", branch_name);
-+ if (check_refname_format(prefixed, 0))
-+ die(_("invalid default branch name: '%s'"), branch_name);
-+
-+ free(from_config);
-+ return prefixed;
-+}
-+
- /*
- * *string and *len will only be substituted, and *string returned (for
- * later free()ing) if the string passed in is a magic short-hand form
+ int init_db(const char *git_dir, const char *real_git_dir,
+- const char *template_dir, int hash, unsigned int flags)
++ const char *template_dir, int hash, const char *main_branch,
++ unsigned int flags)
+ {
+ int reinit;
+ int exist_ok = flags & INIT_DB_EXIST_OK;
+@@ builtin/init-db.c: int init_db(const char *git_dir, const char *real_git_dir, +
+ validate_hash_algorithm(&repo_fmt, hash);
+
+- reinit = create_default_files(template_dir, original_git_dir, &repo_fmt);
++ reinit = create_default_files(template_dir, original_git_dir,
++ main_branch, &repo_fmt);
+
+ create_object_directory();
+
+@@ builtin/init-db.c: int cmd_init_db(int argc, const char **argv, const char *prefix)
+ const char *template_dir = NULL;
+ unsigned int flags = 0;
+ const char *object_format = NULL;
++ const char *main_branch = NULL;
+ int hash_algo = GIT_HASH_UNKNOWN;
+ const struct option init_db_options[] = {
+ OPT_STRING(0, "template", &template_dir, N_("template-directory"),
+@@ builtin/init-db.c: int cmd_init_db(int argc, const char **argv, const char *prefix)
+ OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET),
+ OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
+ N_("separate git dir from working tree")),
++ OPT_STRING('b', "main-branch", &main_branch, N_("name"),
++ N_("override the name of the main branch")),
+ OPT_STRING(0, "object-format", &object_format, N_("hash"),
+ N_("specify the hash algorithm to use")),
+ OPT_END()
+@@ builtin/init-db.c: int cmd_init_db(int argc, const char **argv, const char *prefix)
+ UNLEAK(work_tree);
+
+ flags |= INIT_DB_EXIST_OK;
+- return init_db(git_dir, real_git_dir, template_dir, hash_algo, flags);
++ return init_db(git_dir, real_git_dir, template_dir, hash_algo,
++ main_branch, flags);
+ }

- ## refs.h ##
-@@ refs.h: int repo_dwim_log(struct repository *r, const char *str, int len, struct object_
- int dwim_ref(const char *str, int len, struct object_id *oid, char **ref);
- int dwim_log(const char *str, int len, struct object_id *oid, char **ref); -
-+/*
-+ * Retrieves the name of the default branch. If short_name is non-zero, the -+ * branch name will be prefixed with "refs/heads/".
-+ */
-+char *git_default_branch_name(int short_name);
-+
- /*
- * A ref_transaction represents a collection of reference updates that
- * should succeed or fail together.
+ ## cache.h ##
+@@ cache.h: int path_inside_repo(const char *prefix, const char *path);
+
+ int init_db(const char *git_dir, const char *real_git_dir,
+ const char *template_dir, int hash_algo,
+- unsigned int flags);
++ const char *main_branch, unsigned int flags);
+ void initialize_repository_version(int hash_algo);
+
+ void sanitize_stdfds(void);

## t/t0001-init.sh ##
@@ t/t0001-init.sh: test_expect_success MINGW 'redirect std handles' '
grep "Needed a single revision" output.txt
'

-+test_expect_success 'custom default branch name from config' '
-+ git config --global core.defaultbranchname nmb &&
-+ GIT_TEST_DEFAULT_BRANCH_NAME= git init custom-config &&
-+ git config --global --unset core.defaultbranchname &&
-+ git -C custom-config symbolic-ref HEAD >actual &&
-+ grep nmb actual
-+'
-+
-+test_expect_success 'custom default branch name from env' '
-+ GIT_TEST_DEFAULT_BRANCH_NAME=nmb git init custom-env &&
-+ git -C custom-env symbolic-ref HEAD >actual &&
-+ grep nmb actual
-+'
++test_expect_success '--main-branch' '
++ git init --main-branch=hello main-branch-option &&
++ git -C main-branch-option symbolic-ref HEAD >actual &&
++ echo refs/heads/hello >expect &&
++ test_cmp expect actual &&
+
-+test_expect_success 'invalid custom default branch name' '
-+ test_must_fail env GIT_TEST_DEFAULT_BRANCH_NAME="with space" \
-+ git init custom-invalid 2>err &&
-+ test_i18ngrep "invalid default branch name" err
++ : re-initializing should not change the main branch name &&
++ git init --main-branch=ignore main-branch-option 2>err &&
++ test_i18ngrep "ignoring --main-branch" err &&
++ git -C main-branch-option symbolic-ref HEAD >actual &&
++ grep hello actual &&
++ git -C main-branch-option config core.mainBranch >actual &&
++ grep hello actual
+'
+
test_done

  -:  ----------- >  8:  c711eba7e76 init: allow overriding the default main branch name via the config
  6:  cce86c06bbf !  9:  0e59b618169 clone: learn about the possibly-configured default branch name
     @@ Metadata
      Author: Johannes Schindelin <[email protected]>
      
       ## Commit message ##
     -    clone: learn about the possibly-configured default branch name
     +    clone: handle overridden main branch names
      
          When cloning a repository without any branches, Git chooses a default
          branch name for the as-yet unborn branch.
      
     -    Now that we can configure what the default branch name should be, we
     -    will want `git clone` to respect that setting.
     +    As part of the implicit initialization of the local repository, Git
     +    just learned to respect `init.defaultBranch` to choose a different main
     +    branch name. We now really want that branch name to be used as a
     +    fall-back.
     +
     +    At the same time, we also want to make sure that `core.mainBranch` is
     +    set correctly, reflecting the name of the main branch. In case we detect
     +    a main branch, we do have to do that explicitly, otherwise `init_db()`
     +    will already have done that for us.
      
          Signed-off-by: Johannes Schindelin <[email protected]>
      
     + ## Documentation/config/init.txt ##
     +@@ Documentation/config/init.txt: init.templateDir::
     + 	(See the "TEMPLATE DIRECTORY" section of linkgit:git-init[1].)
     + 
     + init.defaultBranch::
     +-	Allows overriding the default branch name when initializing
     +-	a new repository.
     ++	Allows overriding the default branch name e.g. when initializing
     ++	a new repository or when cloning an empty repository.
     +
       ## builtin/clone.c ##
     +@@ builtin/clone.c: static void update_head(const struct ref *our, const struct ref *remote,
     + 		/* Local default branch link */
     + 		if (create_symref("HEAD", our->name, NULL) < 0)
     + 			die(_("unable to update HEAD"));
     ++		git_config_set("core.mainbranch", head);
     + 		if (!option_bare) {
     + 			update_ref(msg, "HEAD", &our->old_oid, NULL, 0,
     + 				   UPDATE_REFS_DIE_ON_ERR);
      @@ builtin/clone.c: int cmd_clone(int argc, const char **argv, const char *prefix)
       		remote_head_points_at = NULL;
       		remote_head = NULL;
     @@ builtin/clone.c: int cmd_clone(int argc, const char **argv, const char *prefix)
      -			install_branch_config(0, "master", option_origin,
      -					      "refs/heads/master");
      +		if (!option_bare) {
     -+			char *default_branch = git_default_branch_name(0);
     ++			char *main_branch =
     ++				git_main_branch_name(MAIN_BRANCH_FULL_NAME);
      +			const char *nick;
      +
     -+			if (!skip_prefix(default_branch, "refs/heads/", &nick))
     ++			if (!skip_prefix(main_branch, "refs/heads/", &nick))
      +				BUG("unexpected default branch '%s'",
     -+				    default_branch);
     ++				    main_branch);
      +			install_branch_config(0, nick, option_origin,
     -+					      default_branch);
     -+			free(default_branch);
     ++					      main_branch);
     ++			free(main_branch);
      +		}
       	}
       
       	write_refspec_config(src_ref_prefix, our_head_points_at,
      
     - ## t/t5609-clone-branch.sh ##
     -@@ t/t5609-clone-branch.sh: test_expect_success 'clone -b not allowed with empty repos' '
     - 	test_must_fail git clone -b branch empty clone-branch-empty
     + ## t/t5606-clone-options.sh ##
     +@@ t/t5606-clone-options.sh: test_expect_success 'redirected clone -v does show progress' '
     + 
       '
       
     -+test_expect_success 'chooses correct default branch name' '
     -+	GIT_TEST_DEFAULT_BRANCH_NAME= \
     -+		git -c core.defaultBranchName=up clone empty whats-up &&
     -+	test_write_lines refs/heads/up refs/heads/up >expect &&
     -+	git -C whats-up symbolic-ref HEAD >actual &&
     -+	git -C whats-up config branch.up.merge >>actual &&
     -+	test_cmp expect actual
     ++test_expect_success 'chooses correct default main branch name' '
     ++	git init --bare empty &&
     ++	git -c init.defaultBranch=up clone empty whats-up &&
     ++	test refs/heads/up = $(git -C whats-up symbolic-ref HEAD) &&
     ++	test up = $(git -C whats-up config core.mainBranch) &&
     ++	test refs/heads/up = $(git -C whats-up config branch.up.merge)
     ++'
     ++
     ++test_expect_success 'guesses main branch name correctly' '
     ++	git init --main-branch=guess main-branch &&
     ++	test_commit -C main-branch no-spoilers &&
     ++	git -C main-branch branch abc guess &&
     ++	git clone main-branch is-it &&
     ++	test guess = $(git -C is-it config core.mainBranch) &&
     ++	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD)
      +'
      +
       test_done
  2:  06a2cea051c ! 10:  59b8f4cfbb2 remote: respect `core.defaultBranchName`
     @@ Metadata
      Author: Johannes Schindelin <[email protected]>
      
       ## Commit message ##
     -    remote: respect `core.defaultBranchName`
     +    remote: learn about the possibly-overridden default main branch name
      
          When guessing the default branch name of a remote, and there are no refs
          to guess from, we want to go with the preference specified by the user
     -    for the fall-back.
     +    for the fall-back, i.e. the default name to be used for the main branch
     +    of new repositories (because as far as the user is concerned, a remote
     +    that has no branches yet is a new repository).
      
          Signed-off-by: Johannes Schindelin <[email protected]>
      
     @@ remote.c: static void read_remotes_file(struct remote *remote)
       static void read_branches_file(struct remote *remote)
       {
      -	char *frag;
     -+	char *frag, *default_branch_name = NULL;
     ++	char *frag, *main_branch = NULL;
       	struct strbuf buf = STRBUF_INIT;
       	FILE *f = fopen_or_warn(git_path("branches/%s", remote->name), "r");
       
     @@ remote.c: static void read_branches_file(struct remote *remote)
       	/*
       	 * The branches file would have URL and optionally
      -	 * #branch specified.  The "master" (or specified) branch is
     -+	 * #branch specified.  The default (or specified) branch is
     ++	 * #branch specified.  The main (or specified) branch is
       	 * fetched and stored in the local branch matching the
       	 * remote name.
       	 */
     @@ remote.c: static void read_branches_file(struct remote *remote)
       		*(frag++) = '\0';
       	else
      -		frag = "master";
     -+		frag = default_branch_name = git_default_branch_name(1);
     ++		frag = main_branch = git_main_branch_name(MAIN_BRANCH_FOR_INIT);
       
       	add_url_alias(remote, strbuf_detach(&buf, NULL));
       	strbuf_addf(&buf, "refs/heads/%s:refs/heads/%s",
     @@ remote.c: static void read_branches_file(struct remote *remote)
       	strbuf_addf(&buf, "HEAD:refs/heads/%s", frag);
       	refspec_append(&remote->push, buf.buf);
       	remote->fetch_tags = 1; /* always auto-follow */
     -+	free(default_branch_name);
     ++	free(main_branch);
       	strbuf_release(&buf);
       }
       
      @@ remote.c: struct ref *guess_remote_head(const struct ref *head,
     + 	if (head->symref)
     + 		return copy_ref(find_ref_by_name(refs, head->symref));
       
     - 	/* If refs/heads/master could be right, it is. */
     +-	/* If refs/heads/master could be right, it is. */
     ++	/* If a remote branch exists with the main branch name, let's use it. */
       	if (!all) {
      -		r = find_ref_by_name(refs, "refs/heads/master");
     -+		char *name = git_default_branch_name(0);
     ++		char *name = git_main_branch_name(MAIN_BRANCH_FULL_NAME |
     ++						  MAIN_BRANCH_FOR_INIT);
      +
      +		r = find_ref_by_name(refs, name);
      +		free(name);
       		if (r && oideq(&r->old_oid, &head->old_oid))
       			return copy_ref(r);
       	}
     +
     + ## t/t5606-clone-options.sh ##
     +@@ t/t5606-clone-options.sh: test_expect_success 'guesses main branch name correctly' '
     + 	git -C main-branch branch abc guess &&
     + 	git clone main-branch is-it &&
     + 	test guess = $(git -C is-it config core.mainBranch) &&
     +-	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD)
     ++	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD) &&
     ++
     ++	git -c init.defaultBranch=none init --bare no-head &&
     ++	git -C main-branch push ../no-head guess abc &&
     ++	git clone no-head is-it2 &&
     ++	test_must_fail git -C is-it2 symbolic-ref refs/remotes/origin/HEAD &&
     ++	git -C no-head update-ref --no-deref HEAD refs/heads/guess &&
     ++	git -c init.defaultBranch=guess clone no-head is-it3 &&
     ++	test refs/remotes/origin/guess = \
     ++		$(git -C is-it3 symbolic-ref refs/remotes/origin/HEAD)
     + '
     + 
     + test_done
  5:  06ef42052d5 ! 11:  59d6267f099 submodule: use the (possibly overridden) default branch name
     @@ Metadata
      Author: Johannes Schindelin <[email protected]>
      
       ## Commit message ##
     -    submodule: use the (possibly overridden) default branch name
     +    submodule: use the correct default for the main branch name
      
          To allow for overriding the default branch name, we have introduced a
          config setting. With this patch, the `git submodule` command learns
     @@ builtin/submodule--helper.c: static const char *remote_submodule_branch(const ch
      -	if (!branch)
      -		return "master";
      +	if (!branch) {
     -+		static char *default_branch;
     ++		static char *fall_back;
      +
     -+		if (!default_branch)
     -+			default_branch = git_default_branch_name(1);
     ++		if (!fall_back)
     ++			fall_back = git_main_branch_name(MAIN_BRANCH_FOR_INIT);
      +
     -+		return default_branch;
     ++		return fall_back;
      +	}
       
       	if (!strcmp(branch, ".")) {
       		const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
     +
     + ## t/t7406-submodule-update.sh ##
     +@@ t/t7406-submodule-update.sh: test_expect_success 'setup a submodule tree' '
     + 	)
     + '
     + 
     ++test_expect_success 'update --remote uses configured default main branch' '
     ++	git clone super main-branch &&
     ++	test_must_fail git -C main-branch -c init.defaultBranch=hello \
     ++		submodule update --init --remote submodule 2>err &&
     ++	test_i18ngrep origin/hello err
     ++'
     ++
     + test_expect_success 'submodule update detaching the HEAD ' '
     + 	(cd super/submodule &&
     + 	 git reset --hard HEAD~1
  4:  73cb567cd33 ! 12:  e09f857f068 testsvn: respect `core.defaultBranchName`
     @@ Metadata
      Author: Johannes Schindelin <[email protected]>
      
       ## Commit message ##
     -    testsvn: respect `core.defaultBranchName`
     +    testsvn: respect `init.defaultBranch`
      
     -    Since the default branch name can now be configured, the `testsvn`
     -    remote helper needs to be told about it.
     +    The default name of the main branch in new repositories can now be
     +    configured. The `testsvn` remote helper translates the remote Subversion
     +    repository's branch name `trunk` to the hard-coded name `master`.
     +    Clearly, the intention was to make the name align with Git's detaults.
     +
     +    So while we are not talking about a newly-created repository in the
     +    `testsvn` context, it _still_ makes sense to use the overridden default
     +    name for the main branch whenever users configured it.
      
          Signed-off-by: Johannes Schindelin <[email protected]>
      
     @@ remote-testsvn.c: int cmd_main(int argc, const char **argv)
       			notes_ref_sb = STRBUF_INIT;
       	static struct remote *remote;
      -	const char *url_in;
     -+	const char *url_in, *default_branch;
     ++	const char *url_in, *remote_ref_short;
       
       	setup_git_directory();
       	if (argc < 2 || argc > 3) {
     @@ remote-testsvn.c: int cmd_main(int argc, const char **argv)
       		return 1;
       	}
       
     -+	remote_ref = git_default_branch_name(0);
     -+	if (!skip_prefix(remote_ref, "refs/heads/", &default_branch))
     ++	remote_ref = git_main_branch_name(MAIN_BRANCH_FULL_NAME |
     ++					  MAIN_BRANCH_FOR_INIT);
     ++	if (!skip_prefix(remote_ref, "refs/heads/", &remote_ref_short))
      +		BUG("unexpected remote_ref '%s'", remote_ref);
      +
       	remote = remote_get(argv[1]);
     @@ remote-testsvn.c: int cmd_main(int argc, const char **argv)
       
      -	strbuf_addf(&private_ref_sb, "refs/svn/%s/master", remote->name);
      +	strbuf_addf(&private_ref_sb, "refs/svn/%s/%s",
     -+		    remote->name, default_branch);
     ++		    remote->name, remote_ref_short);
       	private_ref = private_ref_sb.buf;
       
       	strbuf_addf(&notes_ref_sb, "refs/notes/%s/revs", remote->name);
     +
     + ## t/t9020-remote-svn.sh ##
     +@@ t/t9020-remote-svn.sh: test_expect_success REMOTE_SVN 'incremental imports must lead to the same head'
     + 	test_cmp master.good .git/refs/remotes/svnsim/master
     + '
     + 
     ++test_expect_success REMOTE_SVN 'respects configured default main branch' '
     ++	git -c init.defaultBranch=trunk remote add -f trunk \
     ++		"testsvn::file://$TEST_DIRECTORY/t9154/svn.dump" &&
     ++	git rev-parse --verify refs/remotes/trunk/trunk
     ++'
     ++
     + test_debug 'git branch -a'
     + 
     + test_done

9: f680e66dd6d < -: ----------- Document how the default branch name can be overridden

Signature · 1 line
gitgitgadget
#83 lore raw

PATCH v2 1/12 fast-export: do anonymize the primary branch name

From: Junio C Hamano <[email protected]>

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.

---
 builtin/fast-export.c            | 9 +++++----
 t/t9351-fast-export-anonymize.sh | 9 +++++----
 2 files changed, 10 insertions(+), 8 deletions(-)
builtin/fast-export.c +5 -4
index 85868162eec..1072bbf041f 100644
@@ -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++) {
t/t9351-fast-export-anonymize.sh +5 -4
index 897dc509075..2415f0ec213 100755
@@ -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
 '
 
Signature · 1 line
gitgitgadget
#84 lore raw

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

Quoted 11 lines · Junio C Hamano via GitGitGadget

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

#85 lore raw

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

Quoted 7 lines · Jeff King

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

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

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

#86 lore raw

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

Quoted 10 lines · Junio C Hamano
Quoted 7 lines · Jeff King

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.

Quoted 3 lines

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

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

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

-Peff

#87 lore raw

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

Quoted 13 lines · Jeff King
Quoted 10 lines · Junio C Hamano
Quoted 7 lines · Jeff King

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.

Quoted 6 lines
Quoted 3 lines

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

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

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

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

Quoted 3 lines

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

#88 lore raw

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

Quoted 7 lines · Elijah Newren
Quoted 2 lines

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

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

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

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

Quoted 6 lines

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

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

#89 lore raw

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

Hi Junio,

Quoted 15 lines · Junio C Hamano
Quoted 7 lines · Elijah Newren
Quoted 2 lines

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

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

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

Quoted 6 lines

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

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

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

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

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

Quoted 9 lines
Quoted 6 lines

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

Yes, absolutely. You either check "develop" out temporarily just to take anonymized export to make "develop" discoverable in the output,

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

Quoted 3 lines

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

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

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

Thanks,
Elijah

#90 lore raw

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

In reply to Elijah Newren
Quoted 7 lines · Elijah Newren
Quoted 2 lines

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

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

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

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

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

-Peff

#91 lore raw

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

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

---
 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(-)
Documentation/config/core.txt +5 -0
index 74619a9c03b..32bb5368ebb 100644
@@ -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.
fmt-merge-msg.c +4 -2
index 72d32bd73b1..43f4f829242 100644
@@ -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,
refs.c +27 -0
index 224ff66c7bb..f1854cffa2f 100644
@@ -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
refs.h +7 -0
index a92d2c74c83..a207ef01348 100644
@@ -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.
t/t6200-fmt-merge-msg.sh +7 -0
index e4c2a6eca43..7a873f4a05c 100755
@@ -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}
Signature · 1 line
gitgitgadget
#92 lore raw

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

Hi dscho

Quoted 6 lines · Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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

Quoted 7 lines

However, there are a couple of hard-coded spots in Git's source code that make this endeavor harder than necessary. For example, when formatting the commit message for merge commits, Git appends "into <branch-name>" unless the current branch is the master branch.

Clearly, this is not what one wants when already having gone through all the steps to manually rename the main branch

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

Quoted 75 lines

(and taking care of all the
fall-out such as re-targeting existing Pull Requests).

Let's introduce a way to override Git's hard-coded default:
core.mainBranch.

We will start supporting this config option in the git fmt-merge-msg command and successively adjust all other places where the main branch name is hard-coded.

---
  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(-)
Documentation/config/core.txt +5 -0
index 74619a9c03b..32bb5368ebb 100644
@@ -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.
fmt-merge-msg.c +4 -2
index 72d32bd73b1..43f4f829242 100644
@@ -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,
refs.c +8 -0
index 224ff66c7bb..f1854cffa2f 100644
@@ -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)

refs.c void expand_ref_prefix(struct argv_array *prefixes, const char *prefix) · line 580

Quoted 10 lines
refs.c +10 -0
+		die(_("could not retrieve `%s`"), config_display_key);
+
+	ret = name ? name : xstrdup(fall_back);
+
+	if (check_refname_format(ret, REFNAME_ALLOW_ONELEVEL))
+		die(_("invalid branch name: %s = %s"),
+		    config_display_key, name);
+
+	if (name != ret)
+		free(name);

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

Quoted 17 lines
refs.c +9 -0
+
+	return ret;
+}
+
+char *git_main_branch_name(void)
+{
+	return repo_main_branch_name(the_repository);
+}
+
  /*
   * *string and *len will only be substituted, and *string returned (for
   * later free()ing) if the string passed in is a magic short-hand form
refs.h +0 -0
index a92d2c74c83..a207ef01348 100644

refs.h int repo_dwim_log(struct repository *r, const char *str, int len, struct object_ · line 158

Quoted 5 lines
refs.h +2 -0
@@ -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 27 lines
refs.h +5 -0
+ * repository.
+ */
+char *git_main_branch_name(void);
+char *repo_main_branch_name(struct repository *r);
+
  /*
   * A ref_transaction represents a collection of reference updates that
   * should succeed or fail together.
t/t6200-fmt-merge-msg.sh +7 -0
index e4c2a6eca43..7a873f4a05c 100755
@@ -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}
#93 lore raw

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

Hi Phillip,

Quoted 9 lines · Phillip Wood
Quoted 6 lines · Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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 9 lines
Quoted 7 lines

However, there are a couple of hard-coded spots in Git's source code that make this endeavor harder than necessary. For example, when formatting the commit message for merge commits, Git appends "into <branch-name>" unless the current branch is the master branch.

Clearly, this is not what one wants when already having gone through all the steps to manually rename the main branch

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

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

Quoted 80 lines
Quoted 80 lines

(and taking care of all the
fall-out such as re-targeting existing Pull Requests).

Let's introduce a way to override Git's hard-coded default:
core.mainBranch.

We will start supporting this config option in the git fmt-merge-msg command and successively adjust all other places where the main branch name is hard-coded.

---
  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(-)
Documentation/config/core.txt +5 -0
index 74619a9c03b..32bb5368ebb 100644
@@ -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.
fmt-merge-msg.c +4 -1
index 72d32bd73b1..43f4f829242 100644
@@ -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,
refs.c +13 -0
index 224ff66c7bb..f1854cffa2f 100644
@@ -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))
Quoted 8 lines

refs.c void expand_ref_prefix(struct argv_array *prefixes, const char *prefix) · line 580

Quoted 5 lines
refs.c +5 -0
+		die(_("invalid branch name: %s = %s"),
+		    config_display_key, name);
+
+	if (name != ret)
+		free(name);

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

Right.

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

Quoted 22 lines
Quoted 22 lines
refs.c +9 -0
+
+	return ret;
+}
+
+char *git_main_branch_name(void)
+{
+	return repo_main_branch_name(the_repository);
+}
+
  /*
   * *string and *len will only be substituted, and *string returned (for

* later free()ing) if the string passed in is a magic short-hand form

refs.h +0 -0
index a92d2c74c83..a207ef01348 100644
@@ -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);
 
Quoted 4 lines

refs.h int repo_dwim_log(struct repository *r, const char *str, int len, struct object_ · line 158

Quoted 2 lines
refs.h +2 -0
+/*
+ * 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

Quoted 35 lines

Best Wishes

Phillip

Quoted 28 lines
refs.h +5 -0
+ * repository.
+ */
+char *git_main_branch_name(void);
+char *repo_main_branch_name(struct repository *r);
+
  /*
   * A ref_transaction represents a collection of reference updates that

* should succeed or fail together.

t/t6200-fmt-merge-msg.sh +4 -0
index e4c2a6eca43..7a873f4a05c 100755
@@ -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

&&

t/t6200-fmt-merge-msg.sh +3 -0
+	! grep "into default" actual
+'
+
  test_expect_success 'merge.log=3 limits shortlog length' '
   cat >expected <<-EOF &&
   Merge branch ${apos}left${apos}
#94 lore raw

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

In reply to Johannes Schindelin via GitGitGadget

"Johannes Schindelin via GitGitGadget" <[email protected]>

Quoted 14 lines · writes:
fmt-merge-msg.c +1 -1
index 72d32bd73b1..43f4f829242 100644
@@ -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++) {

fmt-merge-msg.c static void fmt_merge_msg_title(struct strbuf *out, · line 459

Quoted 10 lines
fmt-merge-msg.c +3 -1
@@ -451,10 +451,12 @@ static void fmt_merge_msg_title(struct strbuf *out,
 			strbuf_addf(out, " of %s", srcs.items[i].string);
 	}
 
-	if (!strcmp("master", current_branch))
+	main_branch = git_main_branch_name();
+	if (!strcmp(main_branch, current_branch))
 		strbuf_addch(out, '\n');
 	else
 		strbuf_addf(out, " into %s\n", current_branch);
+	free(main_branch);

While you are at it, taking

https://lore.kernel.org/git/20200614211500.GA22505@dcvr/

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

fmt-merge-msg.c static void fmt_merge_msg_title(struct strbuf *out,

Quoted 4 lines
fmt-merge-msg.c +4 -0
+core.mainBranch::
+	The name of the main (or: primary) branch in the current repository.
+	For historical reasons, `master` is used as the fall-back for this
+	setting.

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

An instruction

... oh, if you want to do so, you can set the core.mainBranch configuration variable to 'main'

sounds strange than

... oh, if you want to do so, you can set the core.primaryBranch configuration variable to 'main'

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

#95 lore raw

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

Hi Junio,

Quoted 30 lines · Junio C Hamano

"Johannes Schindelin via GitGitGadget" <[email protected]>

Quoted 14 lines · writes:
fmt-merge-msg.c +1 -1
index 72d32bd73b1..43f4f829242 100644
@@ -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++) {

fmt-merge-msg.c static void fmt_merge_msg_title(struct strbuf *out, · line 459

Quoted 10 lines
fmt-merge-msg.c +3 -1
@@ -451,10 +451,12 @@ static void fmt_merge_msg_title(struct strbuf *out,
 			strbuf_addf(out, " of %s", srcs.items[i].string);
 	}
 
-	if (!strcmp("master", current_branch))
+	main_branch = git_main_branch_name();
+	if (!strcmp(main_branch, current_branch))
 		strbuf_addch(out, '\n');
 	else
 		strbuf_addf(out, " into %s\n", current_branch);
+	free(main_branch);

While you are at it, taking

Quoted 5 lines

https://lore.kernel.org/git/20200614211500.GA22505@dcvr/

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

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

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

Ciao,
Dscho

Quoted 25 lines

fmt-merge-msg.c static void fmt_merge_msg_title(struct strbuf *out,

Quoted 5 lines
fmt-merge-msg.c +4 -0
+core.mainBranch::
+	The name of the main (or: primary) branch in the current repository.
+	For historical reasons, `master` is used as the fall-back for this
+	setting.

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

An instruction

... oh, if you want to do so, you can set the core.mainBranch configuration variable to 'main'

sounds strange than

... oh, if you want to do so, you can set the core.primaryBranch configuration variable to 'main'

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

#96 lore raw

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

In reply to Johannes Schindelin via GitGitGadget

Documentation/config/core.txt core.abbrev:: · line 633

Quoted 6 lines · Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

Documentation/config/core.txt +4 -0
+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.

#97 lore raw

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

Quoted 15 lines · Ævar Arnfjörð Bjarmason

Documentation/config/core.txt core.abbrev:: · line 633

Quoted 6 lines · Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

Documentation/config/core.txt +4 -0
+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).

Quoted 6 lines

I think we should do the same here for consistency & ease of reading.

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

Very good point.

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

Thanks.

[Reference]

*1* https://lore.kernel.org/git/[email protected]

#98 lore raw

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

In reply to Johannes Schindelin via GitGitGadget
Quoted 5 lines · Johannes Schindelin via GitGitGadget
refs.c +5 -0
+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";

refs.c void expand_ref_prefix(struct argv_array *prefixes, const char *prefix) · line 577

Quoted 10 lines
refs.c +10 -0
+	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

#99 lore raw

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

Quoted 5 lines · Jeff King

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

Yup.

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

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

#100 lore raw

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

Hi,

Quoted 10 lines · Junio C Hamano
Quoted 5 lines · Jeff King

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

Yup.

Quoted 7 lines

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

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

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

Thank you for your help improving the patch series, Dscho

#101 lore raw

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

In reply to Johannes Schindelin via GitGitGadget

Am 15.06.20 um 14:50 schrieb Johannes Schindelin via GitGitGadget:

fmt-merge-msg.c static void fmt_merge_msg_title(struct strbuf *out, · line 460

Quoted 12 lines
fmt-merge-msg.c +3 -1
@@ -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

#102 lore raw

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

Quoted 5 lines · Johannes Sixt

Am 15.06.20 um 14:50 schrieb Johannes Schindelin via GitGitGadget:

Quoted 4 lines
fmt-merge-msg.c +0 -0
@@ -451,10 +451,12 @@ static void fmt_merge_msg_title(struct strbuf *out,
 			strbuf_addf(out, " of %s", srcs.items[i].string);
 	}
 
Quoted 12 lines

fmt-merge-msg.c static void fmt_merge_msg_title(struct strbuf *out, · line 460

Quoted 8 lines
fmt-merge-msg.c +3 -1
-	if (!strcmp("master", current_branch))
+	main_branch = git_main_branch_name();
+	if (!strcmp(main_branch, current_branch))
 		strbuf_addch(out, '\n');
 	else
 		strbuf_addf(out, " into %s\n", current_branch);
+	free(main_branch);
 }

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

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

#103 lore raw

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

Hi Junio & Hannes,

Quoted 20 lines · Junio C Hamano
Quoted 5 lines · Johannes Sixt

Am 15.06.20 um 14:50 schrieb Johannes Schindelin via GitGitGadget:

Quoted 4 lines
fmt-merge-msg.c +0 -0
@@ -451,10 +451,12 @@ static void fmt_merge_msg_title(struct strbuf *out,
 			strbuf_addf(out, " of %s", srcs.items[i].string);
 	}
 
Quoted 12 lines

fmt-merge-msg.c static void fmt_merge_msg_title(struct strbuf *out, · line 460

Quoted 8 lines
fmt-merge-msg.c +3 -1
-	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.

Quoted 5 lines

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

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

Ciao,
Dscho

#104 lore raw

PATCH v2 3/12 send-pack/transport-helper: respect `core.mainBranch`

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

---
 send-pack.c             | 6 +++++-
 t/t5528-push-default.sh | 7 +++++++
 transport-helper.c      | 6 +++++-
 3 files changed, 17 insertions(+), 2 deletions(-)
send-pack.c +5 -1
index 0abee22283d..2532864c812 100644
@@ -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)
t/t5528-push-default.sh +7 -0
index 4d1e0c363ea..f7583b20f87 100755
@@ -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 &&
transport-helper.c +5 -1
index a46afcb69db..8c8f40e322d 100644
@@ -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;
 	}
 
Signature · 1 line
gitgitgadget
#105 lore raw

PATCH v2 4/12 git_main_branch_name(): optionally report the full ref name

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

---
 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(-)
fmt-merge-msg.c +1 -1
index 43f4f829242..03dba905643 100644
@@ -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
refs.c +8 -4
index f1854cffa2f..7da3ac178c4 100644
@@ -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);
 }
 
 /*
refs.h +6 -2
index a207ef01348..96472f9a9f5 100644
@@ -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
send-pack.c +1 -1
index 2532864c812..898720511d0 100644
@@ -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",
transport-helper.c +1 -1
index 8c8f40e322d..7a54e5b2fb2 100644
@@ -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"
Signature · 1 line
gitgitgadget
#106 lore raw

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

Hi dscho

Quoted 47 lines · Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

---
  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(-)
fmt-merge-msg.c +1 -1
index 43f4f829242..03dba905643 100644
@@ -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
refs.c +2 -1
index f1854cffa2f..7da3ac178c4 100644
@@ -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";

refs.c char *repo_main_branch_name(struct repository *r) · line 577

Quoted 8 lines
refs.c +4 -1
@@ -570,7 +571,10 @@ char *repo_main_branch_name(struct repository *r)
  	if (repo_config_get_string(r, config_key, &name) < 0)
  		die(_("could not retrieve `%s`"), config_display_key);
 
-	ret = name ? name : xstrdup(fall_back);
+	if (full_name)
+		ret = xstrfmt("refs/heads/%s", name ? name : fall_back);
+	else
+		ret = name ? name : xstrdup(fall_back);

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

Quoted 19 lines
refs.c +2 -2
  	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);
  }
 
  /*
refs.h +0 -0
index a207ef01348..96472f9a9f5 100644

refs.h int dwim_log(const char *str, int len, struct object_id *oid, char **ref); · line 163

Quoted 7 lines
refs.h +3 -0
@@ -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 35 lines
refs.h +3 -2
-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
send-pack.c +1 -1
index 2532864c812..898720511d0 100644
@@ -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",
transport-helper.c +1 -1
index 8c8f40e322d..7a54e5b2fb2 100644
@@ -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"
#107 lore raw

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

Hi Phillip,

Quoted 82 lines · Phillip Wood
Quoted 47 lines · Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

---
  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(-)
fmt-merge-msg.c +1 -0
index 43f4f829242..03dba905643 100644
@@ -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
refs.c +2 -1
index f1854cffa2f..7da3ac178c4 100644
@@ -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";

refs.c char *repo_main_branch_name(struct repository *r) · line 577

Quoted 7 lines
refs.c +4 -0
@@ -570,7 +571,10 @@ char *repo_main_branch_name(struct repository *r)
   if (repo_config_get_string(r, config_key, &name) < 0)
    die(_("could not retrieve `%s`"), config_display_key);
  -	ret = name ? name : xstrdup(fall_back);
+	if (full_name)
+		ret = xstrfmt("refs/heads/%s", name ? name : fall_back);
+	else
+		ret = name ? name : xstrdup(fall_back);

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

Quoted 23 lines
refs.c +2 -2
   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);
  }
 
  /*
refs.h +0 -0
index a207ef01348..96472f9a9f5 100644
@@ -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.
Quoted 8 lines
Quoted 5 lines
refs.h +2 -0
+ *
+ * The result is an allocated string. Unless the flags ask for a short

name, it
+ * will be prefixed with "refs/heads/".
*/

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

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

Ciao,
Dscho

Quoted 41 lines

Best Wishes

Phillip

Quoted 35 lines
refs.h +3 -2
-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
send-pack.c +1 -1
index 2532864c812..898720511d0 100644
@@ -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",
transport-helper.c +1 -1
index 8c8f40e322d..7a54e5b2fb2 100644
@@ -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"
#108 lore raw

PATCH v2 5/12 fast-export: handle overridden main branch names correctly

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

---
 builtin/fast-export.c            | 11 ++++++++++-
 t/t9351-fast-export-anonymize.sh |  6 ++++++
 2 files changed, 16 insertions(+), 1 deletion(-)
builtin/fast-export.c +10 -1
index 1072bbf041f..deeb01b6937 100644
@@ -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);
t/t9351-fast-export-anonymize.sh +6 -0
index 2415f0ec213..f42be635c2f 100755
@@ -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
Signature · 1 line
gitgitgadget
#109 lore raw

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

Hi dscho

Quoted 31 lines · Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

---
  builtin/fast-export.c            | 11 ++++++++++-
  t/t9351-fast-export-anonymize.sh |  6 ++++++
  2 files changed, 16 insertions(+), 1 deletion(-)
builtin/fast-export.c +3 -0
index 1072bbf041f..deeb01b6937 100644
@@ -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

builtin/fast-export.c static const char *anonymize_refname(const char *refname) · line 535

Quoted 10 lines
builtin/fast-export.c +7 -1
+	 * repositories (and `master` for aged ones), and such well-known names
+	 * may not necessarily need anonymizing, it could be configured to use
+	 * a secret word that the user may not want to reveal.
  	 */
-	if (!strcmp(refname, "refs/heads/master"))
+	if (!main_branch)
+		main_branch = git_main_branch_name(MAIN_BRANCH_FULL_NAME);
+
+	if (!strcmp(refname, main_branch))
  		return "refs/heads/ref0";

This leaks main_branch if it came from git_main_branch_name()

Best Wishes

Phillip

Quoted 19 lines
builtin/fast-export.c +0 -0
  	strbuf_reset(&anon);
t/t9351-fast-export-anonymize.sh +6 -0
index 2415f0ec213..f42be635c2f 100755
@@ -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
#110 lore raw

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

Quoted 6 lines · Phillip Wood
Quoted 5 lines
builtin/fast-export.c +1 -0
@@ -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 8 lines

builtin/fast-export.c static const char *anonymize_refname(const char *refname) · line 535

Quoted 6 lines
builtin/fast-export.c +4 -1
-	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

#111 lore raw

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

Hi Peff

Quoted 17 lines · Jeff King
Quoted 6 lines · Phillip Wood
Quoted 5 lines
builtin/fast-export.c +1 -0
@@ -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 8 lines

builtin/fast-export.c static const char *anonymize_refname(const char *refname) · line 535

Quoted 6 lines
builtin/fast-export.c +4 -1
-	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()

Quoted 2 lines

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

Quoted 7 lines

(at which point we
could free it, but don't bother to do so, letting the process exit take care of it, and trusting in leak detectors to be aware that it's still reachable, as we do for lots of other process-lifetime allocations).

-Peff

#112 lore raw

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

In reply to Jeff King

Hi Peff,

Quoted 17 lines · Jeff King
Quoted 6 lines · Phillip Wood
Quoted 5 lines
builtin/fast-export.c +1 -0
@@ -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 8 lines

builtin/fast-export.c static const char *anonymize_refname(const char *refname) · line 535

Quoted 6 lines
builtin/fast-export.c +4 -1
-	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()

Quoted 5 lines

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

#113 lore raw

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

In reply to Johannes Schindelin via GitGitGadget

"Johannes Schindelin via GitGitGadget" <[email protected]>

builtin/fast-export.c static const char *anonymize_refname(const char *refname) · line 527

Quoted 2 lines · writes:
builtin/fast-export.c +2 -0
+	 * While the main branch name might often be `main` for new
+	 * repositories (and `master` for aged ones), and such well-known names

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

builtin/fast-export.c static const char *anonymize_refname(const char *refname) · line 535

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

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

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

#114 lore raw

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

Hi Junio,

Quoted 9 lines · Junio C Hamano

"Johannes Schindelin via GitGitGadget" <[email protected]>

builtin/fast-export.c static const char *anonymize_refname(const char *refname) · line 527

Quoted 2 lines · writes:
builtin/fast-export.c +2 -0
+	 * While the main branch name might often be `main` for new
+	 * repositories (and `master` for aged ones), and such well-known names

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

Quoted 14 lines

builtin/fast-export.c static const char *anonymize_refname(const char *refname) · line 535

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

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

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

Quoted 2 lines

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

Welcome back! I hope you were able to rest.

Ciao,
Dscho

#115 lore raw

PATCH v2 6/12 branch -m: adjust `core.mainBranch` if necessary

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

---
 builtin/branch.c  | 9 +++++++++
 t/t3200-branch.sh | 9 +++++++++
 2 files changed, 18 insertions(+)
builtin/branch.c +9 -0
index accb61b1aae..62f8db5fb05 100644
@@ -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);
t/t3200-branch.sh +9 -0
index 411a70b0ce9..328544f2736 100755
@@ -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
Signature · 1 line
gitgitgadget
#116 lore raw

PATCH v2 7/12 init: allow specifying the main branch name for the new repository

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

---
 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(-)
Documentation/git-init.txt +7 -0
index adc6adfd380..011a7ff4d76 100644
@@ -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
builtin/clone.c +2 -1
index cb48a291caf..487b0a42d75 100644
@@ -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;
builtin/init-db.c +27 -7
index 0b7222e7188..287cdafaab1 100644
@@ -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);
 }
cache.h +1 -1
index 0f0485ecfe2..afd5ad3121f 100644
@@ -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);
t/t0001-init.sh +15 -0
index 1edd5aeb8f0..5d8e321a703 100755
@@ -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
Signature · 1 line
gitgitgadget
#117 lore raw

PATCH v2 8/12 init: allow overriding the default main branch name via the config

In reply to Johannes Schindelin via GitGitGadget

From: Don Goodman-Wilson <[email protected]>

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.

---
 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(-)
Documentation/config/init.txt +4 -0
index 46fa8c6a082..6ae4a38416e 100644
@@ -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.
builtin/init-db.c +4 -2
index 287cdafaab1..d09c9dc7845 100644
@@ -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);
 
refs.c +5 -2
index 7da3ac178c4..4b0e5b14062 100644
@@ -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;
 
refs.h +4 -0
index 96472f9a9f5..c801d08490c 100644
@@ -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);
 
t/t0001-init.sh +16 -0
index 5d8e321a703..fbf02066940 100755
@@ -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
Signature · 1 line
gitgitgadget
#118 lore raw

PATCH v2 9/12 clone: handle overridden main branch names

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

---
 Documentation/config/init.txt |  4 ++--
 builtin/clone.c               | 16 +++++++++++++---
 t/t5606-clone-options.sh      | 17 +++++++++++++++++
 3 files changed, 32 insertions(+), 5 deletions(-)
Documentation/config/init.txt +2 -2
index 6ae4a38416e..dc77f8c8446 100644
@@ -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.
builtin/clone.c +13 -3
index 487b0a42d75..755fcaeb0ba 100644
@@ -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,
t/t5606-clone-options.sh +17 -0
index 9e24ec88e67..98b2d8527f6 100755
@@ -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
Signature · 1 line
gitgitgadget
#119 lore raw

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

builtin/clone.c static void update_head(const struct ref *our, const struct ref *remote, · line 724

Quoted 12 lines · Johannes Schindelin via GitGitGadget
builtin/clone.c +1 -0
index 487b0a42d75..755fcaeb0ba 100644
@@ -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

#120 lore raw

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

Hi Peff,

Quoted 17 lines · Jeff King

builtin/clone.c static void update_head(const struct ref *our, const struct ref *remote, · line 724

Quoted 12 lines · Johannes Schindelin via GitGitGadget
builtin/clone.c +1 -0
index 487b0a42d75..755fcaeb0ba 100644
@@ -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...

Quoted 3 lines

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.

Quoted 6 lines

But we would not want it to be missing, because that will likely need to stay a default for "master" indefinitely (to keep behavior for existing repositories). However, it won't be missing. We'll always have set it during the init_db() call, and this is just overriding that. So we'd end update_head() with either:

Quoted 8 lines

- 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

#121 lore raw

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

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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

---
 remote.c                 | 15 ++++++++++-----
 t/t5606-clone-options.sh | 11 ++++++++++-
 2 files changed, 20 insertions(+), 6 deletions(-)
remote.c +10 -5
index 534c6426f1e..2dcf4ac6d15 100644
@@ -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);
 	}
t/t5606-clone-options.sh +10 -1
index 98b2d8527f6..61ce9c09920 100755
@@ -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
Signature · 1 line
gitgitgadget
#122 lore raw

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

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

---
 builtin/submodule--helper.c | 10 ++++++++--
 t/t7406-submodule-update.sh |  7 +++++++
 2 files changed, 15 insertions(+), 2 deletions(-)
builtin/submodule--helper.c +8 -2
index 46c03d2a126..48d73e8d9cb 100644
@@ -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);
t/t7406-submodule-update.sh +7 -0
index 4fb447a143e..641113afef4 100755
@@ -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
Signature · 1 line
gitgitgadget
#123 lore raw

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

Quoted 5 lines · Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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

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

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

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

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

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

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

It seems like, independent of any change in the default branch names, we ought to be using $remote_name/HEAD for this case anyway. I suspect that would be a behavior improvement by itself, as it means more cases could avoid having to specify the branch name in .gitmodules manually. Probably nobody noticed so far because "HEAD" is almost always "master" in the current world. It technically breaks the case that you truly did want to use "master" in the submodule, but they set HEAD to something else, and you couldn't be bothered to put it into your .gitmodules file. That seems rather unlikely to me.

And then everything would Just Work without having to worry about the local mainbranch value at all.

Alternatively, submodule--helper could pass back the empty string for "no, we don't have a configured branch name" and this shell code could actually try a sequence of reasonable guesses: init.mainbranch, then "master" (and between the two, "main" if that later becomes the default).

-Peff

#124 lore raw

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

Hi Peff,

Quoted 52 lines · Jeff King
Quoted 5 lines · Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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

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

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

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

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

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

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

It seems like, independent of any change in the default branch names, we ought to be using $remote_name/HEAD for this case anyway. I suspect that would be a behavior improvement by itself, as it means more cases could avoid having to specify the branch name in .gitmodules manually. Probably nobody noticed so far because "HEAD" is almost always "master" in the current world. It technically breaks the case that you truly did want to use "master" in the submodule, but they set HEAD to something else, and you couldn't be bothered to put it into your .gitmodules file. That seems rather unlikely to me.

Quoted 2 lines

And then everything would Just Work without having to worry about the local mainbranch value at all.

This is the route that I am taking.

Please note that t7519 contains a few test cases that rely on the current confusing behavior where git submodule update --remote fetches the remote master even if that is not the remote repository's current branch!

I did adjust t7519 to stop verifying this confusing behavior, and to verify the saner behavior instead.

This is of course a bit worrisome, as there might actually be users out there relying on the confusing behavior.

However, I think it is okay to fix this:

- The git submodule update --remote command does not strike me as awfully common. In fact, I had never heard of it before I worked on this here patch.

- Current Git's behavior when running this command is outright confusing, unless the remote repository's current branch _is_ master (in which case the proposed behavior matches the old behavior).

- It is actually easily fixed by setting submodule.<name>.branch to master _iff_ users want to reinstate the old behavior.

Quoted 5 lines

Alternatively, submodule--helper could pass back the empty string for "no, we don't have a configured branch name" and this shell code could actually try a sequence of reasonable guesses: init.mainbranch, then "master" (and between the two, "main" if that later becomes the default).

Quite honestly: I'd rather not.

Thank you,
Dscho

#125 lore raw

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

Quoted 12 lines · Johannes Schindelin
Quoted 1 line

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

Quoted 6 lines

- 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

#126 lore raw

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

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

---
 remote-testsvn.c      | 12 +++++++++---
 t/t9020-remote-svn.sh |  6 ++++++
 2 files changed, 15 insertions(+), 3 deletions(-)
remote-testsvn.c +9 -3
index 3af708c5b67..6ec300bf6c3 100644
@@ -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);
t/t9020-remote-svn.sh +6 -0
index 6fca08e5e35..c931193f013 100755
@@ -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
Signature · 1 line
gitgitgadget
#127 lore raw

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

Quoted 6 lines · Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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/[email protected]/

#128 lore raw

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

Hi Peff,

Quoted 10 lines · Jeff King
Quoted 6 lines · Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

Quoted 1 line

I'd agree that moving this to Git's default name makes sense.

Okay.

Quoted 5 lines

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

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

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

Thank you,
Dscho

Quoted 5 lines

-Peff

[1] https://lore.kernel.org/git/[email protected]/

#129 lore raw

v3 cover Allow overriding the default name of the default branch

In reply to Johannes Schindelin via GitGitGadget

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

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

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

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

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

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

This patch series allows overriding the branch name being used for new repositories' main branch. This can be configured via init.defaultBranch.

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

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

Changes since v2:

* Dropped the fast-export patches, as they have been superseded by Peff's jk/fast-export-anonym
[https://github.com/gitgitgadget/git/commits/jk/fast-export-anonym].

* Adjusted the fmt-merge-msg patch so as to not special-case master anymore (instead of special-casing a specific "main" branch).

* Modified the git submodule patch so that it uses origin/HEAD instead of trying to look for a remote branch with the name indicated by init.defaultBranch.

Changes since v1:

* The modifications to respect GIT_TEST_DEFAULT_BRANCH_NAME have been backed out from this patch series, as they are only relevant once we start converting the test suite to accommodate for a new default main branch name.

* An error message that started with an upper-case letter was downcased.

* git_default_branch_name()'s logic was simplified by replacing an if ... else ... by a ternary assignment.

* The git_default_branch_name() function was renamed to git_main_branch_name() and a corresponding repo_main_branch_name() was introduced.

* The "init" commit message's first paragraph now elaborates a little bit on the reasoning why projects want to move away from the current default branch name.

* The "init" commit was split into two.

* There are now two config settings: init.defaultBranch (defining the branch name to use when initializing new repositories) and core.mainBranch (which is now configured by init_db(), declaring what the name of the main branch is in this repository).

* The commits were re-ordered to introduce the concept of core.mainBranch first because technically, this is something that we could do even without changing git init at all.

* git fast-export --anonymize now always uses the ref name ref0 for the main branch, no matter whether it was overridden or whether the fall-back is in effect.

* The code comment regarding anonymizing the main branch to ref0 in git fast-export --anonymize was enhanced.

* A new patch was added to rename core.mainBranch if the main branch is renamed via git branch -m.

* Added a patch that introduces support for git init --main-branch=<branch-name>.

* Where possible, I added tests (although I did not try to extend test coverage to all changes: the send-pack.c/transport-helper.c patch only adds a test for the send-pack.c adjustment, for example).

Don Goodman-Wilson (1):
init: allow setting the default for the initial branch name via the
config

Johannes Schindelin (7):
fmt-merge-msg: stop treating master specially send-pack/transport-helper: avoid mentioning a particular branch
submodule: use a better fall-back for missing remote.<name>.branch
init: allow specifying the initial branch name for the new repository
clone: use configured default branch name when appropriate
remote: use the configured default branch name when appropriate
testsvn: respect init.defaultBranch

 Documentation/config/init.txt                 |  4 ++
 Documentation/git-init.txt                    |  7 ++
 Documentation/git-submodule.txt               |  4 +-
 builtin/clone.c                               | 13 ++--
 builtin/init-db.c                             | 34 +++++++--
 builtin/submodule--helper.c                   |  2 +-
 cache.h                                       |  2 +-
 fmt-merge-msg.c                               |  5 +-
 refs.c                                        | 30 ++++++++
 refs.h                                        |  9 +++
 remote-testsvn.c                              | 10 ++-
 remote.c                                      | 14 +++-
 send-pack.c                                   |  2 +-
 t/t0001-init.sh                               | 26 +++++++
 t/t1507-rev-parse-upstream.sh                 |  2 +-
 t/t4013-diff-various.sh                       |  4 +-
 t/t4013/diff.log_--decorate=full_--all        |  2 +-
 t/t4013/diff.log_--decorate_--all             |  2 +-
 ...--patch-with-stat_--summary_master_--_dir_ |  2 +-
 t/t4013/diff.log_--patch-with-stat_master     |  2 +-
 .../diff.log_--patch-with-stat_master_--_dir_ |  2 +-
 ...ot_--cc_--patch-with-stat_--summary_master |  2 +-
 ..._--root_--patch-with-stat_--summary_master |  2 +-
 .../diff.log_--root_--patch-with-stat_master  |  2 +-
 ...root_-c_--patch-with-stat_--summary_master |  2 +-
 t/t4013/diff.log_--root_-p_master             |  2 +-
 t/t4013/diff.log_--root_master                |  2 +-
 t/t4013/diff.log_-m_-p_--first-parent_master  |  2 +-
 t/t4013/diff.log_-m_-p_master                 |  4 +-
 t/t4013/diff.log_-p_--first-parent_master     |  2 +-
 t/t4013/diff.log_-p_master                    |  2 +-
 t/t4013/diff.log_master                       |  2 +-
 t/t4013/diff.show_--first-parent_master       |  2 +-
 t/t4013/diff.show_-c_master                   |  2 +-
 t/t4013/diff.show_-m_master                   |  4 +-
 t/t4013/diff.show_master                      |  2 +-
 ...ot_--cc_--patch-with-stat_--summary_master |  2 +-
 ...root_-c_--patch-with-stat_--summary_master |  2 +-
 t/t4202-log.sh                                | 72 +++++++++----------
 t/t5528-push-default.sh                       |  6 ++
 t/t5606-clone-options.sh                      | 24 +++++++
 t/t6200-fmt-merge-msg.sh                      | 36 +++++-----
 t/t7406-submodule-update.sh                   | 16 +++++
 t/t7419-submodule-set-branch.sh               |  7 +-
 t/t7600-merge.sh                              | 14 ++--
 t/t7608-merge-messages.sh                     | 10 +--
 t/t9020-remote-svn.sh                         |  6 ++
 transport-helper.c                            |  2 +-
 48 files changed, 287 insertions(+), 122 deletions(-)

base-commit: c9c318d6bf26bcecdca5b6f31683b9d5887a83ee
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-656%2Fdscho%2Fdefault-branch-name-option-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-656/dscho/default-branch-name-option-v3
Pull-Request: https://github.com/gitgitgadget/git/pull/656

Range-diff vs v2:

  1:  ebd10f73cd <  -:  ---------- fast-export: do anonymize the primary branch name
  -:  ---------- >  1:  fffdb9944f fmt-merge-msg: stop treating `master` specially
  3:  bd8af3755a !  2:  a29943d7bb send-pack/transport-helper: respect `core.mainBranch`
     @@ Metadata
      Author: Johannes Schindelin <[email protected]>
      
       ## Commit message ##
     -    send-pack/transport-helper: respect `core.mainBranch`
     +    send-pack/transport-helper: avoid mentioning a particular branch
      
     -    When mentioning the main branch name in an error message, we want to go
     -    with the preference specified by the user, only falling back to Git's
     -    own, hard-coded default when none was configured explicitly.
     +    When trying to push all matching branches, but none match, we offer a
     +    message suggesting to push the `master` branch.
     +
     +    However, we want to step away from making that branch any more special
     +    than any other branch, so let's reword that message to mention no branch
     +    in particular.
      
          Signed-off-by: Johannes Schindelin <[email protected]>
      
       ## send-pack.c ##
      @@ send-pack.c: int send_pack(struct send_pack_args *args,
     - 	}
       
       	if (!remote_refs) {
     -+		char *branch_name = git_main_branch_name();
     -+
       		fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
      -			"Perhaps you should specify a branch such as 'master'.\n");
     -+			"Perhaps you should specify a branch such as '%s'.\n",
     -+			branch_name);
     -+		free(branch_name);
     ++			"Perhaps you should specify a specific branch.\n");
       		return 0;
       	}
       	if (args->atomic && !atomic_supported)
     @@ t/t5528-push-default.sh: test_expect_success 'push from/to new branch with upstr
       
      +test_expect_success '"matching" fails if none match' '
      +	git init --bare empty &&
     -+	test_must_fail git -c core.mainBranch=unmatch push empty : 2>actual &&
     -+	needle="Perhaps you should specify a branch such as '\''unmatch'\''" &&
     -+	test_i18ngrep "$needle" actual
     ++	test_must_fail git push empty : 2>actual &&
     ++	test_i18ngrep "Perhaps you should specify a specific branch" actual
      +'
      +
       test_expect_success 'push ambiguously named branch with upstream, matching and simple' '
     @@ t/t5528-push-default.sh: test_expect_success 'push from/to new branch with upstr
      
       ## transport-helper.c ##
      @@ transport-helper.c: static int push_refs(struct transport *transport,
     - 	}
     - 
       	if (!remote_refs) {
     -+		char *branch_name = git_main_branch_name();
     -+
       		fprintf(stderr,
       			_("No refs in common and none specified; doing nothing.\n"
      -			  "Perhaps you should specify a branch such as 'master'.\n"));
     -+			  "Perhaps you should specify a branch such as '%s'.\n"),
     -+			branch_name);
     -+		free(branch_name);
     ++			  "Perhaps you should specify a specific branch.\n"));
       		return 0;
       	}

11: 59d6267f09 ! 3: 6bda69541b submodule: use the correct default for the main branch name
@@ Metadata
Author: Johannes Schindelin <[email protected]>

## Commit message ##
- submodule: use the correct default for the main branch name
+ submodule: use a better fall-back for missing remote.<name>.branch

- To allow for overriding the default branch name, we have introduced a
- config setting. With this patch, the git submodule command learns
- about this, too.
+ When remote.<name>.branch is not configured, git submodule update
+ currently falls back to using the branch name master. A much better
+ idea, however, is to use HEAD: on all Git servers running reasonably
+ recent Git versions, the symref HEAD points to the main branch.
+
+ Note: t7419 demonstrates that there _might_ be use cases out there that
+ _expect_ git submodule update --remote to update submodules to the
+ remote master branch even if the remote HEAD points to another
+ branch. Arguably, this patch makes the behavior more intuitive, but
+ there is a slight possibility that this might cause regressions in
+ obscure setups.

+ ## Documentation/git-submodule.txt ##
+@@ Documentation/git-submodule.txt: OPTIONS
+ .gitmodules for update --remote. A special value of . is used to
+ indicate that the name of the branch in the submodule should be the
+ same name as the current branch in the current repository. If the
+- option is not specified, it defaults to 'master'.
++ option is not specified, it defaults to 'HEAD'.
+
+ -f::
+ --force::
+@@ Documentation/git-submodule.txt: OPTIONS
+ the superproject's recorded SHA-1 to update the submodule, use the
+ status of the submodule's remote-tracking branch. The remote used
+ is branch's remote (branch.<name>.remote), defaulting to origin.
+- The remote branch used defaults to master, but the branch name may
++ The remote branch used defaults to HEAD, but the branch name may
+ be overridden by setting the submodule.<name>.branch option in
+ either .gitmodules or .git/config (with .git/config taking
+ precedence).
+
## builtin/submodule--helper.c ##
@@ builtin/submodule--helper.c: static const char *remote_submodule_branch(const char *path)
- branch = sub->branch;
free(key);

-- if (!branch)
+ if (!branch)
- return "master";
-+ if (!branch) {
-+ static char *fall_back;
-+
-+ if (!fall_back)
-+ fall_back = git_main_branch_name(MAIN_BRANCH_FOR_INIT);
-+
-+ return fall_back;
-+ }
++ return "HEAD";

if (!strcmp(branch, ".")) {
const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
@@ t/t7406-submodule-update.sh: test_expect_success 'setup a submodule tree' '
)
'

-+test_expect_success 'update --remote uses configured default main branch' '
-+ git clone super main-branch &&
-+ test_must_fail git -C main-branch -c init.defaultBranch=hello \
-+ submodule update --init --remote submodule 2>err &&
-+ test_i18ngrep origin/hello err
++test_expect_success 'update --remote falls back to using HEAD' '
++ test_create_repo main-branch-submodule &&
++ test_commit -C main-branch-submodule initial &&
++
++ test_create_repo main-branch &&
++ git -C main-branch submodule add ../main-branch-submodule &&
++ git -C main-branch commit -m add-submodule &&
++
++ git -C main-branch-submodule switch -c hello &&
++ test_commit -C main-branch-submodule world &&
++
++ git clone --recursive main-branch main-branch-clone &&
++ git -C main-branch-clone submodule update --remote main-branch-submodule &&
++ test_path_exists main-branch-clone/main-branch-submodule/world.t
+'
+
test_expect_success 'submodule update detaching the HEAD ' '
(cd super/submodule &&
git reset --hard HEAD~1
+
+ ## t/t7419-submodule-set-branch.sh ##
+@@ t/t7419-submodule-set-branch.sh: test_expect_success 'test submodule set-branch --branch' '
+ '
+
+ test_expect_success 'test submodule set-branch --default' '
++ test_commit -C submodule c &&
+ (cd super &&
+ git submodule set-branch --default submodule &&
+ ! grep branch .gitmodules &&
+ git submodule update --remote &&
+ cat <<-\EOF >expect &&
+- a
++ c
+ EOF
+ git -C submodule show -s --pretty=%s >actual &&
+ test_cmp expect actual
+@@ t/t7419-submodule-set-branch.sh: test_expect_success 'test submodule set-branch --default' '
+ '
+
+ test_expect_success 'test submodule set-branch -b' '
++ test_commit -C submodule b &&
+ (cd super &&
+ git submodule set-branch -b topic submodule &&
+ grep "branch = topic" .gitmodules &&
+@@ t/t7419-submodule-set-branch.sh: test_expect_success 'test submodule set-branch -b' '
+ '
+
+ test_expect_success 'test submodule set-branch -d' '
++ test_commit -C submodule d &&
+ (cd super &&
+ git submodule set-branch -d submodule &&
+ ! grep branch .gitmodules &&
+ git submodule update --remote &&
+ cat <<-\EOF >expect &&
+- a
++ d
+ EOF
+ git -C submodule show -s --pretty=%s >actual &&
+ test_cmp expect actual
7: 0ec04b2086 ! 4: e8a6587c1a init: allow specifying the main branch name for the new repository

     @@ Metadata
      Author: Johannes Schindelin <[email protected]>
      
       ## Commit message ##
     -    init: allow specifying the main branch name for the new repository
     +    init: allow specifying the initial branch name for the new repository
      
     -    There is a growing number of projects trying to avoid the non-inclusive
     -    name `master` in their repositories: The `master`/`slave` terminology is
     -    insensitive and perpetuates injustice. This `master`/`slave` idea is
     -    actually where Git's naming comes from, as it was inherited from
     -    BitKeeper which uses the term in exactly this way, see
     -    https://mail.gnome.org/archives/desktop-devel-list/2019-May/msg00066.html
     +    There is a growing number of projects and companies desiring to change
     +    the main branch name of their repositories (see e.g.
     +    https://twitter.com/mislav/status/1270388510684598272 for background on
     +    this).
      
          To change that branch name for new repositories, currently the only way
          to do that automatically is by copying all of Git's template directory,
     @@ Commit message
          template files.
      
          To make this process much less cumbersome, let's introduce a new option:
     -    `--main-branch=<branch-name>`.
     -
     -    This will not only initialize the repository with the specified initial
     -    branch; It will also record that branch name in `core.mainBranch`.
     +    `--initial-branch=<branch-name>`.
      
          Signed-off-by: Johannes Schindelin <[email protected]>
      
     @@ Documentation/git-init.txt: SYNOPSIS
       [verse]
       'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
       	  [--separate-git-dir <git dir>] [--object-format=<format]
     -+	  [-b <branch-name> | --main-branch=<branch-name>]
     ++	  [-b <branch-name> | --initial-branch=<branch-name>]
       	  [--shared[=<permissions>]] [directory]
       
       
     @@ Documentation/git-init.txt: repository.
       If this is reinitialization, the repository will be moved to the specified path.
       
      +-b <branch-name::
     -+--main-branch=<branch-name>::
     ++--initial-branch=<branch-name>::
      +
     -+Use the specified name for the main (or: initial) branch in the newly created
     -+repository. If not specified, fall back to the default name: `master`.
     ++Use the specified name for the initial branch in the newly created repository.
     ++If not specified, fall back to the default name: `master`.
      +
       --shared[=(false|true|umask|group|all|world|everybody|0xxx)]::
       
     @@ builtin/init-db.c: void initialize_repository_version(int hash_algo)
       
       static int create_default_files(const char *template_path,
       				const char *original_git_dir,
     -+				const char *main_branch,
     ++				const char *initial_branch,
       				const struct repository_format *fmt)
       {
       	struct stat st1;
     @@ builtin/init-db.c: static int create_default_files(const char *template_path,
      -		if (create_symref("HEAD", "refs/heads/master", NULL) < 0)
      +		char *ref;
      +
     -+		if (!main_branch)
     -+			main_branch = "master";
     ++		if (!initial_branch)
     ++			initial_branch = "master";
      +
     -+		ref = xstrfmt("refs/heads/%s", main_branch);
     ++		ref = xstrfmt("refs/heads/%s", initial_branch);
      +		if (check_refname_format(ref, 0) < 0)
     -+			die(_("invalid main branch name: '%s'"), main_branch);
     ++			die(_("invalid initial branch name: '%s'"),
     ++			    initial_branch);
      +
      +		if (create_symref("HEAD", ref, NULL) < 0)
       			exit(1);
      -	}
      +		free(ref);
     -+
     -+		git_config_set("core.mainbranch", main_branch);
     -+	} else if (main_branch)
     -+		warning(_("re-init: ignoring --main-branch=%s"), main_branch);
     ++	} else if (initial_branch)
     ++		warning(_("re-init: ignoring --initial-branch=%s"),
     ++			initial_branch);
       
       	initialize_repository_version(fmt->hash_algo);
       
     @@ builtin/init-db.c: static void validate_hash_algorithm(struct repository_format
       
       int init_db(const char *git_dir, const char *real_git_dir,
      -	    const char *template_dir, int hash, unsigned int flags)
     -+	    const char *template_dir, int hash, const char *main_branch,
     ++	    const char *template_dir, int hash, const char *initial_branch,
      +	    unsigned int flags)
       {
       	int reinit;
     @@ builtin/init-db.c: int init_db(const char *git_dir, const char *real_git_dir,
       
      -	reinit = create_default_files(template_dir, original_git_dir, &repo_fmt);
      +	reinit = create_default_files(template_dir, original_git_dir,
     -+				      main_branch, &repo_fmt);
     ++				      initial_branch, &repo_fmt);
       
       	create_object_directory();
       
     @@ builtin/init-db.c: int cmd_init_db(int argc, const char **argv, const char *pref
       	const char *template_dir = NULL;
       	unsigned int flags = 0;
       	const char *object_format = NULL;
     -+	const char *main_branch = NULL;
     ++	const char *initial_branch = NULL;
       	int hash_algo = GIT_HASH_UNKNOWN;
       	const struct option init_db_options[] = {
       		OPT_STRING(0, "template", &template_dir, N_("template-directory"),
     @@ builtin/init-db.c: int cmd_init_db(int argc, const char **argv, const char *pref
       		OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET),
       		OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
       			   N_("separate git dir from working tree")),
     -+		OPT_STRING('b', "main-branch", &main_branch, N_("name"),
     -+			   N_("override the name of the main branch")),
     ++		OPT_STRING('b', "initial-branch", &initial_branch, N_("name"),
     ++			   N_("override the name of the initial branch")),
       		OPT_STRING(0, "object-format", &object_format, N_("hash"),
       			   N_("specify the hash algorithm to use")),
       		OPT_END()
     @@ builtin/init-db.c: int cmd_init_db(int argc, const char **argv, const char *pref
       	flags |= INIT_DB_EXIST_OK;
      -	return init_db(git_dir, real_git_dir, template_dir, hash_algo, flags);
      +	return init_db(git_dir, real_git_dir, template_dir, hash_algo,
     -+		       main_branch, flags);
     ++		       initial_branch, flags);
       }
      
       ## cache.h ##
     @@ cache.h: int path_inside_repo(const char *prefix, const char *path);
       int init_db(const char *git_dir, const char *real_git_dir,
       	    const char *template_dir, int hash_algo,
      -	    unsigned int flags);
     -+	    const char *main_branch, unsigned int flags);
     ++	    const char *initial_branch, unsigned int flags);
       void initialize_repository_version(int hash_algo);
       
       void sanitize_stdfds(void);
     @@ t/t0001-init.sh: test_expect_success MINGW 'redirect std handles' '
       	grep "Needed a single revision" output.txt
       '
       
     -+test_expect_success '--main-branch' '
     -+	git init --main-branch=hello main-branch-option &&
     -+	git -C main-branch-option symbolic-ref HEAD >actual &&
     ++test_expect_success '--initial-branch' '
     ++	git init --initial-branch=hello initial-branch-option &&
     ++	git -C initial-branch-option symbolic-ref HEAD >actual &&
      +	echo refs/heads/hello >expect &&
      +	test_cmp expect actual &&
      +
     -+	: re-initializing should not change the main branch name &&
     -+	git init --main-branch=ignore main-branch-option 2>err &&
     -+	test_i18ngrep "ignoring --main-branch" err &&
     -+	git -C main-branch-option symbolic-ref HEAD >actual &&
     -+	grep hello actual &&
     -+	git -C main-branch-option config core.mainBranch >actual &&
     ++	: re-initializing should not change the branch name &&
     ++	git init --initial-branch=ignore initial-branch-option 2>err &&
     ++	test_i18ngrep "ignoring --initial-branch" err &&
     ++	git -C initial-branch-option symbolic-ref HEAD >actual &&
      +	grep hello actual
      +'
      +

2: f4d5473915 ! 5: a500e0f214 fmt-merge-msg: introduce a way to override the main branch name
@@
## Metadata ##
-Author: Johannes Schindelin <[email protected]>
+Author: Don Goodman-Wilson <[email protected]>

## Commit message ##
- fmt-merge-msg: introduce a way to override the main branch name
+ init: allow setting the default for the initial branch name via the config

- There is a growing number of projects and companies desiring to change
- the main branch name of their repositories (see e.g.
- https://twitter.com/mislav/status/1270388510684598272 for background on
- this).
+ We just introduced the command-line option
+ --initial-branch=<branch-name> to allow initializing a new repository
+ with a different initial branch than the hard-coded one.

- However, there are a couple of hard-coded spots in Git's source code
- that make this endeavor harder than necessary. For example, when
- formatting the commit message for merge commits, Git appends "into
- <branch-name>" unless the current branch is the master branch.
+ To allow users to override the initial branch name more permanently
+ (i.e. without having to specify the name manually for each and every
+ git init invocation), let's introduce the init.defaultBranch config
+ setting.

- Clearly, this is not what one wants when already having gone through all
- the steps to manually rename the main branch (and taking care of all the
- fall-out such as re-targeting existing Pull Requests).
+ Helped-by: Johannes Schindelin <[email protected]>
+ Helped-by: Derrick Stolee <[email protected]>
+ Signed-off-by: Don Goodman-Wilson <[email protected]>

- Let's introduce a way to override Git's hard-coded default:
- core.mainBranch.
-
- We will start supporting this config option in the git fmt-merge-msg
- command and successively adjust all other places where the main branch
- name is hard-coded.
-
- Signed-off-by: Johannes Schindelin <[email protected]>
-
- ## Documentation/config/core.txt ## -@@ Documentation/config/core.txt: core.abbrev::
- in your repository, which hopefully is enough for
- abbreviated object names to stay unique for some time.
- The minimum length is 4.
+ ## Documentation/config/init.txt ## +@@
+ init.templateDir::
+ Specify the directory from which templates will be copied.
+ (See the "TEMPLATE DIRECTORY" section of linkgit:git-init[1].)
+
-+core.mainBranch::
-+ The name of the main (or: primary) branch in the current repository.
-+ For historical reasons, master is used as the fall-back for this
-+ setting.
++init.defaultBranch::
++ Allows overriding the default branch name when initializing
++ a new repository.

- ## fmt-merge-msg.c ##
-@@ fmt-merge-msg.c: static void fmt_merge_msg_title(struct strbuf *out,
- const char *current_branch)
- {
- int i = 0;
-- char *sep = "";
-+ char *sep = "", *main_branch;
+ ## builtin/init-db.c ##
+@@ builtin/init-db.c: static int create_default_files(const char *template_path,
+ char *ref;

- strbuf_addstr(out, "Merge ");
- for (i = 0; i < srcs.nr; i++) {
-@@ fmt-merge-msg.c: static void fmt_merge_msg_title(struct strbuf *out,
- strbuf_addf(out, " of %s", srcs.items[i].string);
- }
+ if (!initial_branch)
+- initial_branch = "master";
++ initial_branch = git_default_branch_name();

-- if (!strcmp("master", current_branch))
-+ main_branch = git_main_branch_name();
-+ if (!strcmp(main_branch, current_branch))
- strbuf_addch(out, '\n');
- else
- strbuf_addf(out, " into %s\n", current_branch);
-+ free(main_branch);
- }
-
- static void fmt_tag_signature(struct strbuf *tagbuf,
+ ref = xstrfmt("refs/heads/%s", initial_branch);
+ if (check_refname_format(ref, 0) < 0)

## refs.c ##
@@ refs.c: void expand_ref_prefix(struct argv_array *prefixes, const char *prefix)
argv_array_pushf(prefixes, *p, len, prefix);
}

-+char *repo_main_branch_name(struct repository *r)
++char *repo_default_branch_name(struct repository *r)
+{
-+ const char *config_key = "core.mainbranch";
-+ const char *config_display_key = "core.mainBranch";
-+ const char *fall_back = "master";
-+ char *name = NULL, *ret;
++ const char *config_key = "init.defaultbranch";
++ const char *config_display_key = "init.defaultBranch";
++ char *ret = NULL, *full_ref;
+
-+ if (repo_config_get_string(r, config_key, &name) < 0)
++ if (repo_config_get_string(r, config_key, &ret) < 0)
+ die(_("could not retrieve %s"), config_display_key);
+
-+ ret = name ? name : xstrdup(fall_back);
-+
-+ if (check_refname_format(ret, REFNAME_ALLOW_ONELEVEL))
-+ die(_("invalid branch name: %s = %s"),
-+ config_display_key, name);
++ if (!ret)
++ ret = xstrdup("master");
+
-+ if (name != ret)
-+ free(name);
++ full_ref = xstrfmt("refs/heads/%s", ret);
++ if (check_refname_format(full_ref, 0))
++ die(_("invalid branch name: %s = %s"), config_display_key, ret);
++ free(full_ref);
+
+ return ret;
+}
+
-+char *git_main_branch_name(void)
++const char *git_default_branch_name(void)
+{
-+ return repo_main_branch_name(the_repository);
++ static char *ret;
++
++ if (!ret)
++ ret = repo_default_branch_name(the_repository);
++
++ return ret;
+}
+
/*
@@ refs.h: int repo_dwim_log(struct repository *r, const char *str, int len, struct
int dwim_log(const char *str, int len, struct object_id *oid, char **ref);

+/*
-+ * Retrieves the name of the main (or: primary) branch of the given -+ * repository.
++ * Retrieves the default branch name for newly-initialized repositories. ++ *
++ * The return value of repo_default_branch_name() is an allocated string. The ++ * return value of git_default_branch_name() is a singleton.
+ */
-+char *git_main_branch_name(void);
-+char *repo_main_branch_name(struct repository *r);
++const char *git_default_branch_name(void);
++char *repo_default_branch_name(struct repository *r);
+
/*
* A ref_transaction represents a collection of reference updates that
* should succeed or fail together.

- ## t/t6200-fmt-merge-msg.sh ##
-@@ t/t6200-fmt-merge-msg.sh: test_expect_success 'setup FETCH_HEAD' '
- git fetch . left
+ ## t/t0001-init.sh ##
+@@ t/t0001-init.sh: test_expect_success '--initial-branch' '
+ grep hello actual
'

-+test_expect_success 'with overridden default branch name' '
-+ test_when_finished "git switch master" &&
-+ git switch -c default &&
-+ git -c core.mainBranch=default fmt-merge-msg <.git/FETCH_HEAD >actual &&
-+ ! grep "into default" actual
++test_expect_success 'overridden default initial branch name (config)' '
++ test_config_global init.defaultBranch nmb &&
++ git init initial-branch-config &&
++ git -C initial-branch-config symbolic-ref HEAD >actual &&
++ grep nmb actual
++'
++
++test_expect_success 'invalid default branch name' '
++ test_config_global init.defaultBranch "with space" &&
++ test_must_fail git init initial-branch-invalid 2>err &&
++ test_i18ngrep "invalid branch name" err
+'
+
- test_expect_success 'merge.log=3 limits shortlog length' '
- cat >expected <<-EOF &&
- Merge branch ${apos}left${apos}
+ test_done

  4:  ca1c63c3e0 <  -:  ---------- git_main_branch_name(): optionally report the full ref name
  5:  a3be4f39aa <  -:  ---------- fast-export: handle overridden main branch names correctly
  6:  933e314813 <  -:  ---------- branch -m: adjust `core.mainBranch` if necessary
  8:  c711eba7e7 <  -:  ---------- init: allow overriding the default main branch name via the config
  9:  0e59b61816 !  6:  c0d74cedd1 clone: handle overridden main branch names
     @@ Metadata
      Author: Johannes Schindelin <[email protected]>
      
       ## Commit message ##
     -    clone: handle overridden main branch names
     +    clone: use configured default branch name when appropriate
      
          When cloning a repository without any branches, Git chooses a default
          branch name for the as-yet unborn branch.
      
     -    As part of the implicit initialization of the local repository, Git
     -    just learned to respect `init.defaultBranch` to choose a different main
     +    As part of the implicit initialization of the local repository, Git just
     +    learned to respect `init.defaultBranch` to choose a different initial
          branch name. We now really want that branch name to be used as a
          fall-back.
      
     -    At the same time, we also want to make sure that `core.mainBranch` is
     -    set correctly, reflecting the name of the main branch. In case we detect
     -    a main branch, we do have to do that explicitly, otherwise `init_db()`
     -    will already have done that for us.
     -
          Signed-off-by: Johannes Schindelin <[email protected]>
      
       ## Documentation/config/init.txt ##
     @@ Documentation/config/init.txt: init.templateDir::
      +	a new repository or when cloning an empty repository.
      
       ## builtin/clone.c ##
     -@@ builtin/clone.c: static void update_head(const struct ref *our, const struct ref *remote,
     - 		/* Local default branch link */
     - 		if (create_symref("HEAD", our->name, NULL) < 0)
     - 			die(_("unable to update HEAD"));
     -+		git_config_set("core.mainbranch", head);
     - 		if (!option_bare) {
     - 			update_ref(msg, "HEAD", &our->old_oid, NULL, 0,
     - 				   UPDATE_REFS_DIE_ON_ERR);
      @@ builtin/clone.c: int cmd_clone(int argc, const char **argv, const char *prefix)
       		remote_head_points_at = NULL;
       		remote_head = NULL;
     @@ builtin/clone.c: int cmd_clone(int argc, const char **argv, const char *prefix)
      -			install_branch_config(0, "master", option_origin,
      -					      "refs/heads/master");
      +		if (!option_bare) {
     -+			char *main_branch =
     -+				git_main_branch_name(MAIN_BRANCH_FULL_NAME);
     -+			const char *nick;
     ++			const char *branch = git_default_branch_name();
     ++			char *ref = xstrfmt("refs/heads/%s", branch);
      +
     -+			if (!skip_prefix(main_branch, "refs/heads/", &nick))
     -+				BUG("unexpected default branch '%s'",
     -+				    main_branch);
     -+			install_branch_config(0, nick, option_origin,
     -+					      main_branch);
     -+			free(main_branch);
     ++			install_branch_config(0, branch, option_origin, ref);
     ++			free(ref);
      +		}
       	}
       
     @@ t/t5606-clone-options.sh: test_expect_success 'redirected clone -v does show pro
       
       '
       
     -+test_expect_success 'chooses correct default main branch name' '
     ++test_expect_success 'chooses correct default initial branch name' '
      +	git init --bare empty &&
      +	git -c init.defaultBranch=up clone empty whats-up &&
      +	test refs/heads/up = $(git -C whats-up symbolic-ref HEAD) &&
     -+	test up = $(git -C whats-up config core.mainBranch) &&
      +	test refs/heads/up = $(git -C whats-up config branch.up.merge)
      +'
      +
     -+test_expect_success 'guesses main branch name correctly' '
     -+	git init --main-branch=guess main-branch &&
     -+	test_commit -C main-branch no-spoilers &&
     -+	git -C main-branch branch abc guess &&
     -+	git clone main-branch is-it &&
     -+	test guess = $(git -C is-it config core.mainBranch) &&
     ++test_expect_success 'guesses initial branch name correctly' '
     ++	git init --initial-branch=guess initial-branch &&
     ++	test_commit -C initial-branch no-spoilers &&
     ++	git -C initial-branch branch abc guess &&
     ++	git clone initial-branch is-it &&
      +	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD)
      +'
      +

10: 59b8f4cfbb ! 7: 00a1b281e5 remote: learn about the possibly-overridden default main branch name
@@ Metadata
Author: Johannes Schindelin <[email protected]>

## Commit message ##
- remote: learn about the possibly-overridden default main branch name
+ remote: use the configured default branch name when appropriate

When guessing the default branch name of a remote, and there are no refs to guess from, we want to go with the preference specified by the user
- for the fall-back, i.e. the default name to be used for the main branch
- of new repositories (because as far as the user is concerned, a remote
- that has no branches yet is a new repository).
+ for the fall-back, i.e. the default name to be used for the initial
+ branch of new repositories (because as far as the user is concerned, a
+ remote that has no branches yet is a new repository).
+
+ At the same time, when talking to an older Git server that does not
+ report a symref for HEAD (but instead reports a commit hash), let's
+ try to guess the configured default branch name first. If it does not
+ match the reported commit hash, let's fall back to master as before.

## remote.c ##
-@@ remote.c: static void read_remotes_file(struct remote *remote) -
- static void read_branches_file(struct remote *remote)
- {
-- char *frag;
-+ char *frag, *main_branch = NULL;
- struct strbuf buf = STRBUF_INIT;
- FILE *f = fopen_or_warn(git_path("branches/%s", remote->name), "r");
-
@@ remote.c: static void read_branches_file(struct remote *remote)

/*
@@ remote.c: static void read_branches_file(struct remote *remote)
*(frag++) = '\0';
else
- frag = "master";
-+ frag = main_branch = git_main_branch_name(MAIN_BRANCH_FOR_INIT);
++ frag = (char *)git_default_branch_name();

add_url_alias(remote, strbuf_detach(&buf, NULL)); strbuf_addf(&buf, "refs/heads/%s:refs/heads/%s",
-@@ remote.c: static void read_branches_file(struct remote *remote)
- strbuf_addf(&buf, "HEAD:refs/heads/%s", frag);
- refspec_append(&remote->push, buf.buf);
- remote->fetch_tags = 1; /* always auto-follow */
-+ free(main_branch);
- strbuf_release(&buf);
- }
-
@@ remote.c: struct ref *guess_remote_head(const struct ref *head,
if (head->symref)
return copy_ref(find_ref_by_name(refs, head->symref));

- /* If refs/heads/master could be right, it is. */
-+ /* If a remote branch exists with the main branch name, let's use it. */
++ /* If a remote branch exists with the default branch name, let's use it. */
if (!all) {
-- r = find_ref_by_name(refs, "refs/heads/master");
-+ char *name = git_main_branch_name(MAIN_BRANCH_FULL_NAME |
-+ MAIN_BRANCH_FOR_INIT);
++ char *ref = xstrfmt("refs/heads/%s", git_default_branch_name());
++
++ r = find_ref_by_name(refs, ref);
++ free(ref);
++ if (r && oideq(&r->old_oid, &head->old_oid))
++ return copy_ref(r);
+
-+ r = find_ref_by_name(refs, name);
-+ free(name);
++ /* Fall back to the hard-coded historical default */
+ r = find_ref_by_name(refs, "refs/heads/master");
if (r && oideq(&r->old_oid, &head->old_oid))
return copy_ref(r);
- }

## t/t5606-clone-options.sh ##
-@@ t/t5606-clone-options.sh: test_expect_success 'guesses main branch name correctly' '
- git -C main-branch branch abc guess &&
- git clone main-branch is-it &&
- test guess = $(git -C is-it config core.mainBranch) &&
+@@ t/t5606-clone-options.sh: test_expect_success 'guesses initial branch name correctly' '
+ test_commit -C initial-branch no-spoilers &&
+ git -C initial-branch branch abc guess &&
+ git clone initial-branch is-it &&
- test refs/heads/guess = $(git -C is-it symbolic-ref HEAD)
+ test refs/heads/guess = $(git -C is-it symbolic-ref HEAD) &&
+
+ git -c init.defaultBranch=none init --bare no-head &&
-+ git -C main-branch push ../no-head guess abc &&
++ git -C initial-branch push ../no-head guess abc &&
+ git clone no-head is-it2 &&
+ test_must_fail git -C is-it2 symbolic-ref refs/remotes/origin/HEAD &&
+ git -C no-head update-ref --no-deref HEAD refs/heads/guess &&
12: e09f857f06 ! 8: 1aa0e63785 testsvn: respect init.defaultBranch
@@ Metadata
## Commit message ##
testsvn: respect init.defaultBranch

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

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

@@ remote-testsvn.c: int cmd_main(int argc, const char **argv)
return 1;
}

-+ remote_ref = git_main_branch_name(MAIN_BRANCH_FULL_NAME |
-+ MAIN_BRANCH_FOR_INIT);
-+ if (!skip_prefix(remote_ref, "refs/heads/", &remote_ref_short))
-+ BUG("unexpected remote_ref '%s'", remote_ref);
++ remote_ref_short = git_default_branch_name();
++ remote_ref = xstrfmt("refs/heads/%s", remote_ref_short);
+
remote = remote_get(argv[1]);
url_in = (argc == 3) ? argv[2] : remote->url[0];
@@ t/t9020-remote-svn.sh: test_expect_success REMOTE_SVN 'incremental imports must
test_cmp master.good .git/refs/remotes/svnsim/master
'

-+test_expect_success REMOTE_SVN 'respects configured default main branch' ' ++test_expect_success REMOTE_SVN 'respects configured default initial branch' '
+ git -c init.defaultBranch=trunk remote add -f trunk \
+ "testsvn::file://$TEST_DIRECTORY/t9154/svn.dump" &&
+ git rev-parse --verify refs/remotes/trunk/trunk

Signature · 1 line
gitgitgadget
#130 lore raw

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

From: Johannes Schindelin <[email protected]>

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.

---
 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(-)
fmt-merge-msg.c +1 -4
index 72d32bd73b..cfb8ff2f33 100644
@@ -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,
t/t1507-rev-parse-upstream.sh +1 -1
index dfc0d96d8a..f213aa8053 100755
@@ -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
 )
 '
t/t4013-diff-various.sh +2 -2
index 3f60f7d96c..43267d6024 100755
@@ -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
t/t4013/diff.log_--decorate=full_--all +1 -1
index 3f9b872ece..c56783b985 100644
@@ -31,7 +31,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 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 <[email protected]>
t/t4013/diff.log_--decorate_--all +1 -1
index f5e20e1e14..1cbdc038f4 100644
@@ -31,7 +31,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (side)
 Author: A U Thor <[email protected]>
t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ +1 -1
index a18f1472a9..f5b1b6516b 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <[email protected]>
t/t4013/diff.log_--patch-with-stat_master +1 -1
index ae425c4672..af23803cdc 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <[email protected]>
t/t4013/diff.log_--patch-with-stat_master_--_dir_ +1 -1
index d5207cadf4..814098fbf8 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <[email protected]>
t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master +1 -1
index 0fc1e8cd71..b927fe4a98 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
  dir/sub | 2 ++
  file0   | 3 +++
t/t4013/diff.log_--root_--patch-with-stat_--summary_master +1 -1
index dffc09dde9..6db3cea329 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <[email protected]>
t/t4013/diff.log_--root_--patch-with-stat_master +1 -1
index 55aa98012d..98e9c320c3 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <[email protected]>
t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master +1 -1
index 019d85f7de..b61b1117ae 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
  dir/sub | 2 ++
  file0   | 3 +++
t/t4013/diff.log_--root_-p_master +1 -1
index b42c334439..345bd9e8a9 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <[email protected]>
t/t4013/diff.log_--root_master +1 -1
index e8f46159da..db56b1fe6b 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <[email protected]>
t/t4013/diff.log_-m_-p_--first-parent_master +1 -1
index 7a0073f529..bcadb50e26 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 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
t/t4013/diff.log_-m_-p_master +2 -2
index 9ca62a01ed..2acf43a9fb 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 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 <[email protected]>
 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
t/t4013/diff.log_-p_--first-parent_master +1 -1
index 3fc896d424..c6a5876d80 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
 Author: A U Thor <[email protected]>
t/t4013/diff.log_-p_master +1 -1
index bf1326dc36..1841cded94 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <[email protected]>
t/t4013/diff.log_master +1 -1
index a8f6ce5abd..f8ec445eb3 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <[email protected]>
t/t4013/diff.show_--first-parent_master +1 -1
index 3dcbe473a0..94548f4598 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 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
t/t4013/diff.show_-c_master +1 -1
index 81aba8da96..1c46ed64fd 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 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
t/t4013/diff.show_-m_master +2 -2
index 4ea2ee453d..7559fc22f8 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 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 <[email protected]>
 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
t/t4013/diff.show_master +1 -1
index fb08ce0e46..57091c5d90 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 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
t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master +1 -1
index 30aae7817b..5f13a71bb5 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
  dir/sub | 2 ++
  file0   | 3 +++
t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master +1 -1
index d1d32bd34c..8acb88267b 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
  dir/sub | 2 ++
  file0   | 3 +++
t/t4202-log.sh +36 -36

215 lines not on this page · raw message

t/t6200-fmt-merge-msg.sh +18 -18
index e4c2a6eca4..2b3fd498d0 100755
@@ -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
 
t/t7600-merge.sh +7 -7
index 5883a6adc3..1d45f9a4ed 100755
@@ -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' '
t/t7608-merge-messages.sh +5 -5
index 8e7e0a5865..2af33f195b 100755
@@ -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
Signature · 1 line
gitgitgadget
#131 lore raw

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

"Johannes Schindelin via GitGitGadget" <[email protected]>

Quoted 31 lines · writes:

From: Johannes Schindelin <[email protected]>

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.

---
 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 +-
Quoted 8 lines
 t/t4013/diff.show_master                      |  2 +-
 ...ot_--cc_--patch-with-stat_--summary_master |  2 +-
 ...root_-c_--patch-with-stat_--summary_master |  2 +-
 t/t4202-log.sh                                | 72 +++++++++----------
 t/t6200-fmt-merge-msg.sh                      | 36 +++++-----
 t/t7600-merge.sh                              | 14 ++--
 t/t7608-merge-messages.sh                     | 10 +--
 29 files changed, 94 insertions(+), 97 deletions(-)

This must have been tedious as the tests with merge commits are all over the place (I know updating t4013 would not have been too much of the work as it has its own self-update knob, but it still is a lot of work to verify that the changes make sense).

Thanks.

#132 lore raw

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

Hi Junio,

Quoted 43 lines · Junio C Hamano

"Johannes Schindelin via GitGitGadget" <[email protected]>

Quoted 31 lines · writes:

From: Johannes Schindelin <[email protected]>

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.

---
 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 +-
Quoted 8 lines
 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(-)
Quoted 4 lines

This must have been tedious as the tests with merge commits are all over the place (I know updating t4013 would not have been too much of the work as it has its own self-update knob, but it still is a lot of work to verify that the changes make sense).

I missed the self-update knob, but in any case, I would not have used it, anyway, to make sure that I do look closely at all the sites.

Ciao,
Dscho

#133 lore raw

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

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

---
 send-pack.c             | 2 +-
 t/t5528-push-default.sh | 6 ++++++
 transport-helper.c      | 2 +-
 3 files changed, 8 insertions(+), 2 deletions(-)
send-pack.c +1 -1
index 0abee22283..db79cdac77 100644
@@ -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)
t/t5528-push-default.sh +6 -0
index 4d1e0c363e..68b84c4add 100755
@@ -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 &&
transport-helper.c +1 -1
index a46afcb69d..b81a3486bd 100644
@@ -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;
 	}
 
Signature · 1 line
gitgitgadget
#134 lore raw

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

"Johannes Schindelin via GitGitGadget" <[email protected]>

transport-helper.c static int push_refs(struct transport *transport, · line 1049

Quoted 6 lines · writes:
transport-helper.c +1 -1
@@ -1046,7 +1046,7 @@ static int push_refs(struct transport *transport,
 	if (!remote_refs) {
 		fprintf(stderr,
 			_("No refs in common and none specified; doing nothing.\n"
-			  "Perhaps you should specify a branch such as 'master'.\n"));
+			  "Perhaps you should specify a specific branch.\n"));

Hmph, not just "specify a branch."? Maybe it is just me, but "specify a specific branch" did not roll well on my tongue.

#135 lore raw

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

Hi Junio,

Quoted 12 lines · Junio C Hamano

"Johannes Schindelin via GitGitGadget" <[email protected]>

transport-helper.c static int push_refs(struct transport *transport, · line 1049

Quoted 6 lines · writes:
transport-helper.c +1 -1
@@ -1046,7 +1046,7 @@ static int push_refs(struct transport *transport,
 	if (!remote_refs) {
 		fprintf(stderr,
 			_("No refs in common and none specified; doing nothing.\n"
-			  "Perhaps you should specify a branch such as 'master'.\n"));
+			  "Perhaps you should specify a specific branch.\n"));

Hmph, not just "specify a branch."? Maybe it is just me, but "specify a specific branch" did not roll well on my tongue.

Oh well. "Perhaps you should specify a branch" sounded too judgmental to me, but I'm not a native speaker, so I simply removed the word "specific".

Ciao,
Dscho

#136 lore raw

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

Quoted 17 lines · Johannes Schindelin

Hi Junio,

Quoted 12 lines · Junio C Hamano

"Johannes Schindelin via GitGitGadget" <[email protected]>

transport-helper.c static int push_refs(struct transport *transport, · line 1049

Quoted 6 lines · writes:
transport-helper.c +1 -1
@@ -1046,7 +1046,7 @@ static int push_refs(struct transport *transport,
 	if (!remote_refs) {
 		fprintf(stderr,
 			_("No refs in common and none specified; doing nothing.\n"
-			  "Perhaps you should specify a branch such as 'master'.\n"));
+			  "Perhaps you should specify a specific branch.\n"));

Hmph, not just "specify a branch."? Maybe it is just me, but "specify a specific branch" did not roll well on my tongue.

Quoted 2 lines

Oh well. "Perhaps you should specify a branch" sounded too judgmental to me, but I'm not a native speaker, so I simply removed the word "specific".

I'm not either. Note that when I say "maybe it is just me", I usually am not asking to change anything.

#137 lore raw

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

Hi Junio,

Quoted 17 lines · Junio C Hamano
Quoted 15 lines · Johannes Schindelin
Quoted 12 lines · Junio C Hamano

"Johannes Schindelin via GitGitGadget" <[email protected]>

transport-helper.c static int push_refs(struct transport *transport, · line 1049

Quoted 6 lines · writes:
transport-helper.c +1 -1
@@ -1046,7 +1046,7 @@ static int push_refs(struct transport *transport,
 	if (!remote_refs) {
 		fprintf(stderr,
 			_("No refs in common and none specified; doing nothing.\n"
-			  "Perhaps you should specify a branch such as 'master'.\n"));
+			  "Perhaps you should specify a specific branch.\n"));

Hmph, not just "specify a branch."? Maybe it is just me, but "specify a specific branch" did not roll well on my tongue.

Quoted 4 lines
Quoted 2 lines

Oh well. "Perhaps you should specify a branch" sounded too judgmental to me, but I'm not a native speaker, so I simply removed the word "specific".

I'm not either.

We should start a society or something ;-)

Quoted 2 lines

Note that when I say "maybe it is just me", I usually am not asking to change anything.

Of course! In this instance, your suggestion made me think and prefer the non-repetitive version (because let's face it, taking out that word did not make it any more or less judgemental).

Ciao,
Dscho

#138 lore raw

PATCH v3 3/8 submodule: use a better fall-back for missing remote.<name>.branch

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

When remote.<name>.branch is not configured, git submodule update currently falls back to using the branch name master. A much better idea, however, is to use HEAD: on all Git servers running reasonably recent Git versions, the symref HEAD points to the main branch.

Note: t7419 demonstrates that there _might_ be use cases out there that _expect_ git submodule update --remote to update submodules to the remote master branch even if the remote HEAD points to another branch. Arguably, this patch makes the behavior more intuitive, but there is a slight possibility that this might cause regressions in obscure setups.

---
 Documentation/git-submodule.txt |  4 ++--
 builtin/submodule--helper.c     |  2 +-
 t/t7406-submodule-update.sh     | 16 ++++++++++++++++
 t/t7419-submodule-set-branch.sh |  7 +++++--
 4 files changed, 24 insertions(+), 5 deletions(-)
Documentation/git-submodule.txt +2 -2
index c9ed2bf3d5..b20f85e622 100644
@@ -284,7 +284,7 @@ OPTIONS
 	`.gitmodules` for `update --remote`.  A special value of `.` is used to
 	indicate that the name of the branch in the submodule should be the
 	same name as the current branch in the current repository.  If the
-	option is not specified, it defaults to 'master'.
+	option is not specified, it defaults to 'HEAD'.
 
 -f::
 --force::
@@ -322,7 +322,7 @@ OPTIONS
 	the superproject's recorded SHA-1 to update the submodule, use the
 	status of the submodule's remote-tracking branch.  The remote used
 	is branch's remote (`branch.<name>.remote`), defaulting to `origin`.
-	The remote branch used defaults to `master`, but the branch name may
+	The remote branch used defaults to `HEAD`, but the branch name may
 	be overridden by setting the `submodule.<name>.branch` option in
 	either `.gitmodules` or `.git/config` (with `.git/config` taking
 	precedence).
builtin/submodule--helper.c +1 -1
index 46c03d2a12..f55f7b7704 100644
@@ -1981,7 +1981,7 @@ static const char *remote_submodule_branch(const char *path)
 	free(key);
 
 	if (!branch)
-		return "master";
+		return "HEAD";
 
 	if (!strcmp(branch, ".")) {
 		const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
t/t7406-submodule-update.sh +16 -0
index 4fb447a143..aa19ff3a2e 100755
@@ -70,6 +70,22 @@ test_expect_success 'setup a submodule tree' '
 	)
 '
 
+test_expect_success 'update --remote falls back to using HEAD' '
+	test_create_repo main-branch-submodule &&
+	test_commit -C main-branch-submodule initial &&
+
+	test_create_repo main-branch &&
+	git -C main-branch submodule add ../main-branch-submodule &&
+	git -C main-branch commit -m add-submodule &&
+
+	git -C main-branch-submodule switch -c hello &&
+	test_commit -C main-branch-submodule world &&
+
+	git clone --recursive main-branch main-branch-clone &&
+	git -C main-branch-clone submodule update --remote main-branch-submodule &&
+	test_path_exists main-branch-clone/main-branch-submodule/world.t
+'
+
 test_expect_success 'submodule update detaching the HEAD ' '
 	(cd super/submodule &&
 	 git reset --hard HEAD~1
t/t7419-submodule-set-branch.sh +5 -2
index fd25f786a3..3b925c302f 100755
@@ -52,12 +52,13 @@ test_expect_success 'test submodule set-branch --branch' '
 '
 
 test_expect_success 'test submodule set-branch --default' '
+	test_commit -C submodule c &&
 	(cd super &&
 		git submodule set-branch --default submodule &&
 		! grep branch .gitmodules &&
 		git submodule update --remote &&
 		cat <<-\EOF >expect &&
-		a
+		c
 		EOF
 		git -C submodule show -s --pretty=%s >actual &&
 		test_cmp expect actual
@@ -65,6 +66,7 @@ test_expect_success 'test submodule set-branch --default' '
 '
 
 test_expect_success 'test submodule set-branch -b' '
+	test_commit -C submodule b &&
 	(cd super &&
 		git submodule set-branch -b topic submodule &&
 		grep "branch = topic" .gitmodules &&
@@ -78,12 +80,13 @@ test_expect_success 'test submodule set-branch -b' '
 '
 
 test_expect_success 'test submodule set-branch -d' '
+	test_commit -C submodule d &&
 	(cd super &&
 		git submodule set-branch -d submodule &&
 		! grep branch .gitmodules &&
 		git submodule update --remote &&
 		cat <<-\EOF >expect &&
-		a
+		d
 		EOF
 		git -C submodule show -s --pretty=%s >actual &&
 		test_cmp expect actual
Signature · 1 line
gitgitgadget
#139 lore raw

Re: [PATCH v3 3/8] submodule: use a better fall-back for missing remote.<name>.branch

Hi Dscho,

Quoted 8 lines · Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

When remote.<name>.branch is not configured, git submodule update currently falls back to using the branch name master. A much better idea, however, is to use HEAD: on all Git servers running reasonably recent Git versions, the symref HEAD points to the main branch.

To be pedantic, it is up to the maintainer/developers to make sure that HEAD on the canonic repository indeed points to the branch that is considered the 'main' branch of the project; the Git version does not really matter IMO... I've seen plenty of repos at work that have HEAD pointing to master but master is not used, or not anymore...

Quoted 8 lines

Note: t7419 demonstrates that there _might_ be use cases out there that _expect_ git submodule update --remote to update submodules to the remote master branch even if the remote HEAD points to another branch. Arguably, this patch makes the behavior more intuitive, but there is a slight possibility that this might cause regressions in obscure setups.

I think that's an excellent idea. However I'd be more explicit in the commit message title:
submodule: fall back to remote's HEAD for missing remote.<name>.branch

meta comment: I never know where is the best place to make suggestions about changing the commit message title, since I can't quote it in my replies!

Quoted 6 lines

---

Documentation/git-submodule.txt |  4 ++--
builtin/submodule--helper.c     |  2 +-
t/t7406-submodule-update.sh     | 16 ++++++++++++++++
t/t7419-submodule-set-branch.sh |  7 +++++--
4 files changed, 24 insertions(+), 5 deletions(-)

I think Documentation/gitmodules.txt (submodule.<name>.branch header)
should also be changed to reflect the behaviour change:

Documentation/gitmodules.txt +3 -3
index 67275fd187..539b4e1997 100644
@@ -49,9 +49,9 @@ submodule.<name>.update::
 
 submodule.<name>.branch::
 	A remote branch name for tracking updates in the upstream submodule.
-	If the option is not specified, it defaults to 'master'.  A special
-	value of `.` is used to indicate that the name of the branch in the
-	submodule should be the same name as the current branch in the
+	If the option is not specified, it defaults to the remote 'HEAD'.
+	A special value of `.` is used to indicate that the name of the branch
+	in the submodule should be the same name as the current branch in the
 	current repository.  See the `--remote` documentation in
 	linkgit:git-submodule[1] for details.
 

Documentation/git-submodule.txt OPTIONS · line 287

Quoted 10 lines
Documentation/git-submodule.txt +1 -1
index c9ed2bf3d5..b20f85e622 100644
@@ -284,7 +284,7 @@ OPTIONS
 	`.gitmodules` for `update --remote`.  A special value of `.` is used to
 	indicate that the name of the branch in the submodule should be the
 	same name as the current branch in the current repository.  If the
-	option is not specified, it defaults to 'master'.
+	option is not specified, it defaults to 'HEAD'.

Just to be extra clear (it's easy to get confused with submodules!) I'd say explicitly:

If the option is not specified, it defaults to the remote 'HEAD'.

Documentation/git-submodule.txt OPTIONS · line 325

Quoted 9 lines
Documentation/git-submodule.txt +1 -3
-f::
--force::
@@ -322,7 +322,7 @@ OPTIONS
 	the superproject's recorded SHA-1 to update the submodule, use the
 	status of the submodule's remote-tracking branch.  The remote used
 	is branch's remote (`branch.<name>.remote`), defaulting to `origin`.
-	The remote branch used defaults to `master`, but the branch name may
+	The remote branch used defaults to `HEAD`, but the branch name may

Same thing here:

The remote branch used defaults to the remote HEAD.

Documentation/git-submodule.txt OPTIONS · line 328

Quoted 3 lines
Documentation/git-submodule.txt +0 -0
 	be overridden by setting the `submodule.<name>.branch` option in
 	either `.gitmodules` or `.git/config` (with `.git/config` taking
 	precedence).

Also, you seem to have missed the master reference in the description of the 'set-branch' subcommand. Something like this would do, I think:

Documentation/git-submodule.txt +1 -1
index c9ed2bf3d5..8cf5831a72 100644
@@ -183,7 +183,7 @@ set-branch (-d|--default) [--] <path>::
 	Sets the default remote tracking branch for the submodule. The
 	`--branch` option allows the remote branch to be specified. The
 	`--default` option removes the submodule.<name>.branch configuration
-	key, which causes the tracking branch to default to 'master'.
+	key, which causes the tracking branch to default to the remote 'HEAD'.
 
 set-url [--] <path> <newurl>::
 	Sets the URL of the specified submodule to <newurl>. Then, it will

The rest of the patch looks good.

Cheers,
Philippe.

#140 lore raw

Re: [PATCH v3 3/8] submodule: use a better fall-back for missing remote.<name>.branch

Hi Philippe,

Quoted 9 lines · Philippe Blain
Quoted 8 lines · Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

When remote.<name>.branch is not configured, git submodule update currently falls back to using the branch name master. A much better idea, however, is to use HEAD: on all Git servers running reasonably recent Git versions, the symref HEAD points to the main branch.

Quoted 5 lines

To be pedantic, it is up to the maintainer/developers to make sure that HEAD on the canonic repository indeed points to the branch that is considered the 'main' branch of the project; the Git version does not really matter IMO... I've seen plenty of repos at work that have HEAD pointing to master but master is not used, or not anymore...

Oh, but in this case, my main concern was servers that are so old that HEAD is not a symref, in which case it can be a bit tricky to figure out the default branch.

In any case, I feel this is such a minor point that I don't really want to spend a lot of time on this paragraph.

Quoted 7 lines
Quoted 7 lines

Note: t7419 demonstrates that there _might_ be use cases out there that _expect_ git submodule update --remote to update submodules to the remote master branch even if the remote HEAD points to another branch. Arguably, this patch makes the behavior more intuitive, but there is a slight possibility that this might cause regressions in obscure setups.

Quoted 6 lines
Quoted 1 line

I think that's an excellent idea. However I'd be more explicit in the commit message title:

submodule: fall back to remote's HEAD for missing remote.<name>.branch

Great!

Quoted 3 lines

meta comment: I never know where is the best place to make suggestions about changing the commit message title, since I can't quote it in my replies!

True. You could copy it, but that's not the same.

Quoted 16 lines
Quoted 6 lines

---

Documentation/git-submodule.txt |  4 ++--
builtin/submodule--helper.c     |  2 +-
t/t7406-submodule-update.sh     | 16 ++++++++++++++++
t/t7419-submodule-set-branch.sh |  7 +++++--
4 files changed, 24 insertions(+), 5 deletions(-)

I think Documentation/gitmodules.txt (submodule.<name>.branch header)
should also be changed to reflect the behaviour change:

Documentation/gitmodules.txt +0 -0
index 67275fd187..539b4e1997 100644
@@ -49,9 +49,9 @@ submodule.<name>.update::
 

Documentation/gitmodules.txt submodule.<name>.update:: · line 56

Quoted 10 lines
Documentation/gitmodules.txt +3 -3
 submodule.<name>.branch::
 	A remote branch name for tracking updates in the upstream submodule.
-	If the option is not specified, it defaults to 'master'.  A special
-	value of `.` is used to indicate that the name of the branch in the
-	submodule should be the same name as the current branch in the
+	If the option is not specified, it defaults to the remote 'HEAD'.
+	A special value of `.` is used to indicate that the name of the branch
+	in the submodule should be the same name as the current branch in the
 	current repository.  See the `--remote` documentation in
 	linkgit:git-submodule[1] for details.

Excellent, I used that verbatim. Thank you!

Quoted 14 lines

Documentation/git-submodule.txt OPTIONS · line 287

Quoted 10 lines
Documentation/git-submodule.txt +1 -1
index c9ed2bf3d5..b20f85e622 100644
@@ -284,7 +284,7 @@ OPTIONS
 	`.gitmodules` for `update --remote`.  A special value of `.` is used to
 	indicate that the name of the branch in the submodule should be the
 	same name as the current branch in the current repository.  If the
-	option is not specified, it defaults to 'master'.
+	option is not specified, it defaults to 'HEAD'.

Just to be extra clear (it's easy to get confused with submodules!) I'd say explicitly:

Quoted 1 line

If the option is not specified, it defaults to the remote 'HEAD'.

Good idea. I incorporated that, too.

Quoted 11 lines

Documentation/git-submodule.txt OPTIONS · line 325

Quoted 8 lines
Documentation/git-submodule.txt +1 -3
-f::
--force::
@@ -322,7 +322,7 @@ OPTIONS
 	the superproject's recorded SHA-1 to update the submodule, use the
 	status of the submodule's remote-tracking branch.  The remote used
 	is branch's remote (`branch.<name>.remote`), defaulting to `origin`.
-	The remote branch used defaults to `master`, but the branch name may
+	The remote branch used defaults to `HEAD`, but the branch name may

Same thing here:

Quoted 1 line

The remote branch used defaults to the remote HEAD.

And that.

Quoted 12 lines

Documentation/git-submodule.txt OPTIONS · line 328

Quoted 3 lines
Documentation/git-submodule.txt +0 -0
 	be overridden by setting the `submodule.<name>.branch` option in
 	either `.gitmodules` or `.git/config` (with `.git/config` taking
 	precedence).

Also, you seem to have missed the master reference in the description of the 'set-branch' subcommand. Something like this would do, I think:

Documentation/git-submodule.txt +0 -0
index c9ed2bf3d5..8cf5831a72 100644

Documentation/git-submodule.txt set-branch (-d|--default) [--] <path>:: · line 189

Quoted 8 lines
Documentation/git-submodule.txt +1 -1
@@ -183,7 +183,7 @@ set-branch (-d|--default) [--] <path>::
 	Sets the default remote tracking branch for the submodule. The
 	`--branch` option allows the remote branch to be specified. The
 	`--default` option removes the submodule.<name>.branch configuration
-	key, which causes the tracking branch to default to 'master'.
+	key, which causes the tracking branch to default to the remote 'HEAD'.
 
 set-url [--] <path> <newurl>::
 	Sets the URL of the specified submodule to <newurl>. Then, it will

And that.

Quoted 1 line

The rest of the patch looks good.

Awesome. Thank you for helping me improve this patch series!

Ciao,
Dscho

#141 lore raw

PATCH v3 4/8 init: allow specifying the initial branch name for the new repository

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

There is a growing number of projects and companies desiring to change the main branch name of their repositories (see e.g.
https://twitter.com/mislav/status/1270388510684598272 for background on this).

To change that branch name for new repositories, currently the only way to do that automatically is by copying all of Git's template directory, then hard-coding the desired default branch name into the .git/HEAD file, and then configuring init.templateDir to point to those copied template files.

To make this process much less cumbersome, let's introduce a new option:
--initial-branch=<branch-name>.

---
 Documentation/git-init.txt |  7 +++++++
 builtin/clone.c            |  3 ++-
 builtin/init-db.c          | 34 +++++++++++++++++++++++++++-------
 cache.h                    |  2 +-
 t/t0001-init.sh            | 13 +++++++++++++
 5 files changed, 50 insertions(+), 9 deletions(-)
Documentation/git-init.txt +7 -0
index adc6adfd38..36dccc6e52 100644
@@ -11,6 +11,7 @@ SYNOPSIS
 [verse]
 'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
 	  [--separate-git-dir <git dir>] [--object-format=<format]
+	  [-b <branch-name> | --initial-branch=<branch-name>]
 	  [--shared[=<permissions>]] [directory]
 
 
@@ -67,6 +68,12 @@ repository.
 +
 If this is reinitialization, the repository will be moved to the specified path.
 
+-b <branch-name::
+--initial-branch=<branch-name>::
+
+Use the specified name for the initial branch in the newly created repository.
+If not specified, fall back to the default name: `master`.
+
 --shared[=(false|true|umask|group|all|world|everybody|0xxx)]::
 
 Specify that the Git repository is to be shared amongst several users.  This
builtin/clone.c +2 -1
index 2a8e3aaaed..b751bdf13e 100644
@@ -1111,7 +1111,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		}
 	}
 
-	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, INIT_DB_QUIET);
+	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL,
+		INIT_DB_QUIET);
 
 	if (real_git_dir)
 		git_dir = real_git_dir;
builtin/init-db.c +27 -7
index 0b7222e718..a898153901 100644
@@ -203,6 +203,7 @@ void initialize_repository_version(int hash_algo)
 
 static int create_default_files(const char *template_path,
 				const char *original_git_dir,
+				const char *initial_branch,
 				const struct repository_format *fmt)
 {
 	struct stat st1;
@@ -258,16 +259,29 @@ static int create_default_files(const char *template_path,
 		die("failed to set up refs db: %s", err.buf);
 
 	/*
-	 * Create the default symlink from ".git/HEAD" to the "master"
-	 * branch, if it does not exist yet.
+	 * Create the default symlink from ".git/HEAD" to the default
+	 * branch name, if it does not exist yet.
 	 */
 	path = git_path_buf(&buf, "HEAD");
 	reinit = (!access(path, R_OK)
 		  || readlink(path, junk, sizeof(junk)-1) != -1);
 	if (!reinit) {
-		if (create_symref("HEAD", "refs/heads/master", NULL) < 0)
+		char *ref;
+
+		if (!initial_branch)
+			initial_branch = "master";
+
+		ref = xstrfmt("refs/heads/%s", initial_branch);
+		if (check_refname_format(ref, 0) < 0)
+			die(_("invalid initial branch name: '%s'"),
+			    initial_branch);
+
+		if (create_symref("HEAD", ref, NULL) < 0)
 			exit(1);
-	}
+		free(ref);
+	} else if (initial_branch)
+		warning(_("re-init: ignoring --initial-branch=%s"),
+			initial_branch);
 
 	initialize_repository_version(fmt->hash_algo);
 
@@ -383,7 +397,8 @@ static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash
 }
 
 int init_db(const char *git_dir, const char *real_git_dir,
-	    const char *template_dir, int hash, unsigned int flags)
+	    const char *template_dir, int hash, const char *initial_branch,
+	    unsigned int flags)
 {
 	int reinit;
 	int exist_ok = flags & INIT_DB_EXIST_OK;
@@ -425,7 +440,8 @@ int init_db(const char *git_dir, const char *real_git_dir,
 
 	validate_hash_algorithm(&repo_fmt, hash);
 
-	reinit = create_default_files(template_dir, original_git_dir, &repo_fmt);
+	reinit = create_default_files(template_dir, original_git_dir,
+				      initial_branch, &repo_fmt);
 
 	create_object_directory();
 
@@ -528,6 +544,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	const char *template_dir = NULL;
 	unsigned int flags = 0;
 	const char *object_format = NULL;
+	const char *initial_branch = NULL;
 	int hash_algo = GIT_HASH_UNKNOWN;
 	const struct option init_db_options[] = {
 		OPT_STRING(0, "template", &template_dir, N_("template-directory"),
@@ -541,6 +558,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 		OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET),
 		OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
 			   N_("separate git dir from working tree")),
+		OPT_STRING('b', "initial-branch", &initial_branch, N_("name"),
+			   N_("override the name of the initial branch")),
 		OPT_STRING(0, "object-format", &object_format, N_("hash"),
 			   N_("specify the hash algorithm to use")),
 		OPT_END()
@@ -652,5 +671,6 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	UNLEAK(work_tree);
 
 	flags |= INIT_DB_EXIST_OK;
-	return init_db(git_dir, real_git_dir, template_dir, hash_algo, flags);
+	return init_db(git_dir, real_git_dir, template_dir, hash_algo,
+		       initial_branch, flags);
 }
cache.h +1 -1
index 0f0485ecfe..654426460c 100644
@@ -628,7 +628,7 @@ int path_inside_repo(const char *prefix, const char *path);
 
 int init_db(const char *git_dir, const char *real_git_dir,
 	    const char *template_dir, int hash_algo,
-	    unsigned int flags);
+	    const char *initial_branch, unsigned int flags);
 void initialize_repository_version(int hash_algo);
 
 void sanitize_stdfds(void);
t/t0001-init.sh +13 -0
index 1edd5aeb8f..61837ca25f 100755
@@ -464,4 +464,17 @@ test_expect_success MINGW 'redirect std handles' '
 	grep "Needed a single revision" output.txt
 '
 
+test_expect_success '--initial-branch' '
+	git init --initial-branch=hello initial-branch-option &&
+	git -C initial-branch-option symbolic-ref HEAD >actual &&
+	echo refs/heads/hello >expect &&
+	test_cmp expect actual &&
+
+	: re-initializing should not change the branch name &&
+	git init --initial-branch=ignore initial-branch-option 2>err &&
+	test_i18ngrep "ignoring --initial-branch" err &&
+	git -C initial-branch-option symbolic-ref HEAD >actual &&
+	grep hello actual
+'
+
 test_done
Signature · 1 line
gitgitgadget
#142 lore raw

Re: [PATCH v3 4/8] init: allow specifying the initial branch name for the new repository

"Johannes Schindelin via GitGitGadget" <[email protected]>

Quoted 3 lines · writes:

[verse]
'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
[--separate-git-dir <git dir>] [--object-format=<format]

Completely offtopic. We lack the closing ket> here.

Documentation/git-init.txt repository. · line 75

Quoted 13 lines
Documentation/git-init.txt +6 -0
+	  [-b <branch-name> | --initial-branch=<branch-name>]
 	  [--shared[=<permissions>]] [directory]
@@ -67,6 +68,12 @@ repository.
 +
 If this is reinitialization, the repository will be moved to the specified path.
 
+-b <branch-name::
+--initial-branch=<branch-name>::
+
+Use the specified name for the initial branch in the newly created repository.
+If not specified, fall back to the default name: `master`.

OK.

Quoted 27 lines
builtin/clone.c +2 -1
index 2a8e3aaaed..b751bdf13e 100644
@@ -1111,7 +1111,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		}
 	}
 
-	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, INIT_DB_QUIET);
+	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL,
+		INIT_DB_QUIET);
 
 	if (real_git_dir)
 		git_dir = real_git_dir;
builtin/init-db.c +1 -0
index 0b7222e718..a898153901 100644
@@ -203,6 +203,7 @@ void initialize_repository_version(int hash_algo)
 
 static int create_default_files(const char *template_path,
 				const char *original_git_dir,
+				const char *initial_branch,
 				const struct repository_format *fmt)
 {
 	struct stat st1;

builtin/init-db.c static int create_default_files(const char *template_path, · line 264

Quoted 8 lines
builtin/init-db.c +2 -2
@@ -258,16 +259,29 @@ static int create_default_files(const char *template_path,
 		die("failed to set up refs db: %s", err.buf);
 
 	/*
-	 * Create the default symlink from ".git/HEAD" to the "master"
-	 * branch, if it does not exist yet.
+	 * Create the default symlink from ".git/HEAD" to the default
+	 * branch name, if it does not exist yet.
 	 */

To the caller of this helper, it may be "the default", but as far as this helper is concerned, it is not "default" but the initial branch that was given by the caller. How about...

	/*
	 * Point the initial branch with HEAD symref, if HEAD does
	 * not exist yet.
	 */

... to modernize the reference to symlink and replace it with symref?

builtin/init-db.c static int create_default_files(const char *template_path, · line 277

Quoted 7 lines
builtin/init-db.c +7 -0
+		if (!initial_branch)
+			initial_branch = "master";
+
+		ref = xstrfmt("refs/heads/%s", initial_branch);
+		if (check_refname_format(ref, 0) < 0)
+			die(_("invalid initial branch name: '%s'"),
+			    initial_branch);

Good. We make sure to prefix with "refs/heads/" so the callers cannot abuse us to point HEAD outside the local branches.

builtin/init-db.c static int create_default_files(const char *template_path, · line 284

Quoted 7 lines
builtin/init-db.c +5 -1
+		if (create_symref("HEAD", ref, NULL) < 0)
 			exit(1);
-	}
+		free(ref);
+	} else if (initial_branch)
+		warning(_("re-init: ignoring --initial-branch=%s"),
+			initial_branch);

Somehow the error checking convention feels uneven in this API. It is a warning-worthy offense for the caller to give initial_branch when we are re-initializing, but it is not an error for the caller not to supply the initial branch name on the other side of if/else. Worse yet, this helper function even knows the command line option name that resulted in the parameter coming to it.

That unevenness ultimately comes from the fact that the caller does not know if we are dealing with a repository that already has HEAD before calling, but at least we should be able to tell the caller if we initialized or not with our return value and allow the caller to issue this warning---that way we can lose the warning from here and get rid of the uneven feeling. Oh, and ...

Quoted 11 lines
builtin/init-db.c +2 -1
@@ -383,7 +397,8 @@ static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash
 }
 
 int init_db(const char *git_dir, const char *real_git_dir,
-	    const char *template_dir, int hash, unsigned int flags)
+	    const char *template_dir, int hash, const char *initial_branch,
+	    unsigned int flags)
 {
 	int reinit;
 	int exist_ok = flags & INIT_DB_EXIST_OK;

builtin/init-db.c int init_db(const char *git_dir, const char *real_git_dir, · line 444

Quoted 6 lines
builtin/init-db.c +2 -1
@@ -425,7 +440,8 @@ int init_db(const char *git_dir, const char *real_git_dir,
 
 	validate_hash_algorithm(&repo_fmt, hash);
 
-	reinit = create_default_files(template_dir, original_git_dir, &repo_fmt);
+	reinit = create_default_files(template_dir, original_git_dir,
+				      initial_branch, &repo_fmt);

... we are telling the caller if we are in reinit situation, so we can afford to do exactly that.

reinit = create_default_files...
if (reinit && initial_branch)

		warning(_("re-init: ignored --initial-branch"));

That's much better ;-)

Other than that, looks good to me.

Thanks.

#143 lore raw

Re: [PATCH v3 4/8] init: allow specifying the initial branch name for the new repository

Hi Junio,

Quoted 8 lines · Junio C Hamano

"Johannes Schindelin via GitGitGadget" <[email protected]>

Quoted 3 lines · writes:

[verse]
'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
[--separate-git-dir <git dir>] [--object-format=<format]

Completely offtopic. We lack the closing ket> here.

Not so off-topic: the fix for this would cause conflicts. In the interest of avoiding merge conflicts, I incorporated a patch to fix that (git grep found two more instances, which I fixed "while at it").

Quoted 56 lines

Documentation/git-init.txt repository. · line 75

Quoted 13 lines
Documentation/git-init.txt +6 -0
+	  [-b <branch-name> | --initial-branch=<branch-name>]
 	  [--shared[=<permissions>]] [directory]
@@ -67,6 +68,12 @@ repository.
 +
 If this is reinitialization, the repository will be moved to the specified path.
 
+-b <branch-name::
+--initial-branch=<branch-name>::
+
+Use the specified name for the initial branch in the newly created repository.
+If not specified, fall back to the default name: `master`.

OK.

Quoted 27 lines
builtin/clone.c +2 -1
index 2a8e3aaaed..b751bdf13e 100644
@@ -1111,7 +1111,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		}
 	}
 
-	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, INIT_DB_QUIET);
+	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL,
+		INIT_DB_QUIET);
 
 	if (real_git_dir)
 		git_dir = real_git_dir;
builtin/init-db.c +1 -0
index 0b7222e718..a898153901 100644
@@ -203,6 +203,7 @@ void initialize_repository_version(int hash_algo)
 
 static int create_default_files(const char *template_path,
 				const char *original_git_dir,
+				const char *initial_branch,
 				const struct repository_format *fmt)
 {
 	struct stat st1;

builtin/init-db.c static int create_default_files(const char *template_path, · line 264

Quoted 8 lines
builtin/init-db.c +2 -2
@@ -258,16 +259,29 @@ static int create_default_files(const char *template_path,
 		die("failed to set up refs db: %s", err.buf);
 
 	/*
-	 * Create the default symlink from ".git/HEAD" to the "master"
-	 * branch, if it does not exist yet.
+	 * Create the default symlink from ".git/HEAD" to the default
+	 * branch name, if it does not exist yet.
 	 */

To the caller of this helper, it may be "the default", but as far as this helper is concerned, it is not "default" but the initial branch that was given by the caller. How about...

Quoted 7 lines
	/*
	 * Point the initial branch with HEAD symref, if HEAD does
	 * not exist yet.
	 */

... to modernize the reference to symlink and replace it with symref?

Good point. I massaged your proposed comment and replaced the old one with it.

Quoted 10 lines

builtin/init-db.c static int create_default_files(const char *template_path, · line 277

Quoted 7 lines
builtin/init-db.c +7 -0
+		if (!initial_branch)
+			initial_branch = "master";
+
+		ref = xstrfmt("refs/heads/%s", initial_branch);
+		if (check_refname_format(ref, 0) < 0)
+			die(_("invalid initial branch name: '%s'"),
+			    initial_branch);

Good. We make sure to prefix with "refs/heads/" so the callers cannot abuse us to point HEAD outside the local branches.

Yes, Peff offered that concern, and I agree.

Quoted 43 lines

builtin/init-db.c static int create_default_files(const char *template_path, · line 284

Quoted 7 lines
builtin/init-db.c +5 -1
+		if (create_symref("HEAD", ref, NULL) < 0)
 			exit(1);
-	}
+		free(ref);
+	} else if (initial_branch)
+		warning(_("re-init: ignoring --initial-branch=%s"),
+			initial_branch);

Somehow the error checking convention feels uneven in this API. It is a warning-worthy offense for the caller to give initial_branch when we are re-initializing, but it is not an error for the caller not to supply the initial branch name on the other side of if/else. Worse yet, this helper function even knows the command line option name that resulted in the parameter coming to it.

That unevenness ultimately comes from the fact that the caller does not know if we are dealing with a repository that already has HEAD before calling, but at least we should be able to tell the caller if we initialized or not with our return value and allow the caller to issue this warning---that way we can lose the warning from here and get rid of the uneven feeling. Oh, and ...

Quoted 11 lines
builtin/init-db.c +2 -1
@@ -383,7 +397,8 @@ static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash
 }
 
 int init_db(const char *git_dir, const char *real_git_dir,
-	    const char *template_dir, int hash, unsigned int flags)
+	    const char *template_dir, int hash, const char *initial_branch,
+	    unsigned int flags)
 {
 	int reinit;
 	int exist_ok = flags & INIT_DB_EXIST_OK;

builtin/init-db.c int init_db(const char *git_dir, const char *real_git_dir, · line 444

Quoted 6 lines
builtin/init-db.c +2 -1
@@ -425,7 +440,8 @@ int init_db(const char *git_dir, const char *real_git_dir,
 
 	validate_hash_algorithm(&repo_fmt, hash);
 
-	reinit = create_default_files(template_dir, original_git_dir, &repo_fmt);
+	reinit = create_default_files(template_dir, original_git_dir,
+				      initial_branch, &repo_fmt);

... we are telling the caller if we are in reinit situation, so we can afford to do exactly that.

Quoted 3 lines

reinit = create_default_files...
if (reinit && initial_branch)

		warning(_("re-init: ignored --initial-branch"));

I changed it accordingly.

Thanks,
Dscho

Quoted 8 lines

That's much better ;-)

Other than that, looks good to me.

Thanks.

#144 lore raw

PATCH v3 5/8 init: allow setting the default for the initial branch name via the config

In reply to Johannes Schindelin via GitGitGadget

From: Don Goodman-Wilson <[email protected]>

We just introduced the command-line option --initial-branch=<branch-name> to allow initializing a new repository with a different initial branch than the hard-coded one.

To allow users to override the initial branch name more permanently (i.e. without having to specify the name manually for each and every git init invocation), let's introduce the init.defaultBranch config setting.

---
 Documentation/config/init.txt |  4 ++++
 builtin/init-db.c             |  2 +-
 refs.c                        | 30 ++++++++++++++++++++++++++++++
 refs.h                        |  9 +++++++++
 t/t0001-init.sh               | 13 +++++++++++++
 5 files changed, 57 insertions(+), 1 deletion(-)
Documentation/config/init.txt +4 -0
index 46fa8c6a08..6ae4a38416 100644
@@ -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.
builtin/init-db.c +1 -1
index a898153901..b8634b5f35 100644
@@ -269,7 +269,7 @@ static int create_default_files(const char *template_path,
 		char *ref;
 
 		if (!initial_branch)
-			initial_branch = "master";
+			initial_branch = git_default_branch_name();
 
 		ref = xstrfmt("refs/heads/%s", initial_branch);
 		if (check_refname_format(ref, 0) < 0)
refs.c +30 -0
index 224ff66c7b..b98dea5217 100644
@@ -560,6 +560,36 @@ void expand_ref_prefix(struct argv_array *prefixes, const char *prefix)
 		argv_array_pushf(prefixes, *p, len, prefix);
 }
 
+char *repo_default_branch_name(struct repository *r)
+{
+	const char *config_key = "init.defaultbranch";
+	const char *config_display_key = "init.defaultBranch";
+	char *ret = NULL, *full_ref;
+
+	if (repo_config_get_string(r, config_key, &ret) < 0)
+		die(_("could not retrieve `%s`"), config_display_key);
+
+	if (!ret)
+		ret = xstrdup("master");
+
+	full_ref = xstrfmt("refs/heads/%s", ret);
+	if (check_refname_format(full_ref, 0))
+		die(_("invalid branch name: %s = %s"), config_display_key, ret);
+	free(full_ref);
+
+	return ret;
+}
+
+const char *git_default_branch_name(void)
+{
+	static char *ret;
+
+	if (!ret)
+		ret = repo_default_branch_name(the_repository);
+
+	return ret;
+}
+
 /*
  * *string and *len will only be substituted, and *string returned (for
  * later free()ing) if the string passed in is a magic short-hand form
refs.h +9 -0
index e010f8aec2..f212f8945e 100644
@@ -154,6 +154,15 @@ int repo_dwim_log(struct repository *r, const char *str, int len, struct object_
 int dwim_ref(const char *str, int len, struct object_id *oid, char **ref);
 int dwim_log(const char *str, int len, struct object_id *oid, char **ref);
 
+/*
+ * Retrieves the default branch name for newly-initialized repositories.
+ *
+ * The return value of `repo_default_branch_name()` is an allocated string. The
+ * return value of `git_default_branch_name()` is a singleton.
+ */
+const char *git_default_branch_name(void);
+char *repo_default_branch_name(struct repository *r);
+
 /*
  * A ref_transaction represents a collection of reference updates that
  * should succeed or fail together.
t/t0001-init.sh +13 -0
index 61837ca25f..047197d08f 100755
@@ -477,4 +477,17 @@ test_expect_success '--initial-branch' '
 	grep hello actual
 '
 
+test_expect_success 'overridden default initial branch name (config)' '
+	test_config_global init.defaultBranch nmb &&
+	git init initial-branch-config &&
+	git -C initial-branch-config symbolic-ref HEAD >actual &&
+	grep nmb actual
+'
+
+test_expect_success 'invalid default branch name' '
+	test_config_global init.defaultBranch "with space" &&
+	test_must_fail git init initial-branch-invalid 2>err &&
+	test_i18ngrep "invalid branch name" err
+'
+
 test_done
Signature · 1 line
gitgitgadget
#145 lore raw

Re: [PATCH v3 5/8] init: allow setting the default for the initial branch name via the config

"Don Goodman-Wilson via GitGitGadget" <[email protected]>

builtin/init-db.c static int create_default_files(const char *template_path, · line 275

Quoted 13 lines · writes:
builtin/init-db.c +1 -1
index a898153901..b8634b5f35 100644
@@ -269,7 +269,7 @@ static int create_default_files(const char *template_path,
 		char *ref;
 
 		if (!initial_branch)
-			initial_branch = "master";
+			initial_branch = git_default_branch_name();
 
 		ref = xstrfmt("refs/heads/%s", initial_branch);
 		if (check_refname_format(ref, 0) < 0)

Continuing with the division of labor between this helper and its caller, I had this funny dislike of falling back here and not in the caller. But with the same idea of using "reinit", we could get rid of this "if the caller didn't give us initial_branch, fall back to..." logic from the function. The caller may do

	reinit = create_default_files(...
			initial_branch ? initial_branch : "master",
			...);
	if (reinit || initial_branch)
		warning(_(...));

in the previous step and then we can teach the caller to use the configured value instead of the hardcoded "master".

That's much better ;-)

Other than that, looks good to me.

Thanks.

#146 lore raw

Re: [PATCH v3 5/8] init: allow setting the default for the initial branch name via the config

Hi Junio,

Quoted 23 lines · Junio C Hamano

"Don Goodman-Wilson via GitGitGadget" <[email protected]>

builtin/init-db.c static int create_default_files(const char *template_path, · line 275

Quoted 13 lines · writes:
builtin/init-db.c +1 -1
index a898153901..b8634b5f35 100644
@@ -269,7 +269,7 @@ static int create_default_files(const char *template_path,
 		char *ref;
 
 		if (!initial_branch)
-			initial_branch = "master";
+			initial_branch = git_default_branch_name();
 
 		ref = xstrfmt("refs/heads/%s", initial_branch);
 		if (check_refname_format(ref, 0) < 0)

Continuing with the division of labor between this helper and its caller, I had this funny dislike of falling back here and not in the caller. But with the same idea of using "reinit", we could get rid of this "if the caller didn't give us initial_branch, fall back to..." logic from the function. The caller may do

Quoted 8 lines
	reinit = create_default_files(...
			initial_branch ? initial_branch : "master",
			...);
	if (reinit || initial_branch)
		warning(_(...));

in the previous step and then we can teach the caller to use the configured value instead of the hardcoded "master".

While that is really tempting, there is another called of init_db() (which calls create_default_files()): builtin/clone.c. And I do not wish to duplicate the logic there.

So I left this as-is.

Ciao,
Dscho

Quoted 7 lines

That's much better ;-)

Other than that, looks good to me.

Thanks.

#147 lore raw

Re: [PATCH v3 5/8] init: allow setting the default for the initial branch name via the config

Quoted 6 lines · Johannes Schindelin
Quoted 6 lines
	reinit = create_default_files(...
			initial_branch ? initial_branch : "master",
			...);
	if (reinit || initial_branch)
		warning(_(...));
Quoted 8 lines
Quoted 2 lines

in the previous step and then we can teach the caller to use the configured value instead of the hardcoded "master".

While that is really tempting, there is another called of init_db() (which calls create_default_files()): builtin/clone.c. And I do not wish to duplicate the logic there.

So I left this as-is.

I am still on the fence after seeing v4, but let's leave it as is. The reason why I wanted to leave the "default to" logic out of the helper was to make sure it implements little or no policy, which would leave the door open to let other callers of the helper to use their own and different default, but we can revisit when we acquire the third caller. I do not see an immediate need to make the clone's fallback default configurable separately from what init uses for the default initial branch name, and with modern servers it is doubtful that the fallback default by clone is ever used anyway.

Thanks.

#148 lore raw

PATCH v3 6/8 clone: use configured default branch name when appropriate

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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

As part of the implicit initialization of the local repository, Git just learned to respect init.defaultBranch to choose a different initial branch name. We now really want that branch name to be used as a fall-back.

---
 Documentation/config/init.txt |  4 ++--
 builtin/clone.c               | 10 +++++++---
 t/t5606-clone-options.sh      | 15 +++++++++++++++
 3 files changed, 24 insertions(+), 5 deletions(-)
Documentation/config/init.txt +2 -2
index 6ae4a38416..dc77f8c844 100644
@@ -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.
builtin/clone.c +7 -3
index b751bdf13e..9a3f91b268 100644
@@ -1267,9 +1267,13 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		remote_head_points_at = NULL;
 		remote_head = NULL;
 		option_no_checkout = 1;
-		if (!option_bare)
-			install_branch_config(0, "master", option_origin,
-					      "refs/heads/master");
+		if (!option_bare) {
+			const char *branch = git_default_branch_name();
+			char *ref = xstrfmt("refs/heads/%s", branch);
+
+			install_branch_config(0, branch, option_origin, ref);
+			free(ref);
+		}
 	}
 
 	write_refspec_config(src_ref_prefix, our_head_points_at,
t/t5606-clone-options.sh +15 -0
index 9e24ec88e6..286bfd93ac 100755
@@ -35,4 +35,19 @@ test_expect_success 'redirected clone -v does show progress' '
 
 '
 
+test_expect_success 'chooses correct default initial branch name' '
+	git init --bare empty &&
+	git -c init.defaultBranch=up clone empty whats-up &&
+	test refs/heads/up = $(git -C whats-up symbolic-ref HEAD) &&
+	test refs/heads/up = $(git -C whats-up config branch.up.merge)
+'
+
+test_expect_success 'guesses initial branch name correctly' '
+	git init --initial-branch=guess initial-branch &&
+	test_commit -C initial-branch no-spoilers &&
+	git -C initial-branch branch abc guess &&
+	git clone initial-branch is-it &&
+	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD)
+'
+
 test_done
Signature · 1 line
gitgitgadget
#149 lore raw

PATCH v3 7/8 remote: use the configured default branch name when appropriate

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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

At the same time, when talking to an older Git server that does not report a symref for HEAD (but instead reports a commit hash), let's try to guess the configured default branch name first. If it does not match the reported commit hash, let's fall back to master as before.

---
 remote.c                 | 14 +++++++++++---
 t/t5606-clone-options.sh | 11 ++++++++++-
 2 files changed, 21 insertions(+), 4 deletions(-)
remote.c +11 -3
index 534c6426f1..965129adc3 100644
@@ -276,7 +276,7 @@ static void read_branches_file(struct remote *remote)
 
 	/*
 	 * The branches file would have URL and optionally
-	 * #branch specified.  The "master" (or specified) branch is
+	 * #branch specified.  The main (or specified) branch is
 	 * fetched and stored in the local branch matching the
 	 * remote name.
 	 */
@@ -284,7 +284,7 @@ static void read_branches_file(struct remote *remote)
 	if (frag)
 		*(frag++) = '\0';
 	else
-		frag = "master";
+		frag = (char *)git_default_branch_name();
 
 	add_url_alias(remote, strbuf_detach(&buf, NULL));
 	strbuf_addf(&buf, "refs/heads/%s:refs/heads/%s",
@@ -2097,8 +2097,16 @@ struct ref *guess_remote_head(const struct ref *head,
 	if (head->symref)
 		return copy_ref(find_ref_by_name(refs, head->symref));
 
-	/* If refs/heads/master could be right, it is. */
+	/* If a remote branch exists with the default branch name, let's use it. */
 	if (!all) {
+		char *ref = xstrfmt("refs/heads/%s", git_default_branch_name());
+
+		r = find_ref_by_name(refs, ref);
+		free(ref);
+		if (r && oideq(&r->old_oid, &head->old_oid))
+			return copy_ref(r);
+
+		/* Fall back to the hard-coded historical default */
 		r = find_ref_by_name(refs, "refs/heads/master");
 		if (r && oideq(&r->old_oid, &head->old_oid))
 			return copy_ref(r);
t/t5606-clone-options.sh +10 -1
index 286bfd93ac..e69427f881 100755
@@ -47,7 +47,16 @@ test_expect_success 'guesses initial branch name correctly' '
 	test_commit -C initial-branch no-spoilers &&
 	git -C initial-branch branch abc guess &&
 	git clone initial-branch is-it &&
-	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD)
+	test refs/heads/guess = $(git -C is-it symbolic-ref HEAD) &&
+
+	git -c init.defaultBranch=none init --bare no-head &&
+	git -C initial-branch push ../no-head guess abc &&
+	git clone no-head is-it2 &&
+	test_must_fail git -C is-it2 symbolic-ref refs/remotes/origin/HEAD &&
+	git -C no-head update-ref --no-deref HEAD refs/heads/guess &&
+	git -c init.defaultBranch=guess clone no-head is-it3 &&
+	test refs/remotes/origin/guess = \
+		$(git -C is-it3 symbolic-ref refs/remotes/origin/HEAD)
 '
 
 test_done
Signature · 1 line
gitgitgadget
#150 lore raw

Re: [PATCH v3 7/8] remote: use the configured default branch name when appropriate

"Johannes Schindelin via GitGitGadget" <[email protected]>

remote.c static void read_branches_file(struct remote *remote) · line 282

Quoted 13 lines · writes:
remote.c +1 -1
index 534c6426f1..965129adc3 100644
@@ -276,7 +276,7 @@ static void read_branches_file(struct remote *remote)
 
 	/*
 	 * The branches file would have URL and optionally
-	 * #branch specified.  The "master" (or specified) branch is
+	 * #branch specified.  The main (or specified) branch is
 	 * fetched and stored in the local branch matching the
 	 * remote name.
 	 */

Isn't this a bit premature here?

#151 lore raw

Re: [PATCH v3 7/8] remote: use the configured default branch name when appropriate

Hi Junio,

Quoted 9 lines · Junio C Hamano

"Johannes Schindelin via GitGitGadget" <[email protected]>

Quoted 6 lines · writes:
remote.c +0 -0
index 534c6426f1..965129adc3 100644
@@ -276,7 +276,7 @@ static void read_branches_file(struct remote *remote)
 
Quoted 9 lines

remote.c static void read_branches_file(struct remote *remote) · line 282

Quoted 7 lines
remote.c +1 -1
 	/*
 	 * The branches file would have URL and optionally
-	 * #branch specified.  The "master" (or specified) branch is
+	 * #branch specified.  The main (or specified) branch is
 	 * fetched and stored in the local branch matching the
 	 * remote name.
 	 */

Isn't this a bit premature here?

Actually, it is just wrong. It should talk about the default branch instead.

Ciao,
Dscho

#152 lore raw

PATCH v3 8/8 testsvn: respect `init.defaultBranch`

In reply to Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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

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

---
 remote-testsvn.c      | 10 +++++++---
 t/t9020-remote-svn.sh |  6 ++++++
 2 files changed, 13 insertions(+), 3 deletions(-)
remote-testsvn.c +7 -3
index 3af708c5b6..cde39b94fb 100644
@@ -13,7 +13,7 @@
 static const char *url;
 static int dump_from_file;
 static const char *private_ref;
-static const char *remote_ref = "refs/heads/master";
+static char *remote_ref;
 static const char *marksfilename, *notes_ref;
 struct rev_note { unsigned int rev_nr; };
 
@@ -286,7 +286,7 @@ int cmd_main(int argc, const char **argv)
 			private_ref_sb = STRBUF_INIT, marksfilename_sb = STRBUF_INIT,
 			notes_ref_sb = STRBUF_INIT;
 	static struct remote *remote;
-	const char *url_in;
+	const char *url_in, *remote_ref_short;
 
 	setup_git_directory();
 	if (argc < 2 || argc > 3) {
@@ -294,6 +294,9 @@ int cmd_main(int argc, const char **argv)
 		return 1;
 	}
 
+	remote_ref_short = git_default_branch_name();
+	remote_ref = xstrfmt("refs/heads/%s", remote_ref_short);
+
 	remote = remote_get(argv[1]);
 	url_in = (argc == 3) ? argv[2] : remote->url[0];
 
@@ -306,7 +309,8 @@ int cmd_main(int argc, const char **argv)
 		url = url_sb.buf;
 	}
 
-	strbuf_addf(&private_ref_sb, "refs/svn/%s/master", remote->name);
+	strbuf_addf(&private_ref_sb, "refs/svn/%s/%s",
+		    remote->name, remote_ref_short);
 	private_ref = private_ref_sb.buf;
 
 	strbuf_addf(&notes_ref_sb, "refs/notes/%s/revs", remote->name);
t/t9020-remote-svn.sh +6 -0
index 9fcfa969a9..754c4a3284 100755
@@ -84,6 +84,12 @@ test_expect_success REMOTE_SVN 'incremental imports must lead to the same head'
 	test_cmp master.good .git/refs/remotes/svnsim/master
 '
 
+test_expect_success REMOTE_SVN 'respects configured default initial branch' '
+	git -c init.defaultBranch=trunk remote add -f trunk \
+		"testsvn::file://$TEST_DIRECTORY/t9154/svn.dump" &&
+	git rev-parse --verify refs/remotes/trunk/trunk
+'
+
 test_debug 'git branch -a'
 
 test_done
Signature · 1 line
gitgitgadget
#153 lore raw

v4 cover Allow overriding the default name of the default branch

In reply to Johannes Schindelin via GitGitGadget

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

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

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

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

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

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

This patch series allows overriding the branch name being used for new repositories' main branch. This can be configured via init.defaultBranch.

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

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

Changes since v3:

* We now avoid the phrasing "specify a specific" in the messages.

* The git submodule patch has a better commit title now, and it also adjusts the documentation more completely now (thanks, Philippe!).

* A code comment in builtin/init-db.c was updated to no longer talk about a symlink when it comes to HEAD.

* Made it the responsibility of the caller to warn about reinit && initial_branch.

Changes since v2:

* Dropped the fast-export patches, as they have been superseded by Peff's jk/fast-export-anonym
[https://github.com/gitgitgadget/git/commits/jk/fast-export-anonym].

* Adjusted the fmt-merge-msg patch so as to not special-case master anymore (instead of special-casing a specific "main" branch).

* Modified the git submodule patch so that it uses origin/HEAD instead of trying to look for a remote branch with the name indicated by init.defaultBranch.

Changes since v1:

* The modifications to respect GIT_TEST_DEFAULT_BRANCH_NAME have been backed out from this patch series, as they are only relevant once we start converting the test suite to accommodate for a new default main branch name.

* An error message that started with an upper-case letter was downcased.

* git_default_branch_name()'s logic was simplified by replacing an if ... else ... by a ternary assignment.

* The git_default_branch_name() function was renamed to git_main_branch_name() and a corresponding repo_main_branch_name() was introduced.

* The "init" commit message's first paragraph now elaborates a little bit on the reasoning why projects want to move away from the current default branch name.

* The "init" commit was split into two.

* There are now two config settings: init.defaultBranch (defining the branch name to use when initializing new repositories) and core.mainBranch (which is now configured by init_db(), declaring what the name of the main branch is in this repository).

* The commits were re-ordered to introduce the concept of core.mainBranch first because technically, this is something that we could do even without changing git init at all.

* git fast-export --anonymize now always uses the ref name ref0 for the main branch, no matter whether it was overridden or whether the fall-back is in effect.

* The code comment regarding anonymizing the main branch to ref0 in git fast-export --anonymize was enhanced.

* A new patch was added to rename core.mainBranch if the main branch is renamed via git branch -m.

* Added a patch that introduces support for git init --main-branch=<branch-name>.

* Where possible, I added tests (although I did not try to extend test coverage to all changes: the send-pack.c/transport-helper.c patch only adds a test for the send-pack.c adjustment, for example).

Don Goodman-Wilson (1):
init: allow setting the default for the initial branch name via the
config

Johannes Schindelin (8):
fmt-merge-msg: stop treating master specially send-pack/transport-helper: avoid mentioning a particular branch
submodule: fall back to remote's HEAD for missing remote.<name>.branch
docs: add missing diamond brackets
init: allow specifying the initial branch name for the new repository
clone: use configured default branch name when appropriate
remote: use the configured default branch name when appropriate
testsvn: respect init.defaultBranch

 Documentation/config/init.txt                 |  4 ++
 Documentation/git-branch.txt                  |  2 +-
 Documentation/git-clone.txt                   |  2 +-
 Documentation/git-init.txt                    |  9 ++-
 Documentation/git-submodule.txt               | 12 ++--
 Documentation/gitmodules.txt                  |  6 +-
 builtin/clone.c                               | 13 ++--
 builtin/init-db.c                             | 33 +++++++--
 builtin/submodule--helper.c                   |  2 +-
 cache.h                                       |  2 +-
 fmt-merge-msg.c                               |  5 +-
 refs.c                                        | 30 ++++++++
 refs.h                                        |  9 +++
 remote-testsvn.c                              | 10 ++-
 remote.c                                      | 14 +++-
 send-pack.c                                   |  2 +-
 t/t0001-init.sh                               | 26 +++++++
 t/t1507-rev-parse-upstream.sh                 |  2 +-
 t/t4013-diff-various.sh                       |  4 +-
 t/t4013/diff.log_--decorate=full_--all        |  2 +-
 t/t4013/diff.log_--decorate_--all             |  2 +-
 ...--patch-with-stat_--summary_master_--_dir_ |  2 +-
 t/t4013/diff.log_--patch-with-stat_master     |  2 +-
 .../diff.log_--patch-with-stat_master_--_dir_ |  2 +-
 ...ot_--cc_--patch-with-stat_--summary_master |  2 +-
 ..._--root_--patch-with-stat_--summary_master |  2 +-
 .../diff.log_--root_--patch-with-stat_master  |  2 +-
 ...root_-c_--patch-with-stat_--summary_master |  2 +-
 t/t4013/diff.log_--root_-p_master             |  2 +-
 t/t4013/diff.log_--root_master                |  2 +-
 t/t4013/diff.log_-m_-p_--first-parent_master  |  2 +-
 t/t4013/diff.log_-m_-p_master                 |  4 +-
 t/t4013/diff.log_-p_--first-parent_master     |  2 +-
 t/t4013/diff.log_-p_master                    |  2 +-
 t/t4013/diff.log_master                       |  2 +-
 t/t4013/diff.show_--first-parent_master       |  2 +-
 t/t4013/diff.show_-c_master                   |  2 +-
 t/t4013/diff.show_-m_master                   |  4 +-
 t/t4013/diff.show_master                      |  2 +-
 ...ot_--cc_--patch-with-stat_--summary_master |  2 +-
 ...root_-c_--patch-with-stat_--summary_master |  2 +-
 t/t4202-log.sh                                | 72 +++++++++----------
 t/t5528-push-default.sh                       |  6 ++
 t/t5606-clone-options.sh                      | 24 +++++++
 t/t6200-fmt-merge-msg.sh                      | 36 +++++-----
 t/t7406-submodule-update.sh                   | 16 +++++
 t/t7419-submodule-set-branch.sh               |  7 +-
 t/t7600-merge.sh                              | 14 ++--
 t/t7608-merge-messages.sh                     | 10 +--
 t/t9020-remote-svn.sh                         |  6 ++
 transport-helper.c                            |  2 +-
 51 files changed, 297 insertions(+), 131 deletions(-)

base-commit: c9c318d6bf26bcecdca5b6f31683b9d5887a83ee
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-656%2Fdscho%2Fdefault-branch-name-option-v4
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-656/dscho/default-branch-name-option-v4
Pull-Request: https://github.com/gitgitgadget/git/pull/656

Range-diff vs v3:

  1:  fffdb9944f =  1:  fffdb9944f fmt-merge-msg: stop treating `master` specially
  2:  a29943d7bb !  2:  1216de51ab send-pack/transport-helper: avoid mentioning a particular branch
     @@ send-pack.c: int send_pack(struct send_pack_args *args,
       	if (!remote_refs) {
       		fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
      -			"Perhaps you should specify a branch such as 'master'.\n");
     -+			"Perhaps you should specify a specific branch.\n");
     ++			"Perhaps you should specify a branch.\n");
       		return 0;
       	}
       	if (args->atomic && !atomic_supported)
     @@ t/t5528-push-default.sh: test_expect_success 'push from/to new branch with upstr
      +test_expect_success '"matching" fails if none match' '
      +	git init --bare empty &&
      +	test_must_fail git push empty : 2>actual &&
     -+	test_i18ngrep "Perhaps you should specify a specific branch" actual
     ++	test_i18ngrep "Perhaps you should specify a branch" actual
      +'
      +
       test_expect_success 'push ambiguously named branch with upstream, matching and simple' '
     @@ transport-helper.c: static int push_refs(struct transport *transport,
       		fprintf(stderr,
       			_("No refs in common and none specified; doing nothing.\n"
      -			  "Perhaps you should specify a branch such as 'master'.\n"));
     -+			  "Perhaps you should specify a specific branch.\n"));
     ++			  "Perhaps you should specify a branch.\n"));
       		return 0;
       	}

3: 6bda69541b ! 3: 54563642db submodule: use a better fall-back for missing remote.<name>.branch
@@ Metadata
Author: Johannes Schindelin <[email protected]>

## Commit message ##
- submodule: use a better fall-back for missing remote.<name>.branch
+ submodule: fall back to remote's HEAD for missing remote.<name>.branch

When remote.<name>.branch is not configured, git submodule update currently falls back to using the branch name master. A much better
- idea, however, is to use HEAD: on all Git servers running reasonably
- recent Git versions, the symref HEAD points to the main branch.
+ idea, however, is to use the remote HEAD: on all Git servers running
+ reasonably recent Git versions, the symref HEAD points to the main
+ branch.

Note: t7419 demonstrates that there _might_ be use cases out there that _expect_ git submodule update --remote to update submodules to the
@@ Commit message
there is a slight possibility that this might cause regressions in obscure setups.

+ Even so, it should be okay to fix this behavior without anything like a
+ longer transition period:
+
+ - The git submodule update --remote command is not really common.
+
+ - Current Git's behavior when running this command is outright
+ confusing, unless the remote repository's current branch _is_ master
+ (in which case the proposed behavior matches the old behavior).
+
+ - If a user encounters a regression due to the changed behavior, the fix
+ is actually trivial: setting submodule.<name>.branch to master
+ will reinstate the old behavior.
+
+ Helped-by: Philippe Blain <[email protected]>

## Documentation/git-submodule.txt ##
+@@ Documentation/git-submodule.txt: set-branch (-d|--default) [--] <path>::
+ Sets the default remote tracking branch for the submodule. The
+ --branch option allows the remote branch to be specified. The
+ --default option removes the submodule.<name>.branch configuration
+- key, which causes the tracking branch to default to 'master'.
++ key, which causes the tracking branch to default to the remote 'HEAD'.
+
+ set-url [--] <path> <newurl>::
+ Sets the URL of the specified submodule to <newurl>. Then, it will
@@ Documentation/git-submodule.txt: OPTIONS
.gitmodules for update --remote. A special value of . is used to indicate that the name of the branch in the submodule should be the same name as the current branch in the current repository. If the
- option is not specified, it defaults to 'master'.
-+ option is not specified, it defaults to 'HEAD'.
++ option is not specified, it defaults to the remote 'HEAD'.

-f::
--force::
@@ Documentation/git-submodule.txt: OPTIONS
status of the submodule's remote-tracking branch. The remote used is branch's remote (branch.<name>.remote), defaulting to origin.
- The remote branch used defaults to master, but the branch name may
-+ The remote branch used defaults to HEAD, but the branch name may
- be overridden by setting the submodule.<name>.branch option in
- either .gitmodules or .git/config (with .git/config taking
- precedence).
+- be overridden by setting the submodule.<name>.branch option in
+- either .gitmodules or .git/config (with .git/config taking
+- precedence).
++ The remote branch used defaults to the remote HEAD, but the branch
++ name may be overridden by setting the submodule.<name>.branch
++ option in either .gitmodules or .git/config (with .git/config
++ taking precedence).
+ +
+ This works for any of the supported update procedures (--checkout,
+ --rebase, etc.). The only change is the source of the target SHA-1. +
+ ## Documentation/gitmodules.txt ##
+@@ Documentation/gitmodules.txt: submodule.<name>.update::
+
+ submodule.<name>.branch::
+ A remote branch name for tracking updates in the upstream submodule.
+- If the option is not specified, it defaults to 'master'. A special
+- value of . is used to indicate that the name of the branch in the
+- submodule should be the same name as the current branch in the
++ If the option is not specified, it defaults to the remote 'HEAD'.
++ A special value of . is used to indicate that the name of the branch
++ in the submodule should be the same name as the current branch in the
+ current repository. See the --remote documentation in
+ linkgit:git-submodule[1] for details.
+

## builtin/submodule--helper.c ##
@@ builtin/submodule--helper.c: static const char *remote_submodule_branch(const char *path)

  -:  ---------- >  4:  1d723d35ed docs: add missing diamond brackets
  4:  e8a6587c1a !  5:  9edd4fd3b2 init: allow specifying the initial branch name for the new repository
     @@ Documentation/git-init.txt
      @@ Documentation/git-init.txt: SYNOPSIS
       [verse]
       'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
     - 	  [--separate-git-dir <git dir>] [--object-format=<format]
     + 	  [--separate-git-dir <git dir>] [--object-format=<format>]
      +	  [-b <branch-name> | --initial-branch=<branch-name>]
       	  [--shared[=<permissions>]] [directory]
       
     @@ builtin/init-db.c: static int create_default_files(const char *template_path,
       	/*
      -	 * Create the default symlink from ".git/HEAD" to the "master"
      -	 * branch, if it does not exist yet.
     -+	 * Create the default symlink from ".git/HEAD" to the default
     -+	 * branch name, if it does not exist yet.
     ++	 * Point the HEAD symref to the initial branch with if HEAD does
     ++	 * not yet exist.
       	 */
       	path = git_path_buf(&buf, "HEAD");
       	reinit = (!access(path, R_OK)
     @@ builtin/init-db.c: static int create_default_files(const char *template_path,
      +
      +		if (create_symref("HEAD", ref, NULL) < 0)
       			exit(1);
     --	}
      +		free(ref);
     -+	} else if (initial_branch)
     -+		warning(_("re-init: ignoring --initial-branch=%s"),
     -+			initial_branch);
     + 	}
       
       	initialize_repository_version(fmt->hash_algo);
     - 
      @@ builtin/init-db.c: static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash
       }
       
     @@ builtin/init-db.c: int init_db(const char *git_dir, const char *real_git_dir,
      -	reinit = create_default_files(template_dir, original_git_dir, &repo_fmt);
      +	reinit = create_default_files(template_dir, original_git_dir,
      +				      initial_branch, &repo_fmt);
     ++	if (reinit && initial_branch)
     ++		warning(_("re-init: ignored --initial-branch=%s"),
     ++			initial_branch);
       
       	create_object_directory();
       
     @@ t/t0001-init.sh: test_expect_success MINGW 'redirect std handles' '
      +
      +	: re-initializing should not change the branch name &&
      +	git init --initial-branch=ignore initial-branch-option 2>err &&
     -+	test_i18ngrep "ignoring --initial-branch" err &&
     ++	test_i18ngrep "ignored --initial-branch" err &&
      +	git -C initial-branch-option symbolic-ref HEAD >actual &&
      +	grep hello actual
      +'
  5:  a500e0f214 =  6:  7747eaa57d init: allow setting the default for the initial branch name via the config
  6:  c0d74cedd1 =  7:  1cff7705e4 clone: use configured default branch name when appropriate
  7:  00a1b281e5 !  8:  0a7c0bdfda remote: use the configured default branch name when appropriate

@@ remote.c: static void read_branches_file(struct remote *remote)
/*
* The branches file would have URL and optionally
- * #branch specified. The "master" (or specified) branch is
-+ * #branch specified. The main (or specified) branch is
++ * #branch specified. The default (or specified) branch is
* fetched and stored in the local branch matching the
* remote name.
*/
8: 1aa0e63785 = 9: 6c72abf677 testsvn: respect init.defaultBranch

Signature · 1 line
gitgitgadget
#154 lore raw

PATCH v4 1/9 fmt-merge-msg: stop treating `master` specially

From: Johannes Schindelin <[email protected]>

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.

---
 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(-)
fmt-merge-msg.c +1 -4
index 72d32bd73b..cfb8ff2f33 100644
@@ -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,
t/t1507-rev-parse-upstream.sh +1 -1
index dfc0d96d8a..f213aa8053 100755
@@ -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
 )
 '
t/t4013-diff-various.sh +2 -2
index 3f60f7d96c..43267d6024 100755
@@ -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
t/t4013/diff.log_--decorate=full_--all +1 -1
index 3f9b872ece..c56783b985 100644
@@ -31,7 +31,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 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 <[email protected]>
t/t4013/diff.log_--decorate_--all +1 -1
index f5e20e1e14..1cbdc038f4 100644
@@ -31,7 +31,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (side)
 Author: A U Thor <[email protected]>
t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ +1 -1
index a18f1472a9..f5b1b6516b 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <[email protected]>
t/t4013/diff.log_--patch-with-stat_master +1 -1
index ae425c4672..af23803cdc 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <[email protected]>
t/t4013/diff.log_--patch-with-stat_master_--_dir_ +1 -1
index d5207cadf4..814098fbf8 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <[email protected]>
t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master +1 -1
index 0fc1e8cd71..b927fe4a98 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
  dir/sub | 2 ++
  file0   | 3 +++
t/t4013/diff.log_--root_--patch-with-stat_--summary_master +1 -1
index dffc09dde9..6db3cea329 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <[email protected]>
t/t4013/diff.log_--root_--patch-with-stat_master +1 -1
index 55aa98012d..98e9c320c3 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <[email protected]>
t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master +1 -1
index 019d85f7de..b61b1117ae 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
  dir/sub | 2 ++
  file0   | 3 +++
t/t4013/diff.log_--root_-p_master +1 -1
index b42c334439..345bd9e8a9 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <[email protected]>
t/t4013/diff.log_--root_master +1 -1
index e8f46159da..db56b1fe6b 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <[email protected]>
t/t4013/diff.log_-m_-p_--first-parent_master +1 -1
index 7a0073f529..bcadb50e26 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 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
t/t4013/diff.log_-m_-p_master +2 -2
index 9ca62a01ed..2acf43a9fb 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 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 <[email protected]>
 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
t/t4013/diff.log_-p_--first-parent_master +1 -1
index 3fc896d424..c6a5876d80 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
 Author: A U Thor <[email protected]>
t/t4013/diff.log_-p_master +1 -1
index bf1326dc36..1841cded94 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <[email protected]>
t/t4013/diff.log_master +1 -1
index a8f6ce5abd..f8ec445eb3 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <[email protected]>
t/t4013/diff.show_--first-parent_master +1 -1
index 3dcbe473a0..94548f4598 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 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
t/t4013/diff.show_-c_master +1 -1
index 81aba8da96..1c46ed64fd 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 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
t/t4013/diff.show_-m_master +2 -2
index 4ea2ee453d..7559fc22f8 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 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 <[email protected]>
 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
t/t4013/diff.show_master +1 -1
index fb08ce0e46..57091c5d90 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 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
t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master +1 -1
index 30aae7817b..5f13a71bb5 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
  dir/sub | 2 ++
  file0   | 3 +++
t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master +1 -1
index d1d32bd34c..8acb88267b 100644
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <[email protected]>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side'
+    Merge branch 'side' into master
 
  dir/sub | 2 ++
  file0   | 3 +++
t/t4202-log.sh +36 -36

215 lines not on this page · raw message

t/t6200-fmt-merge-msg.sh +18 -18
index e4c2a6eca4..2b3fd498d0 100755
@@ -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
 
t/t7600-merge.sh +7 -7
index 5883a6adc3..1d45f9a4ed 100755
@@ -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' '
t/t7608-merge-messages.sh +5 -5
index 8e7e0a5865..2af33f195b 100755
@@ -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
Signature · 1 line
gitgitgadget
#155 lore raw

Re: [PATCH v4 1/9] fmt-merge-msg: stop treating `master` specially

Quoted 9 lines · Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

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.

---

Hi Dscho,

This change will also affect git-subtree test.
We'll need this patch for subtree:
----------------8<-------------------
From: =?UTF-8?q?=C4=90o=C3=A0n=20Tr=E1=BA=A7n=20C=C3=B4ng=20Danh?=
<[email protected]>
Date: Mon, 29 Jun 2020 22:56:37 +0700
Subject: [PATCH] contrib: subtree: adjust test to change in fmt-merge-msg
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

We're starting to stop treating `master' specially in fmt-merge-msg. Adjust the test to reflect that change.

---
 contrib/subtree/t/t7900-subtree.sh | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
contrib/subtree/t/t7900-subtree.sh +4 -2
index 57ff4b25c1..53d7accf94 100755
@@ -196,7 +196,8 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix' '
 		cd "$subtree_test_count" &&
 		git fetch ./"sub proj" master &&
 		git subtree merge --prefix="sub dir" FETCH_HEAD &&
-		check_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\''"
+		check_equal "$(last_commit_message)" \
+			"Merge commit '\''$(git rev-parse FETCH_HEAD)'\'' into master"
 	)
 '
 
@@ -273,7 +274,8 @@ test_expect_success 'merge new subproj history into subdir/ with a slash appende
 		cd "$test_count" &&
 		git fetch ./subproj master &&
 		git subtree merge --prefix=subdir/ FETCH_HEAD &&
-		check_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\''"
+		check_equal "$(last_commit_message)" \
+			"Merge commit '\''$(git rev-parse FETCH_HEAD)'\'' into master"
 	)
 '
 
Signature · 2 lines
2.27.0.111.gc72c7da667
Danh