On This Page
- Syntax
- How to Initialize a Git Repository
- What Does git init Do?
- What Happens Inside .git/ (Hands-on exploration)
- Detailed Command Options & Advanced Usage
- Real-World Scenario: Setting Up a Clean Repository
- Common Pitfalls and Mistakes
- Command Quick Reference
- FAQ (People Also Ask)
- Continue learning
- Test Your Knowledge
How to Initialize a Git Repository with git init
Quick answer: Run git init from a project directory to create a local Git repository. It creates a hidden .git/ directory but does not stage files, make a commit, create a GitHub repository, or upload anything.
Defaults used on this page: the output shown comes from a repository using Git’s default SHA-1 object format and the default
filesreference backend, so you see.git/objects/plus.git/refs/heads/.git init --object-format=sha256andgit init --ref-format=reftablechange those two details without changing the overall layout described here.
Syntax
git init # initialise the current directory
git init <directory> # create the directory, then initialise it
git init --bare <dir> # create a repository with no working tree
git init -b main # set the initial branch name
How to Initialize a Git Repository
For a new project, create a folder, initialize it, then stage and commit a file:
mkdir my-project
cd my-project
git init -b main
echo "# My project" > README.md
git add README.md
git commit -m "Initial commit"
If you already have a project, run git init from its root instead of creating a new folder. git init -b main sets the initial branch name on supported Git versions; plain git init uses your configured default. Git does not track files until you stage them with git add and record a commit with git commit. If Git asks for your author details, follow the git config guide. To publish the repository later, add a remote with git remote and push separately.
When run in an existing project folder, git init creates or refreshes repository metadata in .git/; it does not stage or commit your project files. git init <directory> also creates the target directory if it does not exist, and reinitializing a repository can refresh metadata or hook templates. From there the normal sequence is git add to stage files, then git commit to record the first snapshot.
What Does git init Do?
In short, git init means initialize: it turns the current directory into a Git repository by creating a hidden .git/ directory. It does not stage files, create a commit, or contact a remote server.
At its core, a computer’s filesystem is relatively simple: it tracks filenames, file contents, file sizes, and directory hierarchies. It has no native understanding of change history, author identities, or branching paths.
When you run git init in a folder, Git creates a local repository database in a hidden .git/ directory. Your existing files are left unchanged: they are not staged or committed, and no remote server is contacted.
Git compares the working tree with repository state when you run commands such as git status. git init does not start a background watcher or track files; use git add and git commit to record work.
What Happens Inside .git/ (Hands-on exploration)
To understand how Git works, you must look inside the .git/ directory. Let’s initialize a fresh repository and examine the skeleton of Git’s internal database.
Step 1: Initialize the Directory
First, create a new directory and initialize it:
The paths, timestamps, ownership, permissions, and exact messages in the shell output below vary by operating system, Git version, user, and configuration; treat them as representative examples.
$ mkdir git-init-deepdive && cd git-init-deepdive
$ git init
Initialized empty Git repository in /home/admin/Code/git-init-deepdive/.git/
Now let’s list the contents of the newly created .git/ folder:
$ ls -al .git/
total 32
drwxr-xr-x 7 admin admin 4096 Jul 7 10:25 .
drwxr-xr-x 3 admin admin 4096 Jul 7 10:25 ..
-rw-r--r-x 1 admin admin 23 Jul 7 10:25 HEAD
-rw-r--r-x 1 admin admin 92 Jul 7 10:25 config
-rw-r--r-x 1 admin admin 73 Jul 7 10:25 description
drwxr-xr-x 2 admin admin 4096 Jul 7 10:25 hooks
drwxr-xr-x 2 admin admin 4096 Jul 7 10:25 info
drwxr-xr-x 4 admin admin 4096 Jul 7 10:25 objects
drwxr-xr-x 4 admin admin 4096 Jul 7 10:25 refs
Let’s analyze what each of these entries does in a newly initialized repository:
1. HEAD (The Active Pointer)
The HEAD file is a plain text file that tells Git which branch or commit is currently active. Let’s read the contents of this file:
$ cat .git/HEAD
ref: refs/heads/main
This output shows that HEAD points to a reference file at refs/heads/main.
However, if we look inside our repository, the branch file refs/heads/main does not exist yet!
$ ls -R .git/refs
.git/refs:
heads/ tags/
.git/refs/heads:
# Empty!
This state is known as an Unborn Branch. Git points HEAD to the initial branch target (for example, main), but it does not create the branch reference until the first commit. In this page’s SHA-1 example, the ref contains a 40-hex-character object ID; a SHA-256 repository uses a different ID length.
2. config (Local Configuration Settings)
This file houses repository-level settings that override your system and global configurations (refer to git config for details). Let’s view the initial settings:
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
These core variables define how Git interacts with your filesystem:
repositoryformatversion = 0: Defines the repository’s database format version. If Git encounters a repository version higher than it supports, it will refuse to read it.filemode = true: Tells Git to track POSIX file executable bit changes (e.g., if you make a script executable viachmod +x).bare = false: Declares that this is a standard working repository containing checked-out files on disk. A “bare” repository contains only the Git administrative directory (usually for remote hosting servers) and has this set totrue.logallrefupdates = true: Instructs Git to maintain the reflog (a detailed history tracking where branch tips andHEADhave pointed over time, stored in.git/logs/).
3. description (Legacy Web Helper)
This is a plain text file containing a placeholder: Unnamed repository; edit this file 'description' to name the repository.. It is used by GitWeb (a legacy web-based viewer for Git repos). In modern development, this file is ignored and can be safely deleted or left as-is.
4. hooks/ (Lifecycle Automation)
This folder contains shell script templates that automate tasks when Git events occur (e.g., pre-commit, commit-msg, pre-push). These templates are copied from your system installation’s templates directory during initialization.
By default, all scripts in this directory end in .sample, which prevents them from executing. To activate a hook, remove the .sample extension and make the script executable (chmod +x).
5. info/exclude (Local-Only Ignore List)
This file is used to define ignore patterns, similar to a .gitignore file. However, while .gitignore is committed and shared with your team, info/exclude is local-only. Use it to ignore files specific to your local machine (such as local IDE configurations) without affecting other developers’ environments.
6. objects/ (The Object Database)
This is the core storage database for your repository. It uses content-addressable storage to store objects, which are categorized into:
- Blobs: Stored file contents.
- Trees: Directory hierarchies.
- Commits: Metadata snapshots pointing to trees and parents.
Initially, the database contains only two empty subdirectories:
info/andpack/(used for packfile indexes and storage optimization). The database is empty until you run your first commit.
7. refs/ (References)
This directory acts as a index for your repository’s commit pointers. It contains:
refs/heads/: Houses local branch pointers.refs/tags/: Houses tags (frozen pointers to historical commits).refs/remotes/: Houses pointers tracking the state of branches on remote repositories (created after adding a remote).
Detailed Command Options & Advanced Usage
1. Re-initializing an Existing Repository
What happens if you run git init in a directory that is already a Git repository?
$ git init
Reinitialized existing Git repository in /home/admin/Code/git-init-deepdive/.git/
Running git init on an existing repository is safe. It does not overwrite your commits, branches, index, or configuration files. Instead, it checks the directory, repairs missing metadata folders if they were accidentally deleted, and pulls in updated hook templates from the system’s template directory.
2. Bare Repositories (git init --bare)
In a normal repository, the checked-out project files live in a working tree beside a .git/ directory. A bare repository has no checked-out working tree: the repository’s Git directory is the top-level directory itself. Bare repositories are commonly used as shared remotes that collaborators push to and clone from.
# Initialize a bare repository
$ git init --bare my-project.git
Initialized empty Git repository in /home/admin/Code/my-project.git/
Let’s look at the directory structure of a bare repository:
$ ls -F my-project.git
HEAD config description hooks/ info/ objects/ refs/
There is no .git/ subdirectory or checked-out project file; these entries are the repository itself. For day-to-day edits, clone the bare repository into a normal working repository. git init --bare starts an empty repository—it does not copy commits from a project you already have. To create a bare copy that includes an existing repository’s history, use git clone --bare <source> <target>.git instead. See the official git init manual and Pro Git’s guide to getting Git on a server.
3. Setting the Initial Branch Name
Historically, Git default-initialized the primary branch as master. To adopt modern naming conventions, you can specify the default branch name during initialization:
# Initialize a repository with a default branch named "main"
$ git init --initial-branch=main
You can also set this default branch name globally so that all future git init commands apply it automatically (refer to git config):
$ git config --global init.defaultBranch main
Real-World Scenario: Setting Up a Clean Repository
Let’s walk through initializing a new project and configuring it with standard settings before recording the first commit.
Step 1: Create the Project Directory and Initialize Git
$ mkdir team-portal && cd team-portal
$ git init --initial-branch=main
Initialized empty Git repository in /home/admin/Code/team-portal/.git/
Step 2: Establish Git Configurations
Verify your local user configurations to ensure commits match your team identity:
$ git config --local user.name "Alex Developer"
$ git config --local user.email "alex@portalproject.com"
Step 3: Define Ignore Rules
Create a .gitignore file to prevent tracking temporary files or system caches:
$ echo "node_modules/" > .gitignore
$ echo ".DS_Store" >> .gitignore
$ echo "*.log" >> .gitignore
Step 4: Write Initial Code and Record the First Commit
Create a file, stage it, and record the commit:
$ echo "<h1>Team Portal</h1>" > index.html
$ git add .
$ git commit -m "chore: initial repository layout"
[main (root-commit) f23c92e] chore: initial repository layout
2 files changed, 4 insertions(+)
create mode 100644 .gitignore
create mode 100644 index.html
Let’s look inside .git/refs/heads/main now that we have recorded a commit:
$ cat .git/refs/heads/main
f23c92e10db526ab1a9db3f28249a02ce5c144e1
The unborn branch state has resolved. In this SHA-1/files-backend example, refs/heads/main points to the illustrative commit ID shown above; exact object IDs vary with repository contents and commit metadata.
Common Pitfalls and Mistakes
1. Accidental Nested Repositories
The Mistake: Running git init inside a subdirectory of a folder that is already tracked by a Git repository.
/my-project/ (.git/ exists)
└── /src/
└── /components/ (runs git init here)
Why it’s a problem: The subdirectory becomes a separate repository. The parent usually sees it as an untracked directory (unless it is ignored); it does not automatically absorb the inner repository’s history. A submodule requires explicit configuration. The Fix: Check which repository contains the current directory before initializing:
# This prints the root of the current repository, if there is one.
$ git rev-parse --show-toplevel
If you created the nested repository by mistake, removing its .git/ directory turns its files into ordinary files in the parent working tree, but permanently removes the nested repository’s history and metadata. Verify the exact path before deleting it:
$ rm -rf path/to/nested-project/.git
2. Initializing in Your System’s Home Directory
The Mistake: Running git init in your terminal’s default path (e.g., C:\Users\Username\ or /home/username/) by accident.
Why it’s a problem: Git will attempt to track every file on your computer, including desktop files, downloads, applications, and system caches. This slows down your terminal and leads to commit conflicts.
The Fix: Locate and delete the accidental .git folder in your home directory:
# Navigate to home and delete the hidden .git directory
$ cd ~
$ rm -rf .git
(Caution: Double-check that you are in your home directory before running rm -rf .git to avoid deleting a valid project history.)
3. Manually Editing Database Objects
The Mistake: Attempting to manually modify, rename, or write files inside .git/objects/ or .git/refs/ to fix a repository issue.
Why it’s a problem: Git’s object database relies on exact cryptographic hashing. Modifying even a single character in an object file will corrupt the hash, making the repository unreadable.
The Fix: Use Git’s command-line API to interact with repository contents rather than editing the files in .git/ directly.
Command Quick Reference
| Command | Action | Common Context |
|---|---|---|
git init | Initializes standard Git repository | Run once at project root |
git init --bare | Initializes repository without working directory | Remote servers / shared hubs |
git init -b <name> | Specifies custom default branch name | Replaces legacy master branch naming |
git init --template=<dir> | Initializes repo with custom hook templates | Standardizes team hooks |
rm -rf .git | Un-tracks project, deleting all local history | Warning: Destructive and irreversible |
FAQ (People Also Ask)
What does git init do?
git init turns the current directory into a Git repository by creating a .git/ subdirectory. That directory holds the object database, the branch references, and the local configuration. It does not create a commit, does not track any file yet, and does not contact any server. You still need git add and git commit before anything is recorded in history.
Does git init upload my code to GitHub?
No. git init is a local command that operates entirely on your computer’s storage. It initializes a local version database in your directory but does not connect to the internet or link to external hosts. To upload your code to GitHub, you must create a remote repository on GitHub, link it locally using git remote add, and push your commits.
How do I undo git init?
To remove Git tracking from a project, delete the hidden .git/ folder. This removes all commit history, branches, configuration settings, and stashes. Your working files will remain intact on your disk but will no longer be tracked:
$ rm -rf .git
What is the difference between a standard and bare Git repository?
A standard Git repository contains a .git/ folder alongside a working copy of your files, allowing you to edit and commit changes locally. A bare repository contains only the Git database files directly in its root (no .git/ folder) and has no working directory. Bare repositories are used on remote servers to store pushed commits safely.
Why is the .git folder hidden by default?
The .git/ directory is hidden by default to prevent accidental modification, moving, or deletion of its contents. Since all version history is stored in this folder, deleting it deletes the repository’s entire history.
Continue learning
Now that the repository exists, follow the objects and refs it created:
- Git branches — create, switch, and inspect branch refs.
- git merge — combine branch histories with fast-forward and three-way merges.
- Git objects — see the blobs, trees, and commits written by your first commit.
- Git refs — understand
HEAD,refs/heads/, tags, and packed refs. - Packfiles — learn how Git compresses objects for storage and transfer.
Test Your Knowledge
Loading quiz…