A useful commit explains one change that another person can review and, if necessary, undo. Your editor does not have to contain only that change. You may fix a calculation while also rewriting a heading and experimenting with a different layout. Partial staging lets you choose which edits belong in the next commit. To use it confidently, understand the index: it stores the proposed next snapshot, separately from both the last commit and the files you are editing. This guide builds that distinction with a small local lab before introducing interactive hunk selection.
Separate three versions of a file
For a tracked file, compare three places: the version in HEAD, the version in the index, and the version in the working tree. Git add copies selected content into the index at that moment. It does not create a lasting connection that automatically stages later edits. A file can therefore have staged and unstaged changes simultaneously. Git commit records the index, not every visible editor buffer. This explains why saving another edit after git add does not necessarily include it in the next commit. Untracked files add another condition: their content enters version control only when deliberately staged.
Read the two columns of short status
In ordinary git status --short output, the first position describes the index relative to HEAD, and the second describes the working tree relative to the index. MM beside a tracked path means both comparisons contain modifications. An added file can likewise be staged and then edited again. Read the long status descriptions while learning rather than trying to memorize every code immediately. A clean working-tree comparison does not prove the staged change is correct; it only shows the two snapshots agree. Always inspect the content difference relevant to the decision you are about to make.
Select hunks with git add -p
Run git add -p followed by a path to review proposed changes interactively. A hunk is a nearby group of changed lines presented with surrounding context. Choose yes to stage it or no to leave it unstaged. The help prompt explains additional choices, including splitting a hunk when Git can separate its changes and editing the patch when you need finer control. Adjacent edits cannot always be split automatically. Start with small, well-separated changes and read the entire presented hunk. A hunk boundary is a text boundary, not proof that the selected behavior forms a complete feature.
Inspect what will actually be committed
Git diff normally compares the working tree with the index. Git diff --cached compares the index with HEAD, revealing the next commit's staged change. Git show :path reads a staged file directly. These views answer different questions and are useful together when one path is marked MM. Before committing, review the cached diff and ensure imports, call sites, tests and configuration needed by the change are included. A staged function without its required helper can create a broken commit even when the full working tree runs correctly. Review the proposed snapshot as another developer will receive it.
Test the staged behavior deliberately
Running tests in the current working directory usually tests every saved edit, including unstaged work. That can hide a missing staged dependency. For important changes, use your project's established process to test an isolated staged snapshot or recreate the intended change in a separate worktree without losing current edits. Do not casually run stash commands as a universal testing recipe: untracked files, index preservation and conflict handling require care. A simpler beginner practice is to keep the staged feature small, inspect every changed path, and avoid relying on unrelated experimental edits for its successful execution.
Correct a staging choice without discarding work
Use git restore --staged followed by a path to remove that path's staged changes while preserving its working-tree content. For an existing tracked file, the default staged restoration uses HEAD as the source. To unstage only selected changes, the patch form git restore --staged -p offers interactive selection. Read its prompt because you are selecting what to restore, not what to add. Do not confuse this with plain git restore path, which can overwrite working-tree edits. When uncertain, first record status and inspect both diffs so you know which snapshot needs correction.
Sources and prerequisites
Start with commits, history and diffs and team workflows. The git add reference, git diff reference and git status reference document the underlying operations.
Git Partial Staging and the Index Summary
- The next commit records the index snapshot.
- Review cached and ordinary diffs when a path has staged and unstaged work.
- Partial selection must include the dependencies required by the proposed change.
Git Partial Staging and the Index Examples
Each example shows the code, the output it produces and what each part does.
Observe a staged snapshot after another edit
Run this Bash lab in a new disposable directory using Git Bash on Windows or a compatible terminal. The first change is staged; the later price edit stays only in the working tree. Initial commit messages may vary by Git version. The expected output below shows only the final inspection commands, which expose the exact index content and the two status columns.
The staged file contains Store and ten. The working file contains Store and twelve. Committing now would record the new title with the old price. Inspect git diff --cached to see the title change and git diff to see the unstaged price change. That result proves staging is a snapshot operation rather than a promise to include whatever the editor contains later.
mkdir staging-lab
cd staging-lab
git init -b main
git config user.name Learner
git config user.email learner@example.test
printf 'Title: Shop\nPrice: 10\n' > catalog.txt
git add catalog.txt
git commit -m 'Start catalog'
printf 'Title: Store\nPrice: 10\n' > catalog.txt
git add catalog.txt
printf 'Title: Store\nPrice: 12\n' > catalog.txt
git show :catalog.txt
git status --shortTitle: Store
Price: 10
MM catalog.txtCommon Git Partial Staging and the Index Mistakes
Assuming green tests validate a partial commit
A test run that passes with both title and price edits present says nothing about whether the selected staged feature has all its dependencies. The distinction matters more in code than in this text fixture. A new test can pass because an unstaged helper exists locally but fail immediately after another developer checks out the commit. Keep staging review and behavior verification connected: identify the intended change, inspect its complete proposed snapshot and test that snapshot under your project's workflow.
Git Partial Staging and the Index in Real Projects
Unstage a file and re-stage it by hunk
Continue in the lab and unstage catalog.txt while keeping both saved edits. Predict the index content before running the inspection. Then use git add -p catalog.txt to decide which change belongs in a focused title commit. The adjacent changed lines may appear together, so split only if the prompt offers a valid split; otherwise practice separating the edits in the file first.
git restore --staged catalog.txt
git show :catalog.txt
git status --shortTitle: Shop
Price: 10
M catalog.txtThe index returns to the committed Shop-and-ten snapshot. The file on disk still contains Store and twelve, so short status now reports only a working-tree modification. This is a safe unstaging result: it changes the proposed commit without erasing the saved work. Check the cached diff is empty, then rebuild the intended staged change and inspect it before committing.
Git Partial Staging and the Index FAQ
Does git add keep staging later saves automatically?
No. It copies the selected content into the index when the command runs. Later edits change the working tree and require another staging decision. That is why the lab shows an MM status and a staged price of ten even though the saved file contains twelve. If you intentionally want the latest entire file, stage it again and review the cached diff. If you want only some of its changes, use patch selection instead.
What is the difference between git diff and git diff --cached?
The ordinary diff shows working-tree changes relative to the index. The cached form shows staged changes relative to HEAD. With partial staging, each can contain a different part of the same file's edits. Read both when planning a commit, and use git show :path if you need the whole staged file rather than only a patch. Neither view by itself establishes that the chosen feature is complete or correctly tested.
Can git add -p split every hunk?
No. Git can split a hunk when the changed regions have suitable separation, but tightly adjacent edits may stay together. The interactive help lists choices available for the current hunk. Manual patch editing requires understanding context and added versus removed lines, so use it carefully. For early practice, make two changes separated by unchanged lines. The objective is a coherent commit, not using the most complicated interactive command on every file.
Does unstaging delete the edits I made?
Git restore --staged targets the index, so the ordinary tracked-file use leaves your saved working-tree edits in place. Plain git restore targets the working tree and has different consequences. Check the full command before running it and confirm the resulting status afterward. The exercise demonstrates the distinction with visible file contents. For valuable uncommitted work, maintain an appropriate local backup because discarding edits that were never committed may leave Git nothing to recover.
Git Partial Staging and the Index Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
After the lab's second save, which price would an immediate commit record?
Git Partial Staging and the Index Quiz
2 questions to check what you learned.
What does MM beside a tracked path describe?
- Two identical commits already uploaded
- A file excluded by two ignore patterns
- Both index-versus-HEAD and working-tree-versus-index modifications
Which command reads the full staged catalog.txt snapshot?
- git show :catalog.txt
- git show HEAD:catalog.txt
- git diff catalog.txt