Unlock Git’s Secrets: Inside the .git Directory and Commit Mechanics
This article explains how Git stores repository data by exploring the .git folder structure, the composition of a commit, object storage, and the role of branches, tags, and HEAD, providing concrete examples and command snippets to demystify Git’s inner workings.
.git Directory Overview
Running git init creates a .git folder that stores all metadata required by Git. After the first commit the directory typically looks like:
├── HEAD
├── branches
├── config
├── description
├── hooks
│ ├── pre-commit.sample
│ ├── pre-push.sample
│ └── ...
├── info
│ └── exclude
├── objects
│ ├── info
│ └── pack
└── refs
├── heads
└── tagsHEAD – points to the current branch reference.
config – repository settings (remotes, user name, email) manipulated with git config.
description – optional text shown by gitweb.
hooks – executable scripts that Git runs at defined points (e.g., pre‑push).
info – contains the .gitignore patterns for files that should not be tracked.
What a Commit Contains
A commit is not merely a snapshot of the working tree; it is a Git object that records four pieces of information:
Tree hash – the root of a tree object that recursively references all blobs (file contents) and sub‑trees.
Commit message.
Committer and author metadata (name, email, timestamp).
Parent commit hash (absent for the initial commit).
When you create a commit Git performs two steps:
If a file has not changed, Git re‑uses the existing blob object identified by its hash.
If a file changed, Git compresses the new content, stores it as a new blob object, and records the new hash in the tree.
Example objects layout after adding a file 1.txt and committing:
├── 4c
│ └── f44f1e3fe4fb7f8aa42138c324f63f5ac85828
├── 86
│ └── 550c31847e518e1927f95991c949fc14efc711
├── e6
│ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
├── info // ignored by Git internals
└── pack // ignored by Git internalsThe first two hexadecimal characters of a blob’s SHA‑1 hash become the sub‑directory name (e.g., 4c), keeping the number of directories under 256.
Inspecting a Commit
You can view the raw commit object with: git cat-file -p <commit‑hash> Typical output (first commit) looks like:
tree 86550c31847e518e1927f95991c949fc14efc711
author Example Author <[email protected]> 1455775173 -0500
committer Example Author <[email protected]> 1455775173 -0500
Initial commitThe tree line points to a tree object that lists the blobs included in the commit. To see the blob for file_1.txt:
git cat-file -p 86550c31847e518e1927f95991c949fc14efc711
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 file_1.txtBranches, Tags, and HEAD
Both branches and tags are simple references that store a commit hash. The HEAD file contains a symbolic reference to the current branch:
cat HEAD
ref: refs/heads/master
cat refs/heads/master
4cf44f1e3fe4fb7f8aa42138c324f63f5ac85828Deleting a branch or tag removes only the reference; the underlying commit objects remain in objects and can still be reached with low‑level commands.
Further Reading
For a complete description of the index file format and other low‑level details, see the official documentation at:
https://github.com/git/git/blob/master/Documentation/technical/index-format.txt
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
