Merge branch 'js/init-defaultbranch-advice'

Our users are going to be trained to prepare for future change of
init.defaultBranch configuration variable.

* js/init-defaultbranch-advice:
  init: provide useful advice about init.defaultBranch
  get_default_branch_name(): prepare for showing some advice
  branch -m: allow renaming a yet-unborn branch
  init: document `init.defaultBranch` better
This commit is contained in:
Junio C Hamano 2020-12-18 15:15:17 -08:00
commit 772bdcd429
10 changed files with 61 additions and 20 deletions

View file

@ -20,8 +20,9 @@ DESCRIPTION
This command creates an empty Git repository - basically a `.git`
directory with subdirectories for `objects`, `refs/heads`,
`refs/tags`, and template files. An initial `HEAD` file that
references the HEAD of the master branch is also created.
`refs/tags`, and template files. An initial branch without any
commits will be created (see the `--initial-branch` option below
for its name).
If the `$GIT_DIR` environment variable is set then it specifies a path
to use instead of `./.git` for the base of the repository.
@ -73,8 +74,10 @@ 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`.
Use the specified name for the initial branch in the newly created
repository. If not specified, fall back to the default name (currently
`master`, but this is subject to change in the future; the name can be
customized via the `init.defaultBranch` configuration variable).
--shared[=(false|true|umask|group|all|world|everybody|0xxx)]::

View file

@ -538,7 +538,9 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
strbuf_addf(&logmsg, "Branch: renamed %s to %s",
oldref.buf, newref.buf);
if (!copy && rename_ref(oldref.buf, newref.buf, logmsg.buf))
if (!copy &&
(!head || strcmp(oldname, head) || !is_null_oid(&head_oid)) &&
rename_ref(oldref.buf, newref.buf, logmsg.buf))
die(_("Branch rename failed"));
if (copy && copy_existing_ref(oldref.buf, newref.buf, logmsg.buf))
die(_("Branch copy failed"));

View file

@ -1326,7 +1326,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
remote_head = NULL;
option_no_checkout = 1;
if (!option_bare) {
const char *branch = git_default_branch_name();
const char *branch = git_default_branch_name(0);
char *ref = xstrfmt("refs/heads/%s", branch);
install_branch_config(0, branch, remote_name, ref);

View file

@ -202,7 +202,8 @@ void initialize_repository_version(int hash_algo, int reinit)
static int create_default_files(const char *template_path,
const char *original_git_dir,
const char *initial_branch,
const struct repository_format *fmt)
const struct repository_format *fmt,
int quiet)
{
struct stat st1;
struct strbuf buf = STRBUF_INIT;
@ -267,7 +268,7 @@ static int create_default_files(const char *template_path,
char *ref;
if (!initial_branch)
initial_branch = git_default_branch_name();
initial_branch = git_default_branch_name(quiet);
ref = xstrfmt("refs/heads/%s", initial_branch);
if (check_refname_format(ref, 0) < 0)
@ -438,7 +439,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,
initial_branch, &repo_fmt);
initial_branch, &repo_fmt,
flags & INIT_DB_QUIET);
if (reinit && initial_branch)
warning(_("re-init: ignored --initial-branch=%s"),
initial_branch);

24
refs.c
View file

@ -562,7 +562,20 @@ void expand_ref_prefix(struct strvec *prefixes, const char *prefix)
strvec_pushf(prefixes, *p, len, prefix);
}
char *repo_default_branch_name(struct repository *r)
static const char default_branch_name_advice[] = N_(
"Using '%s' as the name for the initial branch. This default branch name\n"
"is subject to change. To configure the initial branch name to use in all\n"
"of your new repositories, which will suppress this warning, call:\n"
"\n"
"\tgit config --global init.defaultBranch <name>\n"
"\n"
"Names commonly chosen instead of 'master' are 'main', 'trunk' and\n"
"'development'. The just-created branch can be renamed via this command:\n"
"\n"
"\tgit branch -m <name>\n"
);
char *repo_default_branch_name(struct repository *r, int quiet)
{
const char *config_key = "init.defaultbranch";
const char *config_display_key = "init.defaultBranch";
@ -574,8 +587,11 @@ char *repo_default_branch_name(struct repository *r)
else if (repo_config_get_string(r, config_key, &ret) < 0)
die(_("could not retrieve `%s`"), config_display_key);
if (!ret)
if (!ret) {
ret = xstrdup("master");
if (!quiet)
advise(_(default_branch_name_advice), ret);
}
full_ref = xstrfmt("refs/heads/%s", ret);
if (check_refname_format(full_ref, 0))
@ -585,12 +601,12 @@ char *repo_default_branch_name(struct repository *r)
return ret;
}
const char *git_default_branch_name(void)
const char *git_default_branch_name(int quiet)
{
static char *ret;
if (!ret)
ret = repo_default_branch_name(the_repository);
ret = repo_default_branch_name(the_repository, quiet);
return ret;
}

4
refs.h
View file

@ -170,8 +170,8 @@ int dwim_log(const char *str, int len, struct object_id *oid, char **ref);
* 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);
const char *git_default_branch_name(int quiet);
char *repo_default_branch_name(struct repository *r, int quiet);
/*
* A ref_transaction represents a collection of reference updates that

View file

@ -284,7 +284,7 @@ static void read_branches_file(struct remote *remote)
if (frag)
*(frag++) = '\0';
else
frag = (char *)git_default_branch_name();
frag = (char *)git_default_branch_name(0);
add_url_alias(remote, strbuf_detach(&buf, NULL));
refspec_appendf(&remote->fetch, "refs/heads/%s:refs/heads/%s",
@ -2206,7 +2206,8 @@ struct ref *guess_remote_head(const struct ref *head,
/* 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());
char *ref = xstrfmt("refs/heads/%s",
git_default_branch_name(0));
r = find_ref_by_name(refs, ref);
free(ref);

View file

@ -163,7 +163,7 @@ test_expect_success 'reinit' '
(
mkdir again &&
cd again &&
git init >out1 2>err1 &&
git -c init.defaultBranch=initial init >out1 2>err1 &&
git init >out2 2>err2
) &&
test_i18ngrep "Initialized empty" again/out1 &&
@ -558,6 +558,13 @@ test_expect_success 'overridden default initial branch name (config)' '
grep nmb actual
'
test_expect_success 'advice on unconfigured init.defaultBranch' '
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME= git -c color.advice=always \
init unconfigured-default-branch-name 2>err &&
test_decode_color <err >decoded &&
test_i18ngrep "<YELLOW>hint: " decoded
'
test_expect_success 'overridden default main branch name (env)' '
test_config_global init.defaultBranch nmb &&
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=env git init main-branch-env &&
@ -571,4 +578,12 @@ test_expect_success 'invalid default branch name' '
test_i18ngrep "invalid branch name" err
'
test_expect_success 'branch -m with the initial branch' '
git init rename-initial &&
git -C rename-initial branch -m renamed &&
test renamed = $(git -C rename-initial symbolic-ref --short HEAD) &&
git -C rename-initial branch -m renamed again &&
test again = $(git -C rename-initial symbolic-ref --short HEAD)
'
test_done

View file

@ -79,7 +79,7 @@ setup_repo () {
name=$1 worktreecfg=$2 gitfile=$3 barecfg=$4 &&
sane_unset GIT_DIR GIT_WORK_TREE &&
git init "$name" &&
git -c init.defaultBranch=initial init "$name" &&
maybe_config "$name/.git/config" core.worktree "$worktreecfg" &&
maybe_config "$name/.git/config" core.bare "$barecfg" &&
mkdir -p "$name/sub/sub" &&

View file

@ -1202,7 +1202,9 @@ test_create_repo () {
mkdir -p "$repo"
(
cd "$repo" || error "Cannot setup test environment"
"${GIT_TEST_INSTALLED:-$GIT_EXEC_PATH}/git$X" init \
"${GIT_TEST_INSTALLED:-$GIT_EXEC_PATH}/git$X" -c \
init.defaultBranch="${GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME-master}" \
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