DEV Community

Mohd Asif Ansari
Mohd Asif Ansari

Posted on

Inside Git: How It Works and the Role of the .git Folder

You know git add and git commit. But what actually happens when you run these commands?

Let's look inside Git and understand how it really works.

The .git Folder: Git's Brain

When you run git init, Git creates a hidden .git folder. This folder is where Git stores everything about your project.

See it:

ls -la    # On Linux/Mac
dir /a    # On Windows
Enter fullscreen mode Exit fullscreen mode

Inside .git

.git/
├── HEAD              # Points to current branch
├── config            # Repository settings
├── objects/          # All your data (commits, files)
├── refs/             # Branch pointers
├── index             # Staging area
└── logs/             # Change history
Enter fullscreen mode Exit fullscreen mode

Most important:

  • objects/: Where Git stores all data
  • refs/: Where branch pointers live
  • HEAD: Shows your current position
  • index: Your staging area

Rule: Never manually edit files in .git. Let Git handle it.

Git Objects: The Three Types

Git stores everything as objects. Three types matter:

1. Blob (File Content)

Stores file content only. No filename, no folders—just content.

Example:
File index.html with content "Hello World" becomes a blob containing just "Hello World".

2. Tree (Directory Structure)

Stores folder structure. Lists files and their locations.

Example:
"This folder has index.html (blob abc123) and style.css (blob def456)."

3. Commit (Snapshot)

Stores project snapshot: which tree, who made it, when, and why.

Example:
"Project looked like this. Author: John. Date: Jan 15. Message: Add homepage."

How They Connect

Commit
  ↓ points to
Tree (folder)
  ↓ contains
Blobs (files)
Enter fullscreen mode Exit fullscreen mode

Real example:

Your project:
├── index.html  ("Hello")
└── style.css   ("body { margin: 0; }")

Git stores:
Commit abc123 → Tree xyz789 → Blob aaa111 ("Hello")
                            → Blob bbb222 ("body { margin: 0; }")
Enter fullscreen mode Exit fullscreen mode

Git Uses Hashes

Every object gets a unique 40-character ID called a hash.

Example:
"Hello World" always creates hash: 980a0d5f19a64b4b30a87d4206aade58726b60e3

Why?

  • Different content = different hash
  • Content changes? Hash changes
  • Git knows immediately if data is corrupted
  • Same content stored only once

What Happens: git add

You run:

git add index.html
Enter fullscreen mode Exit fullscreen mode

Git does:

  1. Reads file content
  2. Creates blob object with hash
  3. Stores blob in .git/objects/
  4. Updates index (staging area)

Result: File is staged, ready to commit.

The file content is now safely stored in Git, but not committed yet.

What Happens: git commit

You run:

git commit -m "Add homepage"
Enter fullscreen mode Exit fullscreen mode

Git does:

  1. Creates tree object from staging area
  2. Creates commit object pointing to tree
  3. Adds metadata: author, date, message, parent commit
  4. Generates commit hash
  5. Updates branch pointer to new commit

Result: Your changes are permanently saved.

How Git Tracks Changes

Common myth: Git stores the differences between versions.

Truth: Git stores complete snapshots.

But doesn't that waste space?

No! Here's why:

  1. Reuses unchanged files: If a file doesn't change, Git points to the old blob
  2. Compression: Git compresses everything
  3. Smart storage: Git packs objects efficiently

Example:

Commit 1:
- index.html (blob aaa)
- style.css (blob bbb)

Commit 2: (only index.html changed)
- index.html (blob ccc) ← new
- style.css (blob bbb) ← reused!
Enter fullscreen mode Exit fullscreen mode

The Staging Area (Index)

The index is a file at .git/index containing your next commit.

Why have staging?

Control. You can:

  • Stage only some files
  • Review before committing
  • Build thoughtful commits

Example:

# Edit two files
echo "New" > file1.txt
echo "More" > file2.txt

# Stage only file1
git add file1.txt

# Commit only file1
git commit -m "Update file1"

# file2 remains uncommitted
Enter fullscreen mode Exit fullscreen mode

HEAD: Your Position

HEAD is a pointer showing where you are.

Location: .git/HEAD

Content:

ref: refs/heads/main
Enter fullscreen mode Exit fullscreen mode

Means: "You're on the main branch."

Switch branches:

git checkout feature
Enter fullscreen mode Exit fullscreen mode

HEAD updates to: ref: refs/heads/feature

Branches Are Just Pointers

A branch is a file containing a commit hash.

Location: .git/refs/heads/main

Content:

f3a8d91c8a7d4e5f6b2c3d4e5f6a7b8c9d0e1f2a
Enter fullscreen mode Exit fullscreen mode

That's it. Just the latest commit hash.

Creating a branch:

git branch feature
Enter fullscreen mode Exit fullscreen mode

Git creates a new file with the current commit hash. Super fast.

Complete Flow

1. Edit file:

echo "Hello" > readme.txt
Enter fullscreen mode Exit fullscreen mode

File in working directory.

2. Stage it:

git add readme.txt
Enter fullscreen mode Exit fullscreen mode

Git creates blob, updates index.

3. Commit:

git commit -m "Add readme"
Enter fullscreen mode Exit fullscreen mode

Git creates tree and commit objects, updates branch pointer.

Visual:

Working Directory
      ↓ (git add)
Staging Area
      ↓ (git commit)  
Repository
      ↓
Branch updated
Enter fullscreen mode Exit fullscreen mode

Try It Yourself

# Create repo
git init test-repo
cd test-repo

# Create file
echo "Test" > file.txt
git add file.txt

# Find the blob hash
git ls-files -s
# Shows: 100644 <hash> 0 file.txt

# View blob content
git cat-file -p <hash>
# Shows: Test

# Commit and explore
git commit -m "First commit"
git log --oneline  # Get commit hash
git cat-file -p <commit-hash>  # View commit object
Enter fullscreen mode Exit fullscreen mode

Key Takeaways

  1. .git stores everything - Your entire history is here
  2. Three objects: blob, tree, commit - Foundation of Git
  3. Hashes identify content - Same content = same hash
  4. Staging prepares commits - Build commits carefully
  5. Branches are pointers - Lightweight and fast
  6. Git stores snapshots - Not differences

Mental Model

Think of Git as a tree:

        C3 (main)
        |
        C2
       /  \
     C1   C1' (feature)
Enter fullscreen mode Exit fullscreen mode
  • Circles = commits
  • Each commit points to a tree
  • Each tree points to blobs
  • Branches = labels on commits

Why This Matters

Understanding internals helps you:

  • Debug problems confidently
  • Use advanced features
  • Recover lost work
  • Explain Git to others
  • Stop fearing Git

Final Thoughts

Git is elegant underneath:

  • Files → blobs
  • Folders → trees
  • Snapshots → commits
  • Labels → branches

Once you see this, Git makes sense.

You're not memorizing commands anymore. You understand what they do.


Resources:

  • Git Book: git-scm.com/book
  • Experiment with git cat-file -p
  • Break things in test repos (best way to learn!)

Top comments (0)