Skip to content
masterclass Buddy

Git · Command

git init

git init creates a new, empty Git repository, or reinitializes one that already exists. It is usually the first command you run to put a project under version control.

Last updated

How it works

git init builds the repository skeleton, which is normally a .git directory. It holds the object store, refs/heads and refs/tags, plus files copied from a template directory. It also creates an initial branch with no commits yet. You can set GIT_DIR to put the repository somewhere other than ./.git, and GIT_OBJECT_DIRECTORY to choose where objects are stored. If you pass a directory, Git runs inside it and creates it if needed. Options also control the hash algorithm, the ref storage format, the initial branch name and group-sharing permissions.

Syntax

git init [-q | --quiet] [--bare] [--template=<template-directory>] [--separate-git-dir <git-dir>] [--object-format=<format>] [--ref-format=<format>] [-b <branch-name> | --initial-branch=<branch-name>] [--shared[=<permissions>]] [<directory>]

Parameters

NameTypeDescription
-q, --quietflagPrints only errors and warnings; all other output is hidden.
--bareflagCreates a bare repository, which has no working tree. If GIT_DIR is unset, the current directory is used.
--template=<template-directory>pathThe directory whose template files are copied into the new repository.
--separate-git-dir=<git-dir>pathStores the repository at <git-dir> and leaves a small text file pointing to it where .git would normally be.
--object-format=<format>sha1 | sha256The hash algorithm for the repository. sha1 is the default; sha256 only works if enabled.
--ref-format=<format>files | reftableHow refs are stored: files (loose files plus packed-refs, the default) or reftable.
-b, --initial-branch=<branch-name>stringThe name of the first branch in the new repository.
--shared[=<permissions>]false | true | umask | group | all | world | everybody | 0xxxMakes the repository shareable by several users by setting core.sharedRepository. With no value it means group.
<directory>pathThe directory to run in; it is created if it does not exist.

Key points

  • You can safely run it again inside an existing repository: nothing already there is replaced.
  • Rerunning it is mainly useful to pick up new template files, or, together with --separate-git-dir, to move the repository to another location.
  • With --bare and no GIT_DIR set, the current directory itself becomes the repository. This is the usual setup for a central repository that others push to.
  • With --separate-git-dir, .git becomes a plain text file that points to where the repository data actually lives.
  • If you give a target directory that does not exist yet, git init creates it for you.
  • Only template entries whose names do not start with a dot are copied into the new repository directory.
  • With --shared, people in the same Unix group can push to the repository.
  • Unless you choose otherwise, refs are stored in the traditional files format; reftable is an opt-in alternative.

Common mistakes

  • If you don't pass -b, the first branch is named master. Git 3.0 will change this default to main, so set init.defaultBranch or -b if you need a predictable name.
  • Choosing sha256 is a lasting decision: SHA-256 and SHA-1 repositories cannot currently exchange data with each other.
  • Shared repositories reject force pushes that are not fast-forwards by default, which can surprise people used to rewriting history.
  • The sample hooks copied from the templates do nothing until you rename each one to drop its .sample suffix.

Example: Start a repo with a chosen branch name, plus a bare remote

#!/usr/bin/env bash
set -euo pipefail

# Bare repository to act as a shared remote
git init --bare --initial-branch=main /tmp/demo-remote.git

# New working repository (directory is created automatically)
git init -b main /tmp/demo-app
cd /tmp/demo-app

echo "# Demo" > README.md
git add .
git commit -m "Initial commit"

git remote add origin /tmp/demo-remote.git
git push -u origin main

# Safe to rerun: existing data is left alone
git init

The script creates a bare remote and a working repository, both starting on main, makes a first commit, pushes it, and then runs git init again to show that rerunning is harmless.

When to use it

Version an existing project

A folder of code that was never tracked gets a repository; then you run git add . and git commit to record its starting state.

Central push target

An admin creates a bare repository on a server, using --shared=group so team members can push to it.

Keep repository data outside the work tree

With --separate-git-dir, the project folder holds only a pointer file, and the actual repository lives on another disk or path.

Standard team setup

A company template directory and init.defaultBranch give every new repository the same hooks, exclude patterns and branch name.

Interview questions

QWhat is a bare repository, and when would you create one with git init --bare?

A bare repository has no working tree, so there are no checked-out files to edit. With --bare, the repository itself is created in the current directory, or in GIT_DIR if that is set, instead of inside a .git subfolder. It is the usual choice for a central or server repository that people push to and fetch from.

Follow-up: Why add --shared to a server repository? It sets core.sharedRepository so new files get group-friendly permissions, which lets everyone in the Unix group push. It also turns on receive.denyNonFastForwards by default.

QWhat happens if you run git init in a directory that is already a Git repository?

It is safe: Git reinitializes the repository without overwriting anything already there. People mostly do this to pick up newly added template files. It is also how you move the repository elsewhere with --separate-git-dir.

Follow-up: Does rerunning it turn on the sample hooks? No. Sample hooks stay disabled until you rename each file to drop its .sample suffix.

QHow do you control the name of the first branch in a new repository?

Pass -b <name> or --initial-branch=<name> to git init. To set it for every new repository, use the init.defaultBranch config variable. If you do neither, Git currently uses master, and the docs say this will become main in Git 3.0.

Follow-up: Which wins between the --object-format option, GIT_DEFAULT_HASH and init.defaultObjectFormat? Both the command-line option and the environment variable take precedence over the config setting.

  • git clone
  • git add
  • git commit
  • git config
  • git init-db
  • githooks
  • gitignore

Source: Git - git-init Documentation. Checked 2026-11-02.