Skip to main content

Command Palette

Search for a command to run...

How git works

Published
4 min readView as Markdown

How Git Works Internally: Understanding the

.git

Folder and Git Objects

Most developers learn Git by memorizing commands — git add, git commit, git push, etc. But once something goes wrong, confusion hits. The real power of Git reveals itself when you understand how it works internally, especially what lives inside the mysterious .git folder.

This post will help you build a mental model of Git’s internals without drowning in implementation details.


1. What Exactly Is the

.git

Folder?

When you run git init, Git creates a hidden folder named .git in your project directory.

That folder is the repository.

Your working directory (the visible project files) is just a view of the repo.

The .git directory stores everything Git needs, including:

✔ Your commit history

✔ Branches & tags

✔ Objects (blobs, trees, commits)

✔ Staging area info

✔ Configuration & HEAD reference

If you delete .git, the entire repo is gone.

🗂 High-level structure of

.git

.git/
 ├── HEAD
 ├── config
 ├── description
 ├── hooks/
 ├── info/
 ├── objects/
 ├── refs/
 │   ├── heads/
 │   ├── tags/
 └── index

You don’t need to remember every file — just understand that this folder = Git’s brain.


2. Git Is Not a Diff-Based System — It’s a Snapshot System

A common misconception is:

“Git stores diffs between files.”

Nope.

Git stores snapshots of your files, and only new snapshots when content actually changes.

This is important because Git achieves:

✔ Speed

✔ Integrity

✔ Efficient storage


3. Git Objects: The Real Building Blocks

Git stores data inside .git/objects/ as objects, identified by a SHA-1 hash.

There are four object types:

ObjectMeaning
blobFile contents
treeDirectory structure (like a folder)
commitA snapshot + metadata
tagHuman-friendly labels for commits

Let’s break down the main three:


3.1 Blob — represents file content

A blob stores file data and nothing else (no filename, no permissions).

For example, two identical files = one blob.

Blob: "console.log('Hello')"
Hash: e.g. a1b2c3...

3.2 Tree — represents directories

A tree stores:

✔ filenames

✔ pointers to blobs or subtrees

✔ file permissions

Example tree structure:

tree (root)
 ├── file1.js → blob hash
 └── src/
      └── index.js → blob hash

3.3 Commit — represents a snapshot

A commit stores:

✔ root tree hash

✔ parent commit(s)

✔ author info

✔ message

✔ timestamp

Example (conceptual):

commit
 ├── tree: 9ad12f...
 ├── parent: 7db32e...
 ├── author: Satyam
 └── message: "Initial commit"

4. How Git Tracks Changes (Internally)

Git has three main areas:

┌─────────────┬───────────────┬────────────┐
│ Working Dir │ Staging Area  │ Repository │
└─────────────┴───────────────┴────────────┘
      |             |                 |
   your files      index           .git/objects

Workflow:

  1. Edit files → working directory

  2. git add → staging area (index)

  3. git commit → repository (objects)


5. What Happens During

git add

?

When you run:

git add file.txt

Git does two things:

(A) Create a blob object

Stores the content of file.txt in .git/objects/ and names it with its hash.

(B) Update the index file

Adds an entry mapping:

filename → blob hash

But no commit is created yet.

So git add prepares data.

Internal flow:

Working Directory → Blob (object)
Blob hash → Index (staging)

6. What Happens During git commit?

When you commit, Git:

  1. Reads staged blobs from index

  2. Creates tree objects

  3. Creates a commit object pointing to that tree

  4. Updates the branch reference

Internal flow:

Index → Tree → Commit → refs/heads/master

If this commit has a parent, Git stores that link too.


7. Git Uses Hashes for Integrity

Git generates a unique SHA-1 hash from object contents.

This means:

✔ If you change a file → hash changes

✔ Impossible to modify history unnoticed

✔ Corruption is detectable

This is why Git provides content-addressable storage.

8. Visual Model of Git Objects (Diagram)

Commit graph (ASCII view):

Commit C (hash: c3)
  |
  └── Tree T3
        ├── file1 → blob b1
        └── file2 → blob b2
  |
Parent → Commit B (hash: b2)
              |
              └── Tree T2 ...

You can create a UI diagram like this for the article.


9. The

HEAD

File and Branches

HEAD tells Git where you currently are, e.g.:

ref: refs/heads/main

Branches are just text files pointing to commit hashes:

refs/heads/main → c3f9a1...

Lightweight and cheap.


10. Why This Mental Model Helps

With this understanding, confusing scenarios make sense:

✔ Why two files with same contents don’t increase repo size

✔ Why Git checkout is fast → just switches commit trees

✔ Why rebasing changes commit hashes → new commit objects

✔ Why history integrity is guaranteed via hashes


Conclusion

Git isn’t magic — it’s a simple system of:

✔ Blobs for file contents

✔ Trees for folders

✔ Commits for snapshots

✔ Hashes for integrity