← all lessons
Foundations · lesson 4 of 18

The Three States

Working Directory, Staging, Repository

Why it matters

Git has three states for your files. Understanding this model is the key to knowing what each command does and why.

Key concepts

The idea

The Shipping Analogy

Think of Git as a shipping warehouse:

1. Working Directory (Your Desk) Where you do actual work. Files here can be modified freely. Git doesn’t care about changes until you stage them.

2. Staging Area (The Loading Dock) Items you’ve decided to ship. You’re selecting which boxes go on the truck. You can add/remove items before the truck leaves.

3. Repository (The Warehouse Archive) Once committed, items are archived permanently. Can’t be changed, only added to.

flowchart TD
    work["Working Directory: edit files"]
    stage["Staging Area (Index)"]
    repo["Repository (.git/)"]
    work -->|git add| stage
    stage -->|git commit| repo
    stage -->|unstage| work

Why Two Steps?

The staging area lets you craft precise commits. Changed 10 files but only want to commit 3? Stage just those 3. This creates cleaner, more meaningful history.

Walkthrough

File States

flowchart TD
    working["Working Directory: untracked, modified, unchanged files"]
    staged["Staging Area (Index): selected changes"]
    committed["Repository (.git/): committed snapshot"]
    working -->|git add selected changes| staged
    staged -->|git commit| committed

Commands for Each Transition

# Working → Staging
git add <file>              # Stage specific file
git add .                   # Stage all changes
git add -p                  # Stage parts of files (interactive)

# Staging → Working (unstage)
git restore --staged <file> # Remove from staging
git reset HEAD <file>       # Alternative (older style)

# Working → Discard
git restore <file>          # Discard working changes
git checkout -- <file>      # Alternative (older style)

# Staging → Repository
git commit -m "message"     # Commit staged changes

Git Objects (What’s in .git/)

Git stores four types of objects:

ObjectPurpose
blobFile contents (compressed)
treeDirectory listing (pointers to blobs)
commitSnapshot + metadata + parent pointer
tagNamed pointer to a commit

Key takeaways

Dos & don’ts

✅ DO

❌ DON’T

Going deeper

Content-Addressable Storage: Git is a content-addressable filesystem. Files are stored by their SHA-1 hash. If two files have identical content, they’re stored once. This makes Git space-efficient.

Plumbing vs Porcelain: Git has low-level “plumbing” commands (hash-object, cat-file, update-index) and high-level “porcelain” commands (add, commit, status). You use porcelain; Git uses plumbing internally.

Common mistakes

Confusing staged and committed: Staged ≠ saved. If you git add but don’t git commit, your changes aren’t in history yet. git status shows the difference.

Editing staged files: If you git add file.txt then edit file.txt again, the new edits are NOT staged. You need to git add file.txt again to stage the latest version.