]> git.ipfire.org Git - thirdparty/git.git/commitdiff
init: allow specifying the initial branch name for the new repository
authorJohannes Schindelin <johannes.schindelin@gmx.de>
Wed, 24 Jun 2020 14:46:32 +0000 (14:46 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 24 Jun 2020 16:14:21 +0000 (09:14 -0700)
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>
Documentation/git-init.txt
builtin/clone.c
builtin/init-db.c
cache.h
t/t0001-init.sh

index f9467cc6a4c791ac3b445f5b0172144f7a1bac15..ddfe265da5b6524f30d972bfea990bb2a89b5611 100644 (file)
@@ -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
index cb48a291caf9a364f21208e762f6b6e07a6ca7f6..487b0a42d752b7637f87e9e9d76bfe4bf3e53dc5 100644 (file)
@@ -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;
index 0b7222e7188858a7c820e870dce4c2dd0370f443..8fdfc334ac6e3801375b75915cfd608a0a026985 100644 (file)
@@ -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,15 +259,26 @@ 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.
+        * 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)
                  || 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);
        }
 
        initialize_repository_version(fmt->hash_algo);
@@ -383,7 +395,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 +438,11 @@ 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);
+       if (reinit && initial_branch)
+               warning(_("re-init: ignored --initial-branch=%s"),
+                       initial_branch);
 
        create_object_directory();
 
@@ -528,6 +545,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 +559,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 +672,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);
 }
diff --git a/cache.h b/cache.h
index 0f0485ecfe2cd9a2270cffcec3552e901658539a..654426460cc06ca093fad53ea3b72622d2b7bfd0 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -628,7 +628,7 @@ int path_inside_repo(const char *prefix, const char *path);
 
 int init_db(const char *git_dir, const char *real_git_dir,
            const char *template_dir, int hash_algo,
-           unsigned int flags);
+           const char *initial_branch, unsigned int flags);
 void initialize_repository_version(int hash_algo);
 
 void sanitize_stdfds(void);
index 1edd5aeb8f01d490b1cceba2c1d67df181868280..386c06b5dd2ce99107f6276ab2e77662122f02f4 100755 (executable)
@@ -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 "ignored --initial-branch" err &&
+       git -C initial-branch-option symbolic-ref HEAD >actual &&
+       grep hello actual
+'
+
 test_done