Inside Git: .git Folder Demystified
The .git folder is essentially a generic key-value content-addressable database. It is created when a git repository is initialized using git init command.
Here is a complete breakdown of the .git folder.
The Root Level Files
These files sit directly inside .git folder and manage the state of the current working tree.
HEAD: This text file contains a reference to the current branch we are on.
It’s content usually looks like:
ref: refs/heads/mainconfig: This text file contains our local configuration. It stores the URL of our remote (origin), our user details (set locally), and branch tracking information
index: This is the staging area. This is the binary file which stores a sorted list of all files in our working directory. their permissions and the SHA1 hash of their content. Upon running
git add, we are updating this file.
The objects / Directory (The Database)
Every file, every directory structure and every commit is stored here. Git is a content-addressable filesystem, i.e. it names file based on the SHA-1 hash of their contents.
There are four types of objects stored here:
Blob (Binary Large Object)
It is the content of the file. It stores only the data, not the filename.
Ex: if we have 2 files README.md and INTRO.txt which has the exact same test “Hello“, Git stores only one blob.
Tree
It represents a directory. It contains a list of other trees (subdirectories) and blobs (files), mapping names to their SHA-1 hashes.
It helps Git reconstructs your folder structure.
Commit
It is a snapshot of the project at a specific time.
It contains a pointer to the top-level Tree (the root folder); a pointer to the Parent Commit (the previous state); and the Metadata (Author, Committer, timestamp, and message)
Tag
- An annotated tag (like v1.0.2) which points to a commit but includes extra metadata. Usually used alongside releases.
The refs / Directory (The Pointers)
It has the table of contents or the bookmarks.
refs/heads/ : Contains one file per local branch (e.g. main, feature-login). Git creates a new file at refs/heads/new-feature and writes the current commit hash into it.
refs/tags/ : Contains pointers for tags (e.g. v1.0.2)
refs/remotes/ : Contains the state of the branches on the server (e.g. origin/main). It gets updated when we do
git fetch
Other Important Directories
hooks/
This contains shell scripts that trigger automatically before or after Git events. Ex: pre-commit, post-merge
logs/
It contains the Reflog (Reference Logs). Everytime HEAD or a branch tip updates, Git logs it here.
info/
This acts like a local .gitignore file that is not shared with other collaberators. Useful for ignoring personal files like IDE settings.
Workflow
The
git addPhase: Creating Blobs and Updating the Index
When you run git add <filename>, Git does two specific things:
Creates a Blob: Git takes the content of your file, compresses it, and calculates a SHA-1 hash. It then stores this content as a blob object inside the
.git/objectsfolder.Updates the Index: Git updates the
.git/indexfile (the staging area). This file acts as a map, linking your filename to the SHA-1 hash of the blob it just created. At this stage, your changes are tracked, but not yet part of the project history.
The
git commitPhase: Building the Snapshot
When you run git commit -m "message", Git solidifies the staging area into the permanent history:
Creates a Tree: Git creates a tree object that represents the structure of your project at that exact moment. This tree points to the blobs (files) and other trees (subdirectories) listed in the index.
Creates a Commit Object: Git creates a commit object that includes:
A pointer to the main tree object.
Metadata (author, committer, timestamp, and message).
A pointer to the parent commit (the SHA-1 of the previous commit), which is how Git maintains the chain of history.
Moves HEAD: Finally, Git updates the file in
.git/refs/heads/[branch-name]to point to the SHA-1 of this new commit object.
