Skip to content
ExponaBLOG
GIT & GITHUB FOR PROFESSIONAL DEVELOPERS · DAY 004 / 100

The three areas: working tree, staging, repository explained

Understand where your changes live.

Expona Admin7 min read

Why understanding Git's three areas matters

Git can feel like magic until something goes wrong. You've modified a file, staged something you didn't mean to, or committed work that wasn't ready. The confusion usually stems from not having a clear mental model of where your changes actually live. Understanding the three areas: working tree, staging, repository explained will change how you work with Git forever—it transforms Git from a black box into a predictable tool you control.

Today, we're going to map out exactly where your code lives at every step of the workflow, and show you how git status reveals all three areas in real time.

Working tree: your files right now

The working tree is the directory on your machine where you actually do work. It's the files you see in your editor, the ones you're modifying, deleting, and creating. When you write code, you're writing to the working tree.

Here's the key: nothing in the working tree is tracked by Git until you tell it to be. You could have 50 files changed, and none of them matter to Git's history until you explicitly stage them.

Let's walk through a real scenario. You're working on a user authentication feature:

bash
$ touch auth.ts
$ echo "export function login(email: string) {" >> auth.ts
$ echo "  // implementation" >> auth.ts
$ echo "}" >> auth.ts

You've created a new file and modified it. It exists in your working tree, but Git doesn't know it's supposed to be part of your project history yet. The working tree is transient—it's your sandbox. You can delete a file, rewrite it entirely, or experiment freely. Once you move to the next area, things become permanent.

This is why git status shows files as "Untracked" when they're only in the working tree. Git is saying: "I see this file exists, but you haven't told me it matters."

Staging area: what goes into the next commit

The staging area (also called the index) is where you curate what will be in your next commit. It sits between your working tree and your repository history. Think of it as a commit preparation zone.

This is where professional developers spend mental effort. You don't commit everything you've changed—you stage the logical, coherent chunks that belong together. This is discipline.

Using our auth example, let's stage the file:

bash
$ git add auth.ts
$ git status

Now git status shows the file under "Changes to be committed" in green. The file hasn't been committed yet, but Git knows you intend to commit it. This is the staging area at work.

Why separate staging from committing? Because real work often involves multiple files, and you need to decide which ones belong in this commit and which belong in a future one. You might modify both auth.ts and config.ts, but only want to commit the auth changes right now.

bash
$ git add auth.ts
$ # Don't add config.ts yet
$ git status

Now your staging area contains only auth.ts. The config.ts changes remain in your working tree, untracked. When you commit, only staged changes go into the repository:

bash
$ git commit -m "Add login function to auth module"

After this commit, config.ts is still in your working tree, waiting for you to decide what to do with it.

This is crucial for writing good commit history. Each commit represents a logical unit of work. The staging area is how you enforce that discipline. Senior developers use git add -p (patch mode) to stage even smaller chunks—individual hunks of code within a single file—to make commits even more granular.

Repository: your committed history

The repository is your permanent record. Every commit you've ever made lives here. When you run git log, you're reading from the repository. When you push to GitHub, you're uploading your repository. It's immutable by design.

Continuing our example, after the commit above, the repository now contains one commit with auth.ts. You can verify this:

bash
$ git log --oneline
a1b2c3d Add login function to auth module

$ git show a1b2c3d

That commit is now part of your repository's permanent history. It's safe. Other developers can pull it. It's on GitHub. It's the single source of truth for what was decided and completed.

The repository is also what your teammates see. When they clone your project, they get the entire repository—all the commits, all the history. The working tree and staging area are local to your machine. Only the repository is shared.

This distinction is important: your work in the working tree and staging area is private until you push the repository to a remote server. You can experiment, stage, even commit locally without anyone seeing it. The moment you push, your repository history becomes part of the team's shared understanding.

How git status reveals all three areas

Now let's tie this together with a real-world workflow and watch git status tell the story of all three areas:

bash
$ # Starting state: everything committed
$ git status
On branch main
nothing to commit, working tree clean

All three areas are in sync. No changes anywhere.

bash
$ # You modify a tracked file (in the repository)
$ echo "console.log('debug');" >> auth.ts
$ git status
On branch main
Changes not staged for commit:
  (use "git add <file>..." to stage changes)
        modified:   auth.ts

Now git status shows that auth.ts is in the working tree but not in the staging area. The repository still has the old version.

bash
$ # You create a new file
$ touch logger.ts
$ echo "export function log(msg: string) {}" >> logger.ts
$ git status
On branch main
Changes not staged for commit:
  modified:   auth.ts
Untracked files:
  logger.ts

Two things are in the working tree now: a modification to an existing file and a completely new file. Neither is staged.

bash
$ # Stage the modification, but not the new file
$ git add auth.ts
$ git status
On branch main
Changes to be committed:
  modified:   auth.ts
Untracked files:
  logger.ts

Now the staging area has auth.ts. The repository doesn't yet. logger.ts is still untracked in the working tree.

bash
$ # Commit what's staged
$ git commit -m "Add debug logging to auth"
$ git status
On branch main
Untracked files:
  logger.ts

After commit, auth.ts has moved from the staging area into the repository. logger.ts is still untracked in the working tree.

bash
$ # Stage the new file
$ git add logger.ts
$ git status
On branch main
Changes to be committed:
  new file:   logger.ts

Now it's in the staging area. Ready to commit.

bash
$ # Commit it
$ git commit -m "Add logger utility"
$ git status
On branch main
nothing to commit, working tree clean

All three areas are in sync again. This is the cycle: working tree → staging area → repository.

Common mistakes

Confusing "untracked" with "unstaged". A file can be untracked (Git has never seen it) or unstaged (Git knows about it, but the current changes aren't staged). These are different. Untracked files show under "Untracked files" in git status. Unstaged changes show under "Changes not staged for commit."

Staging everything without thinking. Running git add . stages everything in your working tree. This is fine if your working tree only contains work that belongs in one commit, but in a long session with multiple features in progress, this violates the discipline of logical commits. Use git add -p to be intentional.

Forgetting that the staging area is temporary. Junior developers sometimes think staging is permanent. It's not. Your staging area resets every time you commit. What persists is the repository. Don't rely on the staging area as backup or memory.

Not understanding that local repositories are private. You can commit locally and no one sees it. This is powerful for experimentation, but it also means commits don't matter until they're pushed. Some teams have policies around this—don't go days without pushing, for example.

Key takeaways

  • The working tree is your live directory—files you're actively editing. Changes here are invisible to Git history until staged.
  • The staging area is your commit preparation zone. You explicitly choose what changes go into the next commit, enabling logical, focused commits.
  • The repository is your permanent, shared history. Every commit is immutable and part of the record.
  • git status always shows you what's in each area and how to move things between them.
  • Professional workflows treat staging as a place for discipline—curating commits, not just dumping changes.
  • Understanding these three areas is the foundation for every other Git concept you'll learn: branching, rebasing, merging, and conflict resolution all depend on this model.
ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles