Skip to main content
ANVISoftware Solutions
Lesson 4 of 15Beginner14 min

The Staging Area

By the end of this lesson

Choose exactly what goes into the next commit.

Most tools that save versions have one step: save. Git has two, and the extra step confuses nearly everyone at first. You edit files, then you add them, then you commit.

The reason is that the thing you are recording and the thing you are working on are not always the same. The staging area is where you assemble the commit you want, while your working directory holds whatever mess you happen to be in.

Three places a version of your file can exist at the same time:

Working directory
What is on disk right now. Everything you have typed since your last commit lives here, finished or not.
Staging area
The draft of your next commit. You put changes here on purpose. Git also calls it the index, and the two words mean the same thing.
Repository
The committed history in .git. Once a change reaches here it has an identifier, a message, and a permanent place in the chain.

git add copies the current state of a change from the working directory into the staging area. git commit takes everything in the staging area and writes it into the repository.

One consequence catches people out: git add captures the file as it was at that moment. Edit the file again afterwards and you now have three different versions in play — the committed one, the staged one, and the one on disk. git status will show the same file as both staged and modified, which is accurate rather than broken.

Seeing and controlling what is staged
Shell
# Overview: staged on one list, unstaged on another
git status

# What have I changed but not staged?
git diff

# What exactly am I about to commit?
git diff --staged

# Stage one file, or one folder
git add src/PayrollReport.cs
git add src/reports/

# Take something back out of the staging area, keeping your edits
git restore --staged src/PayrollReport.cs
  • git diff with no arguments compares your working directory against the staging area. It shows what you have not staged yet.
  • git diff --staged compares the staging area against the last commit. This is the review of your commit before you make it, and it is the most useful habit in this lesson.
  • git restore --staged removes a change from the draft commit without touching your file. Nothing you typed is lost; the change goes back to being unstaged.

Sometimes the unrelated changes are inside the same file. A single class might contain both the bug fix and the variable rename. Staging the file would take both.

For this, git add has an interactive mode. It breaks the file's changes into chunks and asks you about each one: include this, skip it, or split it into smaller pieces. You answer a few single-letter prompts and end up with a partially staged file — one part in the draft commit, the rest still waiting in your working directory.

Staging part of a file
Shell
# Walk through each chunk of change and decide
git add -p src/PayrollReport.cs

# Confirm what the commit will actually contain
git diff --staged

git commit -m "Format payroll dates using the report locale"

# The rest of your edits are still here, unstaged
git status
  • -p is short for patch. Git shows one chunk of change at a time and waits for an answer: y to stage it, n to skip it, s to split it into smaller chunks, q to stop.
  • You are not editing your file. You are choosing which parts of it enter the draft commit, and the file on disk stays exactly as you left it.
  • Reviewing chunk by chunk has a second benefit that has nothing to do with tidy commits: it is a forced reread of your own work, and it is where you notice the debugging line you meant to delete.

Summary

  • A change moves through three places: working directory, staging area, repository
  • git add copies a change into the staging area as it is at that moment; git commit writes the staging area into history
  • Staging exists so one logical change can be committed out of a working directory holding several
  • git add -p stages selected chunks of a file, leaving the rest unstaged
  • git diff shows what is unstaged; git diff --staged shows what your commit will contain

Practice

Attempt each one before opening the solution. Getting it wrong first is how the idea sticks.

Try it yourself

Two changes, two commits, one file each

In a practice repository, edit two different files. Stage only the first, run git diff --staged to confirm the second is absent, then commit.

Now run git status. Your second change should still be sitting there, unstaged and untouched. Commit it separately.

Show solution

The first commit contains one file because that is the only thing you staged. The second change was never part of the draft, so committing did not affect it.

This is the mechanism behind every recommendation about small commits. You are not asked to work in a tidy order — you are given a way to record work in a tidy order afterwards.

Shell
git add src/TaxRates.cs
git diff --staged
git commit -m "Apply the reduced VAT rate to registered charities"

git status
git add docs/tax-notes.md
git commit -m "Note which VAT rates apply to charity customers"

Think about it

Think about it

You stage a file, then edit it again, then commit. Which version of the file ends up in the commit, and why?

Show solution

The staged version — the one captured when you ran git add. Your later edit was never added to the draft, so it stays in the working directory as an uncommitted change.

This is the clearest evidence that the staging area is a real, separate store rather than a list of file names. It holds content, frozen at the moment you staged it.

Knowledge check

Nothing is recorded and there is no score. The explanation appears either way.

What does the staging area let you do that committing everything at once does not?
You run git diff and see nothing, but git status shows changes. What is the likely explanation?

Saved in this browser only.