# How Git Works Internally: Building a Mental Model 🧠

Most developers learn Git by memorizing commands like `git add` and `git commit`.  
But Git becomes *much easier* once you understand **what’s happening under the hood**.

In this article, we’ll explore:

* What the `.git` folder really is
    
* How Git stores data internally
    
* Git objects: **Blob, Tree, Commit**
    
* What actually happens during `git add` and `git commit`
    
* How Git uses hashes to protect your data
    

No advanced math, no magic — just clear concepts.

---

## Why Understanding Git Internals Matters

When you understand Git internally:

* You stop guessing and start reasoning
    
* Commands make logical sense
    
* Debugging Git issues becomes easier
    
* You rely less on memorization
    

Think of this as learning **how Git thinks**.

---

## What Is the `.git` Folder?

When you run:

```plaintext
git init
```

Git creates a hidden folder called:

```plaintext
.git/
```

This folder is the **heart of Git**.

### Important Rule

👉 **Your project is not a Git repository because of Git commands —  
it’s a repository because the** `.git` folder exists.

Delete `.git`, and Git forgets everything.

---

## What’s Inside the `.git` Folder?

![https://humbletoolsmith.com/img/posts/a-look-inside-the-_git-folder/Git%20Folder%20Internals.png](https://humbletoolsmith.com/img/posts/a-look-inside-the-_git-folder/Git%20Folder%20Internals.png align="left")

![https://git-scm.com/book/en/v2/images/data-model-3.png](https://git-scm.com/book/en/v2/images/data-model-3.png align="left")

A simplified view:

```plaintext
.git/
├── objects/
├── refs/
├── HEAD
├── index
├── config
```

Let’s focus on the most important parts.

---

### 1\. `objects/` – Where Git Stores Everything

This is Git’s **database**.

* Every file
    
* Every folder
    
* Every commit
    

All are stored here as **objects**.

---

### 2\. `HEAD` – Where You Are Right Now

`HEAD` points to:

* The current branch
    
* The latest commit on that branch
    

Think of it as:

> “You are here 📍”

---

### 3\. `index` – The Staging Area

The `index` file represents:

* What will go into the **next commit**
    

This is why staging exists.

---

## Git Objects: The Building Blocks 🧱

Git stores data using **four object types**, but three are core:

1. **Blob**
    
2. **Tree**
    
3. **Commit**
    

Let’s break them down.

---

## 1\. Blob (File Content)

A **blob** stores:

* File content only
    
* No filename
    
* No directory info
    

Example:

```plaintext
"Hello Git"
```

That text becomes a **blob object**.

💡 If two files have the same content → Git stores **only one blob**.

---

## 2\. Tree (Folder Structure)

A **tree** represents:

* A directory
    
* Filenames
    
* File permissions
    
* Links to blobs or other trees
    

Think of a tree as:

> A folder pointing to files and subfolders

---

## 3\. Commit (Snapshot + Metadata)

A **commit** stores:

* A reference to a **tree**
    
* Parent commit(s)
    
* Author info
    
* Timestamp
    
* Commit message
    

A commit does **not** store files directly.

---

## Relationship Between Commit, Tree, and Blob

![https://julianogtz.github.io/my-personal-blog/static/ef7bc30d35466f4037e9fd821d6e7efe/5a190/git-database-flow.png](https://julianogtz.github.io/my-personal-blog/static/ef7bc30d35466f4037e9fd821d6e7efe/5a190/git-database-flow.png align="left")

![https://hamwaves.com/collaboration/doc/rypress.com/images/12-4.png](https://hamwaves.com/collaboration/doc/rypress.com/images/12-4.png align="left")

```plaintext
Commit
  ↓
 Tree
  ↓
Blobs (file contents)
```

This structure makes Git fast, efficient, and reliable.

---

## How Git Tracks Changes (Not Diffs!)

Here’s a key idea:

🚫 Git does **not** primarily store diffs  
✅ Git stores **snapshots**

Each commit:

* Points to a full snapshot of the project
    
* Reuses unchanged objects from previous commits
    

That’s why Git is fast and space-efficient.

---

## What Happens Internally During `git add`?

![https://miro.medium.com/v2/resize%3Afit%3A1400/1%2Au5kWY00Tshc76QCPOjPufA.png](https://miro.medium.com/v2/resize%3Afit%3A1400/1%2Au5kWY00Tshc76QCPOjPufA.png align="left")

![https://miro.medium.com/v2/resize%3Afit%3A1400/1%2AMLeAPktNiNWa1FnkE5-h1w.png](https://miro.medium.com/v2/resize%3Afit%3A1400/1%2AMLeAPktNiNWa1FnkE5-h1w.png align="left")

When you run:

```plaintext
git add file.txt
```

Git does the following:

1. Reads file content
    
2. Creates a **blob object**
    
3. Stores it in `.git/objects`
    
4. Updates the **index (staging area)**
    

👉 No commit yet  
👉 Just preparation

---

## What Happens Internally During `git commit`?

![https://miro.medium.com/1%2ALa9tFzHMf2OIhzyhIcs20Q.png](https://miro.medium.com/1%2ALa9tFzHMf2OIhzyhIcs20Q.png align="left")

![https://miro.medium.com/v2/1%2Al3ajqm6cHXkRpTVUlkiXSw.gif](https://miro.medium.com/v2/1%2Al3ajqm6cHXkRpTVUlkiXSw.gif align="left")

When you run:

```plaintext
git commit -m "Add file"
```

Git:

1. Reads the staging area (`index`)
    
2. Creates a **tree object**
    
3. Creates a **commit object**
    
4. Moves `HEAD` to the new commit
    

🎉 Your snapshot is now permanent.

---

## How Git Uses Hashes (Integrity & Safety)

Every Git object is identified by a **SHA-1 hash**.

Example:

```plaintext
e83c5163316f89bfbde7d9ab23ca2e25604af290
```

This hash is based on:

* Object content
    
* Object type
    

### Why This Matters

* Change the content → hash changes
    
* Corruption is instantly detectable
    
* History cannot be silently altered
    

Git is **self-verifying by design**.

---

## The Mental Model to Remember 🧠

Instead of memorizing commands, remember this:

* Git stores **objects**
    
* Objects are connected by **hashes**
    
* Commits point to trees
    
* Trees point to blobs
    
* `git add` prepares
    
* `git commit` records
    

Once this clicks, Git feels logical — not magical.
