@matheusbsbs / matheus-bagliano / commits / 32ba12dab2
Fork 0

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