The three trees: working, staging, repo
Understand the three zones Git uses to track your work — and why a separate staging step gives you precise control over every commit.
What you'll learn
- What the working directory, staging area, and repository each store
- How git add and git commit move changes between those zones
- Why staging lets you craft clean, focused commits instead of all-or-nothing snapshots
Before you start
The core mental model
Every file in a Git project lives in exactly one of three zones at any moment. Think of them as three distinct containers — not folders you can open in Finder, but states of knowledge that Git maintains.
Working Directory — your real files, exactly as they exist on disk right now. When you open a file in your editor and type something, you are changing the working directory. Git can see these changes, but it has not recorded them anywhere yet.
Staging Area (also called the index) — a holding zone where you compose the next snapshot. Nothing is permanent here; it is a proposed commit waiting for your approval. You populate it deliberately, one file (or one hunk) at a time.
Repository (the .git directory) — the permanent, compressed history of every commit you have ever made. Once a snapshot lands here, it is safe and retrievable forever, even if you delete the file from your working directory.
Visualizing the flow
Walking through the flow
1. Edit a file (working directory changes)
Open README.md and add a line. From Git’s perspective the file is now modified — changed on disk relative to what was last committed — but Git has not been asked to record anything.
2. Stage the change (git add)
git add README.md
Git takes a snapshot of README.md as it is right now and places that snapshot in the staging area. The working directory still has your edits; the staging area now also knows about them.
3. Commit the snapshot (git commit)
git commit -m "Add project overview to README"
Git wraps everything in the staging area into a permanent commit object, writes it to the repository, and clears the staging area. The working directory is unchanged.
Reading the three zones with git status
git status is your live map of which zone each file is in. Learn to read it fluently.
Scenario A — a brand new file that has never been added:
git status
On branch main
Untracked files:
(use "git add <file>..." to include in what will be committed)
notes.txt
nothing added to commit but untracked files present
notes.txt exists in the working directory but is invisible to the staging area and repository.
Scenario B — an existing file edited but not yet staged:
git status
On branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
modified: README.md
no changes added to commit
Scenario C — after git add README.md:
git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
“Changes to be committed” means the file is in the staging area, ready for git commit.
Why does the staging area exist?
This is the question most beginners never ask — and the answer is the whole point.
Imagine you spent an afternoon making two unrelated changes: you fixed a bug in auth.py and added a new feature in dashboard.py. Without a staging area you would have to commit both together, muddying your history. With the staging area you can do this:
git add auth.py
git commit -m "Fix login redirect bug"
git add dashboard.py
git commit -m "Add user dashboard page"
Two clean, focused commits from one editing session. The staging area is a curation tool — it lets you decide exactly what story your history tells, independently of the order you actually wrote the code.
A quick note on git init
When you run git init in a folder, Git creates a hidden .git directory. That directory is the repository — it holds the index (staging area) and all committed history. The files outside .git are your working directory. Everything flows from that one git init command.
Summary
| Zone | What it holds | How you move changes in |
|---|---|---|
| Working Directory | Your current files on disk | Edit in your editor |
| Staging Area / Index | The proposed next commit | git add |
| Repository (.git) | Permanent committed history | git commit |
The command git status shows you which zone each changed file is in at any moment. Reading it carefully is 80 percent of understanding Git.