A plain git commit records the contents of the index and nothing else. The index is also called the staging area, and it holds the changes you picked for the next commit. Staging is the act of putting them there.
It sits between the working directory, where you edit files, and the repository, where commits live.
The Pro Git book describes the index as a flattened manifest of paths, modes, and object names, not a tree of directories. So a staged file is a recorded version, not a live link to whatever is on disk right now.
What Is Staging in Git?

Instead of committing every file you touched, you choose which changes go into the next commit. The choices wait in the index, which in version control terms is the proposed next commit (Pro Git book, git-scm.com).
The command that fills it is git add, which copies the current content of a file into the index. Git commit then turns whatever sits there into a new snapshot.
Run git commit with no other arguments and Git records only staged changes (git-add manual, Git 2.56.0). Unstaged edits stay on disk and miss the commit.
That gap is the whole point. Two unrelated fixes made in one afternoon can become two separate commits, and a separate guide explains what git commit does with the index.
How Does the Staging Area Store Changes?

Everything lives in one binary file, .git/index, which holds a reference to file content for every tracked path. Your files are not copied into it.
Git’s index format documentation (last changed in Git 2.32.0, June 2021) describes a 12-byte header that starts with the signature DIRC and supports versions 2, 3 and 4.
Each entry carries a path name relative to the top-level directory and an object name, which is a SHA-1 hash in traditional repositories and SHA-256 in SHA-256 ones. It also stores a mode that combines file type with Unix permission bits.
- Stat data copied from the file system, including timestamps, device, inode, owner IDs and size
- A 16-bit flags field that adds the merge stage number and a few state bits
Run git ls-files –stage to print the mode, object name and stage number for each entry (git-ls-files manual).
| Tree | Role | Updated by |
|---|---|---|
| Working directory | The editable files on disk | Your editor |
| Index | Proposed next commit | git add |
| HEAD | Last commit snapshot | git commit |
HEAD points to the last commit in the local git repository. Right after a commit, all three trees match (Pro Git book).
Because an index entry holds an object name and not a pointer to the live file, the index remembers a version, not a file. The git-add manual adds that git add copies content only at the moment it runs.
A common surprise follows from that. Edit a file after staging it and HEAD, the index and the working directory each hold a different version.
One limit comes straight from the format. The index lists files, not directories, so an empty directory can’t be staged.
What States Does a File Move Through, and How Do You See Them?

A file goes from untracked to modified to staged to committed (the Pro Git book calls that last state unmodified), and git status reports where each one currently sits.
A fresh clone starts clean, with every file tracked and unmodified. Edit one and it becomes modified. Run git add and it becomes staged, and after git commit the cycle resets.
Reading git status Output
Files under Untracked files are new to Git, so they’re absent from both the last commit and the index. Staged files appear under Changes to be committed. Modified files you haven’t added yet show up under Changes not staged for commit.
The compact form, git status -s, uses two columns. The left one describes the index and the right one describes the working tree.
So MM means a file was modified, staged, and then modified again, while ?? marks an untracked file. The remaining flags are covered in an explainer on git status.
Comparing git diff and git diff –staged

Git status names files. Diffs show lines.
Plain git diff compares the working tree with the index, so it lists edits you could still stage. Add –staged and the comparison is index against HEAD, which lists exactly what the next commit will contain. The –cached option is a synonym (git-diff manual, Git 2.56.0).
Stage a file, edit it again, and both commands print output. Stage everything and plain git diff prints nothing at all, which throws people off the first time.
The other forms of the command are covered in a guide to git diff.
How to Stage Files with git add
Run git add followed by a file, a directory, or a dot, then confirm the result with git status. Git copies the file content as it exists at that moment into the index, so a later edit needs another git add.
This page sticks to the staging side. The full command gets its own guide on what git add does.
- Edit or create the files you want to commit.
- Run git add with a file name, a directory name, or a pattern.
- Run git status and read the “Changes to be committed” list.
- Run git commit to record the index.
The variants differ in how they treat new, modified, and deleted files (git-add manual, Git 2.56.0).
| Command | New files | Modified files | Deleted files |
|---|---|---|---|
| git add path | Staged | Staged | Staged |
| git add -A | Staged | Staged | Staged |
| git add -u | Skipped | Staged | Staged |
| git add –no-all path | Staged | Staged | Skipped |
Without a path, git add -A and git add -u work on the whole tree, even when you run them from a subdirectory. The Git 2.0 release notes record that change, along with git add path becoming the same as git add -A path.
Before 2.0, git add path ignored deletions, so removed files stayed in the index. Old tutorials still describe that behavior, which is worth knowing if a guide you’re following disagrees with your terminal.
Ignored files are skipped by default. Name one exactly and the command fails with a list of ignored files, although –force overrides that. And an edit made after staging stays invisible to the commit until you run git add again.
Which files count as ignored depends on the patterns in a .gitignore file, covered in a guide to how gitignore patterns work. Set one up before the first git add of a new project so build output and log files never reach the index.
How to Stage Part of a File with git add -p
Run git add -p and answer the prompt for each hunk. Type y to stage it or n to skip it, and Git stages only the hunks you accept, so one file can feed two separate commits.
A hunk is one block of changed lines from the diff between the index and the working tree (git-add manual, Git 2.56.0). A few other keys matter in practice.
- s splits a hunk into smaller ones
- e lets you edit the hunk by hand
- q quits and leaves the current hunk and everything after it unstaged
The Pro Git book’s help screen lists 13 choices. The git-add manual for Git 2.56.0 lists 16, adding q, p and P, so the keys on your screen depend on your Git version.
The interactive status view shows both counts for a partly staged file side by side, such as +1/-1 staged and +4/-0 unstaged (Pro Git book).
New files need a small workaround. Patch mode works from the index, and a file Git has never seen has no entry there, so run git add -N on it first. That records only the intent to add the path with no content, and then patch mode can start.
The e key opens the hunk in your editor, and the manual warns that it is easy to build a patch that does not apply. Deleting every line cancels the operation and stages nothing new.
The same –patch option exists on git stash, which shelves the hunks you choose instead of staging them (Pro Git book).
How to Unstage a File
Run git restore –staged followed by the file name. Git resets the index entry to match HEAD and leaves your working directory edits alone (git-restore manual, Git 2.56.0).
A file that was never committed drops back to untracked, because HEAD has no entry for it. The step-by-step version lives in a guide on how to unstage a file in Git.
The restore command shipped in Git 2.23.0 (August 2019). Guides written before that use git reset, and for this job the two are equivalent.
Git restore –staged copies the file from HEAD into the index and never touches the working tree. Git reset file is shorthand for git reset –mixed HEAD file, which does the same copy and is the exact opposite of git add (Pro Git book).
| Command | Restores | From | Loses your edits? |
|---|---|---|---|
| git restore –staged file | Index | HEAD | No |
| git restore file | Working tree | Index | Yes |
| git restore –staged –worktree file | Both | HEAD | Yes |
Dropping the –staged flag is the classic slip. Without it, git restore overwrites the working tree from the index, and unstaged edits have no copy anywhere.
To stop tracking a file but keep it on disk, use git rm –cached instead. It fits when a log file or build output got staged because the ignore patterns missed it (Pro Git book).
Reset has a destructive form too. Only the –hard option overwrites working files, and a full guide on what git reset does covers all the modes.
When Can You Skip the Staging Area?

Use git commit -a when every edit to tracked files belongs in one commit. Git stages modified and deleted tracked files itself, then commits.
New files aren’t affected, so an untracked file stays out of the commit (git-commit manual, Git 2.56.0).
Git commit with file paths is another shortcut. It records the current content of the named files and ignores everything else that is staged, but the held-back changes are not lost and go into the next commit.
Staging first keeps commits logically separate, which makes them easier to review (Pro Git book), and git diff –staged previews the exact commit. The price is an extra command before every commit, and partial staging is more ceremony than a tiny single-purpose change needs.
Commit -a is one command for modified and deleted tracked files. It leaves new files out, and unrelated edits ride along, which the Pro Git book warns about.
Run git commit -vv to see the staged diff and the unstaged diff together in the editor (git-commit manual).
The decision rule is short. Run git diff. One purpose in the output means commit -a, two purposes mean staging in parts with git add -p.
Focused commits also give the code review process small diffs to read.
Build the habit around one check, reading git diff –staged before every commit. If it shows two purposes, split the commit.
The habit costs time on one-line fixes, and there the documented shortcut is the better tool. Write whichever rule you pick into your team’s shared git workflow so every commit follows it.
Staging in Git FAQ
Is staging in Git the same as a staging environment?
No. A staging environment is a pre-release copy of the production environment where teams test a build before deployment. Git’s staging area is the index, a local file inside the repository, and it never touches a server.
Is staging the same as tracking a file?
No. Tracked files are those in the last snapshot plus any newly staged ones, and they can be unmodified, modified, or staged (Pro Git book). Untracked files sit in neither the last commit nor the index.
How do I stage a deleted or renamed file?
Use git rm for a deletion, which removes the file and stages the removal in one step. Git stores no rename metadata, so git mv is shorthand for mv, git rm, and git add (Pro Git book). Git detects the rename after the fact.
What happens to staged changes when I run git stash?
Stash saves both the working tree and the index, then rolls each back to HEAD. When you pop it, pass –index to try to restore the staged state too (git-stash manual, Git 2.56.0). Run git stash push –staged to shelve only what is staged.
Does a pre-commit hook check the staged files or the working copy?
Git runs the hook from the root of the working tree, so a script that reads files sees working copies, unstaged edits included (githooks manual, Git 2.56.0). To inspect what will be committed, query the index with git diff –cached. The –no-verify option bypasses the hook.
Can a GUI client stage individual lines?
Yes. The git-gui tool that ships with Git stages individual hunks or individual lines when you right-click in the diff area (Pro Git book). Other clients vary, since some expose only a curated subset of Git, and anything a GUI does the command line can also do.
Testing What You Actually Staged
Staging in Git lets a commit record a combination of edits that the working tree never held, so every partially staged commit needs a test run against the index alone.
The git stash push –keep-index command shelves the unstaged edits and leaves the index intact, so the build sees only the staged state (git stash manual, Git 2.56.0).
Start by staging whole files by purpose. When a file mixes two purposes, split it with git add -p, then test each partial commit with –keep-index. Stop at the first step that gives you clean commits.
The trade-off is time. Each partial commit costs one stash, one test run, and one pop.
A manual stash covers one machine, while continuous integration runs the same check on every pushed commit.
Verified against the Git 2.56.0 manuals in September 2026. A change to –keep-index in a later release would alter this advice.
- Notepad++ Android Options: Apps That Come Close - October 21, 2026
- Data Management Services: A Practical Guide for Growing Companies - October 21, 2026
- MongoDB Cheat Sheet - October 20, 2026




