The Staging Area & git diff

Reviewed & published by Brayan K

The staging area is the feature that makes Git commits so clean. By the end of this lesson you'll know how to choose exactly which changes go into each commit, read git status at a glance, and use git diff to see precisely what you're about to commit.

Part of the free Git course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

What You'll Learn

1️⃣ git status — Your Dashboard

git status tells you, at any moment, which changes are staged (ready to commit), which are unstaged, and which files are untracked. Run it constantly — it's the cheapest, safest command in Git. The short form git status -s uses two columns of one-letter codes: column 1 is the staged state, column 2 is the working-tree state.

# git status is your dashboard — run it constantly. It tells you which
# changes are STAGED (ready to commit) and which are still UNSTAGED.

# The full, friendly version
git status

# The short version — two columns of one-letter codes
git status -s
#   X in column 1 = staged change      (will go in the next commit)
#   Y in column 2 = unstaged change    (still only in your working tree)
#   ??            = untracked file      (Git isn't following it yet)

2️⃣ Staging with git add

The staging area is a waiting room. git add copies the current state of a change into it, and your next commit snapshots exactly what's waiting there. In git status -s, a staged change shows its letter in the first column (e.g. M app.js), while an unstaged change shows it in the second ( M styles.css).

# The staging area (a.k.a. the "index") is a waiting room. You decide
# EXACTLY which changes board the next commit by adding them.

# Stage one file
git add app.js

# Stage several files at once
git add app.js styles.css

# Stage EVERYTHING that changed (new, modified — careful, it's broad)
git add .

# After staging, status shows the file under "Changes to be committed"
git status -s

3️⃣ git diff vs git diff --staged

These two diffs answer two different questions. git diff compares your working directory to the index — "what have I changed but not staged yet?" git diff --staged (also written --cached) compares the index to your last commit — "what will my next commit actually contain?" A handy consequence: once you git add a file, plain git diff shows nothing for it, because the change has moved into the index.

# Two diffs, two questions:
#   git diff           -> "What have I changed but NOT staged yet?"
#                         (working directory  vs  the index)
#   git diff --staged  -> "What will my next commit contain?"
#                         (the index  vs  the last commit)

# What's still unstaged
git diff

# What's already staged and ready to commit (--cached is a synonym)
git diff --staged

Your turn. Make a change, look at it unstaged, stage it, then confirm what your next commit will contain. Fill in the three blanks.

# 🎯 YOUR TURN — replace each ___ then run it in your terminal.
# Goal: see the difference between staged and unstaged changes.

echo "new line" >> app.js

# 1) See the change you just made (it is NOT staged yet)
git ___                        # 👉 the diff that shows UNSTAGED changes

# 2) Stage the file
git ___ app.js                 # 👉 the command that stages a file

# 3) Confirm what your next commit will contain
git diff ___                   # 👉 the flag that shows STAGED changes

# ✅ Expected: step 1 shows the "+new line" diff, step 3 shows the same
#    diff now that it's staged, and plain "git diff" is empty after step 2.

4️⃣ git add -p — Stage Part of a File

Sometimes one file holds two unrelated changes. git add -p (patch mode) breaks the file into hunks and asks about each: press y to stage it, n to skip it, s to split a big hunk into smaller pieces. It's the cleanest way to keep each commit focused on a single idea.

# git add -p (patch mode) is a superpower: it splits a file into "hunks"
# and asks you about each one. Stage the bug fix now, leave the unrelated
# debug print for later — two clean commits instead of one messy blob.

git add -p app.js

# For each hunk Git asks "Stage this hunk [y,n,q,a,d,s,e,?]?"
#   y = yes, stage it      n = no, skip it
#   s = split into smaller hunks      q = quit
#   ? = show help for every option

Common Errors (and the fix)

Pro Tips

📋 Quick Reference

CommandPurpose
git statusShow staged, unstaged, and untracked changes
git status -sShort two-column status
git add fileStage a file for the next commit
git add -pStage selected hunks interactively
git diffShow unstaged changes (working vs index)
git diff --stagedShow staged changes (index vs last commit)
git restore --staged fileUnstage a file (keeps your edits)

Mini-Challenge: One Clean Commit

No commands given this time — just the plan. Curate a single focused commit out of a messy working tree, then check your diffs against the expected result in the comments.

# 🎯 MINI-CHALLENGE: build one clean commit from a messy working tree.
# No commands given — just the plan. Run each step in your terminal.
#
# 1. Make two unrelated edits in the same file (e.g. a fix and a typo)
# 2. Run "git status -s" and read the two-column codes
# 3. Use "git add -p" to stage ONLY the fix hunk (answer y), skip the typo (n)
# 4. Run "git diff" and "git diff --staged" — confirm they show different things
# 5. Commit just the staged fix, leaving the typo edit for a second commit
#
# ✅ Expected: "git diff --staged" shows only the fix, and after committing,
#    "git status -s" still lists the typo edit as unstaged ( M).

# your commands here

🎉 Lesson Complete!

Practice quiz

What is the staging area (also called the index)?

  • A backup of your last commit
  • A waiting room where you choose exactly which changes go into the next commit
  • A remote copy of your repo
  • A list of your branches

Answer: A waiting room where you choose exactly which changes go into the next commit. The staging area holds the precise set of changes that your next git commit will snapshot.

Which command moves a modified file into the staging area?

  • git stage file.txt
  • git commit file.txt
  • git add file.txt
  • git push file.txt

Answer: git add file.txt. git add copies the current state of the file into the staging area (index).

By default, what does plain `git diff` show?

  • Staged changes only
  • Changes between two commits
  • Unstaged changes — working directory vs the index
  • Nothing, it needs a file argument

Answer: Unstaged changes — working directory vs the index. git diff with no flags compares your working directory to what is already staged.

Which command shows what is STAGED, i.e. what will go into the next commit?

  • git diff
  • git diff --staged
  • git diff HEAD~1
  • git status -s

Answer: git diff --staged. git diff --staged (a.k.a. --cached) compares the index against the last commit.

What does `git add -p` let you do?

  • Add every file at once
  • Add files matching a pattern
  • Interactively stage individual hunks (parts) of a file
  • Preview the commit message

Answer: Interactively stage individual hunks (parts) of a file. The -p (patch) flag walks you through each change hunk so you can stage some and skip others.

In `git status -s`, what does ' M file.txt' (space then M) mean?

  • The file is staged
  • The file has unstaged modifications in the working tree
  • The file is untracked
  • The file was deleted

Answer: The file has unstaged modifications in the working tree. The second column M means modified-but-not-staged; the leading space means nothing is staged yet.

In `git status -s`, what does 'M file.txt' (M then two spaces) mean?

  • Unstaged change
  • The modification is staged, ready for the next commit
  • Merge conflict
  • Untracked file

Answer: The modification is staged, ready for the next commit. M in the first column means the change is staged in the index.

What do '??' marks indicate in `git status -s`?

  • A merge conflict
  • A staged deletion
  • An untracked file Git is not following yet
  • A renamed file

Answer: An untracked file Git is not following yet. ?? marks a file Git has never been told about — run git add to start tracking it.

After you `git add` a file, what does plain `git diff` show for it?

  • The same diff as before
  • Nothing — there are no unstaged changes left
  • The whole file
  • An error

Answer: Nothing — there are no unstaged changes left. Once staged, the change lives in the index, so git diff (working vs index) shows nothing for it.

Why is the staging area useful for crafting clean commits?

  • It compresses files
  • It lets you group only related changes into one focused commit
  • It speeds up pushes
  • It prevents merge conflicts

Answer: It lets you group only related changes into one focused commit. Staging selectively means each commit can contain one logical change instead of a messy grab-bag.

Continue this course

Frequently asked questions

What exactly is the staging area?

The staging area — also called the index — is a holding space between your working directory and your repository history. When you run git add, Git copies the current state of those changes into the index. Your next git commit snapshots exactly what's in the index, nothing more, nothing less. This two-step design lets you craft a focused commit instead of being forced to commit every change at once.

What's the difference between git diff and git diff --staged?

Plain git diff compares your working directory against the index, so it answers 'what have I changed but not staged yet?'. git diff --staged (also written --cached) compares the index against your last commit, answering 'what will my next commit actually contain?'. If you've already added a file, plain git diff shows nothing for it because the change now lives in the index.

Should I just use git add . every time?

git add . is convenient but blunt — it stages every change in the current directory, which can sweep in debug prints, unrelated edits, or files you didn't mean to commit. For tidy history, prefer naming files explicitly or using git add -p to stage changes hunk by hunk, so each commit contains one logical change.

What does git add -p do?

The -p (patch) flag puts git add into interactive mode. It breaks each file into 'hunks' of nearby changes and asks you about each one: y to stage it, n to skip it, s to split a big hunk into smaller pieces. It's the cleanest way to stage some changes from a file while leaving others for a later commit.

How do I unstage a file I added by mistake?

Run git restore --staged file.txt. That removes the file from the index (the staging area) but leaves your actual edits untouched in the working directory, so nothing is lost — the change simply goes back to being unstaged. Older guides show git reset HEAD file.txt, which does the same thing.