By admin , 28 April 2026

Introduction

git init turns an ordinary directory into a Git repository. It creates a hidden .git directory holding all of Git's bookkeeping: objects, refs, configuration, and hooks. The working tree (your normal files) is unchanged.

Initializing a project

mkdir my-project
cd my-project
git init
# Initialized empty Git repository in /home/ada/my-project/.git/

Since Git 2.28 you can set the initial branch name on the command line:

git init --initial-branch=main
# or shorthand
git init -b main

What just happened

Inspect the new directory:

ls -a
ls .git

You will see HEAD, config, description, hooks/, info/, objects/, and refs/. Nothing is committed yet; HEAD points at an unborn branch.

Your first commit

  1. Create a file: echo "# My Project" > README.md
  2. Stage it: git add README.md
  3. Commit: git commit -m "Initial commit"
echo "# My Project" > README.md
git add README.md
git commit -m "Initial commit"
git log --oneline

Bare repositories

Servers usually host bare repositories without a working tree. Use --bare:

git init --bare project.git

Bare repos are the target of pushes; you do not edit files in them directly.

Re-initializing

Running git init again in an existing repo is safe; it re-applies templates and prints "Reinitialized existing Git repository". It does not delete commits.

Templates

By default git init seeds .git/hooks/ from /usr/share/git-core/templates/. You can override the template directory to inject your own hooks, default .gitignore, or description into every new repo:

git init --template=~/.git-templates
git config --global init.templateDir ~/.git-templates

This is how organizations push standard pre-commit hooks to every new clone without each developer copying files manually.

Initial branch name

Many projects have moved from master to main as the default branch name. The choice is local to your repo, but matching your hosting provider's default avoids confusion when pushing for the first time. Set it once globally and forget about it: git config --global init.defaultBranch main.

Where Git stops looking

Git locates the repository by walking up the directory tree until it finds a .git directory or file. The walk stops at filesystem boundaries by default (core.discoveryAcrossFilesystem changes that). The environment variable GIT_DIR overrides discovery entirely; GIT_WORK_TREE sets a non-default working tree. Together they let you operate on a repo whose .git is in an unusual location:

GIT_DIR=/srv/repos/widget.git GIT_WORK_TREE=/var/www git status

Common mistakes

Running git init in your home directory by accident, which puts your entire dotfile collection under one massive repository root. Always check pwd first. Another error: deleting .git to "start over" while keeping uncommitted work. That is fine, but realize all history is gone forever. Finally, do not commit large binaries to a freshly initialized repo without first writing a .gitignore; you will regret it when the repo balloons. Run git status right after git init to see what Git plans to track before you stage anything.