init: allow specifying the initial branch name for the new repository
There is a growing number of projects and companies desiring to change the main branch name of their repositories (see e.g. https://twitter.com/mislav/status/1270388510684598272 for background on this). To change that branch name for new repositories, currently the only way to do that automatically is by copying all of Git's template directory, then hard-coding the desired default branch name into the `.git/HEAD` file, and then configuring `init.templateDir` to point to those copied template files. To make this process much less cumbersome, let's introduce a new option: `--initial-branch=<branch-name>`. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Johannes Schindelin committed
Jun 24, 2020 at 14:46 UTC
32ba12dab2acf1ad11836a627956d1473f6b851a
5 files changed
+50
-8
Documentation/git-init.txt
+7
@@ -11,6 +11,7 @@ SYNOPSIS
11
[verse]
12
'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
13
[--separate-git-dir <git dir>] [--object-format=<format>]
14
+ [-b <branch-name> | --initial-branch=<branch-name>]
15
[--shared[=<permissions>]] [directory]
16
17
@@ -67,6 +68,12 @@ repository.
68
+
69
If this is reinitialization, the repository will be moved to the specified path.
70
71
+-b <branch-name::
72
+--initial-branch=<branch-name>::
73
+
74
+Use the specified name for the initial branch in the newly created repository.
75
+If not specified, fall back to the default name: `master`.
76
+
77
--shared[=(false|true|umask|group|all|world|everybody|0xxx)]::
78
79
Specify that the Git repository is to be shared amongst several users. This
builtin/clone.c
+2
-1
@@ -1108,7 +1108,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
1108
}
1109
}
1110
1111
- init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, INIT_DB_QUIET);
1111
+ init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL,
1112
+ INIT_DB_QUIET);
1113
1114
if (real_git_dir)
1115
git_dir = real_git_dir;
builtin/init-db.c
+27
-6
@@ -203,6 +203,7 @@ void initialize_repository_version(int hash_algo)
203
204
static int create_default_files(const char *template_path,
205
const char *original_git_dir,
206
+ const char *initial_branch,
207
const struct repository_format *fmt)
208
{
209
struct stat st1;
@@ -258,15 +259,26 @@ static int create_default_files(const char *template_path,
259
die("failed to set up refs db: %s", err.buf);
260
261
/*
261
- * Create the default symlink from ".git/HEAD" to the "master"
262
- * branch, if it does not exist yet.
262
+ * Point the HEAD symref to the initial branch with if HEAD does
263
+ * not yet exist.
264
*/
265
path = git_path_buf(&buf, "HEAD");
266
reinit = (!access(path, R_OK)
267
|| readlink(path, junk, sizeof(junk)-1) != -1);
268
if (!reinit) {
268
- if (create_symref("HEAD", "refs/heads/master", NULL) < 0)
269
+ char *ref;
270
+
271
+ if (!initial_branch)
272
+ initial_branch = "master";
273
+
274
+ ref = xstrfmt("refs/heads/%s", initial_branch);
275
+ if (check_refname_format(ref, 0) < 0)
276
+ die(_("invalid initial branch name: '%s'"),
277
+ initial_branch);
278
+
279
+ if (create_symref("HEAD", ref, NULL) < 0)
280
exit(1);
281
+ free(ref);
282
}
283
284
initialize_repository_version(fmt->hash_algo);
@@ -383,7 +395,8 @@ static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash
395
}
396
397
int init_db(const char *git_dir, const char *real_git_dir,
386
- const char *template_dir, int hash, unsigned int flags)
398
+ const char *template_dir, int hash, const char *initial_branch,
399
+ unsigned int flags)
400
{
401
int reinit;
402
int exist_ok = flags & INIT_DB_EXIST_OK;
@@ -425,7 +438,11 @@ int init_db(const char *git_dir, const char *real_git_dir,
438
439
validate_hash_algorithm(&repo_fmt, hash);
440
428
- reinit = create_default_files(template_dir, original_git_dir, &repo_fmt);
441
+ reinit = create_default_files(template_dir, original_git_dir,
442
+ initial_branch, &repo_fmt);
443
+ if (reinit && initial_branch)
444
+ warning(_("re-init: ignored --initial-branch=%s"),
445
+ initial_branch);
446
447
create_object_directory();
448
@@ -528,6 +545,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
545
const char *template_dir = NULL;
546
unsigned int flags = 0;
547
const char *object_format = NULL;
548
+ const char *initial_branch = NULL;
549
int hash_algo = GIT_HASH_UNKNOWN;
550
const struct option init_db_options[] = {
551
OPT_STRING(0, "template", &template_dir, N_("template-directory"),
@@ -541,6 +559,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
559
OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET),
560
OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
561
N_("separate git dir from working tree")),
562
+ OPT_STRING('b', "initial-branch", &initial_branch, N_("name"),
563
+ N_("override the name of the initial branch")),
564
OPT_STRING(0, "object-format", &object_format, N_("hash"),
565
N_("specify the hash algorithm to use")),
566
OPT_END()
@@ -652,5 +672,6 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
672
UNLEAK(work_tree);
673
674
flags |= INIT_DB_EXIST_OK;
655
- return init_db(git_dir, real_git_dir, template_dir, hash_algo, flags);
675
+ return init_db(git_dir, real_git_dir, template_dir, hash_algo,
676
+ initial_branch, flags);
677
}
cache.h
+1
-1
@@ -628,7 +628,7 @@ int path_inside_repo(const char *prefix, const char *path);
628
629
int init_db(const char *git_dir, const char *real_git_dir,
630
const char *template_dir, int hash_algo,
631
- unsigned int flags);
631
+ const char *initial_branch, unsigned int flags);
632
void initialize_repository_version(int hash_algo);
633
634
void sanitize_stdfds(void);
t/t0001-init.sh
+13
@@ -464,4 +464,17 @@ test_expect_success MINGW 'redirect std handles' '
464
grep "Needed a single revision" output.txt
465
'
466
467
+test_expect_success '--initial-branch' '
468
+ git init --initial-branch=hello initial-branch-option &&
469
+ git -C initial-branch-option symbolic-ref HEAD >actual &&
470
+ echo refs/heads/hello >expect &&
471
+ test_cmp expect actual &&
472
+
473
+ : re-initializing should not change the branch name &&
474
+ git init --initial-branch=ignore initial-branch-option 2>err &&
475
+ test_i18ngrep "ignored --initial-branch" err &&
476
+ git -C initial-branch-option symbolic-ref HEAD >actual &&
477
+ grep hello actual
478
+'
479
+
480
test_done