Create a Git repository safely with git-init-db
You will finish with an empty Git repository in the directory you choose, plus a quick way to verify whether Git created a working repository, a bare repository, or a separate Git directory. The installed command is Git 2.43.0 from Ubuntu package 2.43.0-1ubuntu7.3. Allow about ten minutes for a first repository.
The route
Jump straight to the step you need, or tick off Done means at the end.
git-init-db is a synonym for git-init. The longer name is retained for compatibility, but git init is the form you will see in current Git documentation. The examples below use git init-db so the command named by this guide is explicit.
1. Choose the directory before creating anything
Creating a repository changes the target directory by adding Git metadata. Work as your ordinary user in a directory you own. No example here needs sudo; using elevated privileges can leave the repository owned by root and make later commits awkward.
For an existing project, replace the placeholder with its real path and inspect it first:
$ PROJECT_DIR=/path/to/project
$ pwd
$ find "$PROJECT_DIR" -maxdepth 1 -mindepth 1 -printf '%f\n' | sort
Checkpoint: confirm that PROJECT_DIR names the project you intend to track. Do not point this command at your home directory or a filesystem root unless you have deliberately checked what will be included later.
2. Initialise a normal working repository
Change into the project and run the command without a directory argument. Git creates .git in the current directory, including the object and reference directories needed for future commits:
$ cd "$PROJECT_DIR"
$ git init-db
hint: Using 'master' as the name for the initial branch
Initialized empty Git repository in /path/to/project/.git/
The exact hint can differ. On this installed Git, the default initial branch is currently master, but the manual says that this is subject to change and can be customised with init.defaultBranch. The repository has no commits yet.
Verify the result without changing it:
$ git status --short --branch
## No commits yet on master
$ test -d .git/objects && test -d .git/refs/heads && echo 'repository layout is present'
repository layout is present
3. Set the initial branch explicitly when it matters
git-init-db's synopsis does not expose --initial-branch, even though the current git init command does. If the first branch name is part of your workflow, set init.defaultBranch before running the compatibility command, or use git init directly:
$ git config --global init.defaultBranch main
$ git init-db /path/to/another-project
Initialized empty Git repository in /path/to/another-project/.git/
This changes your global Git configuration, so treat it as a deliberate user-level setting. To avoid changing global configuration, use the modern command with an explicit branch for just this repository:
$ git init --initial-branch=main /path/to/another-project
If you set a global default only for this test, inspect it with git config --global --get init.defaultBranch and remove that setting later with git config --global --unset init.defaultBranch. The unset command changes configuration and may report an error if no value exists.
4. Create a bare repository for a server-side Git endpoint
A bare repository has no working tree. It is appropriate as a shared push target, not as the directory where you edit files. Create it in a new, clearly named directory:
$ git init-db --bare /path/to/project.git
Initialized empty Git repository in /path/to/project.git/
$ git --git-dir=/path/to/project.git rev-parse --is-bare-repository
true
Git places HEAD, objects, refs, hooks and configuration directly in the bare directory. Do not run ordinary working-tree commands there or assume that a checkout will appear beside the repository.
If several users will write to the bare repository, permissions are an operational and security boundary. The --shared option changes core.sharedRepository and is not a substitute for choosing the right Unix group and directory ownership. Test the access model with the intended accounts before accepting pushes.
5. Keep the Git directory somewhere else
Use --separate-git-dir when the working tree and repository metadata must be stored in different places:
$ git init-db --separate-git-dir /path/to/git-data /path/to/project
Initialized empty Git repository in /path/to/git-data/
$ cat /path/to/project/.git
gitdir: /path/to/git-data
In this mode, .git is a text file containing the actual repository path. Check both paths before moving either one. A broken path makes the working tree appear not to be a repository.
6. Reinitialisation and recovery
Running the command in an existing repository is normally safe: Git does not overwrite existing repository data. It may pick up newly added templates, and --separate-git-dir can move the repository metadata. That does not mean every invocation is harmless. Stop if the path is unexpected, if ownership is wrong, or if a separate Git directory would replace a layout you still need.
If you created a repository in the wrong empty directory, the command itself has no undo operation. Preserve any files you care about, then remove only the unwanted .git directory with a path you have checked. For a separate repository, preserve both the working tree's .git file and the target Git directory until you have confirmed the correct replacement. Do not use a broad recursive deletion command as a shortcut.
A failed initialisation may leave a partial directory. Read the error, inspect the target and check ownership before retrying. If the directory contains valuable data, copy or back it up first. Most failures are path, permission or invalid template-directory problems, not reasons to run the command as root.
Done means
- The target path was checked before it was modified.
git init-dbcreated a normal repository, or--barecreated the intended server-side repository.git status --short --branchorgit rev-parse --is-bare-repositoryconfirms the type and initial state.- The initial branch choice is understood, rather than copied from an unexamined default.
- Any separate Git directory and its
.gitpointer are both present and readable.