Stage part of a Git file with patch mode
Use Git patch mode to stage selected hunks from a tracked file, then inspect the staged and unstaged differences separately. Staging records the selected content in the index; the rest stays in the working file unless another command changes it.
Stage only part of a Git file
Patch mode presents changes in pieces so that a person can choose which hunks enter the index. The add reference describes adding only part of a file’s changes, and the diff reference distinguishes the staged comparison from the remaining working-file comparison12. A hunk is a proposed patch region, not necessarily one logical change; nearby edits can be presented together.
The example changes two distant lines in a tracked text file. It answers yes to the first prompt and no to the second, then verifies the index and working file separately. It also checks each diff’s line counts and prints the selected additions. The exact sequence of answers belongs to this fixture. It must not be copied blindly into a different file whose hunk order or count may differ.
Inspect before choosing
Start with the actual file, the intended commit and its current staged state. A file can already have a staged version as well as newer working changes. Patch mode selects changes relative to its current comparison; it does not know which part of a task belongs in a commit. Inspect enough context to recognize the purpose of each edit, including nearby deletions and dependencies.
The fixture starts from a twenty-line committed file and modifies lines two and nineteen. That distance produces two hunks in this run. A closer pair of changes might appear in one hunk, while file contents, Git options and existing staged changes can change the presentation. The test records what happened for these two edits, not a universal prompt sequence.
Use the interactive choice deliberately
The script supplies y and n through standard input so the same choices can be repeated without a person at the terminal. For this fixture, run git add -p -- note.txt interactively and read each prompt and its context. Accept the intended hunk, decline an unrelated one, and stop if the presented patch does not match the plan. Git’s interactive help describes additional choices; those options are not demonstrated by this example.
The script stores the dialogue in the example’s parent directory so it does not pollute the repository’s status. It then writes a copy of the staged file outside the repository for assertions. The staged copy contains the first replacement and the original nineteenth line. The working file still contains the second replacement. These checks show why staging a portion does not mean deleting the rest of the working edit.
Compare both results
Read the staged diff to see what the next commit is prepared to include. Read the ordinary working diff to see what remains outside the index. In this example each has one added and one removed line, but equal counts do not establish that the right content was selected. The two printed additions identify which changed line is on each side.
Do not infer a clean repository from a single empty comparison. A staged-only change, an untracked file or an edit in another path can need separate attention. The staged and working diff guide explains the two comparisons in a fuller state example. Before a commit, inspect the whole staged set, not just the one path used here.
When a hunk does not match the task
If a hunk combines related and unrelated edits, do not accept it merely to finish the prompts. The right next step depends on the content: the file may need to be edited into separable changes, or Git may offer another interactive choice. This page does not demonstrate manually editing a patch or splitting a combined hunk, so it does not supply a safe recipe for every case.
Likewise, if the file changes after patch mode, recheck both comparisons. The index is a snapshot prepared at the time of staging; later working-file edits are not silently added to that snapshot. Preserve any staged-only content before changing the index again. An editor buffer that has not been saved is outside this test and may not match the file Git reads.
Finally, commit only after the selected staged state is understood. A successful patch-mode interaction does not run project tests, prove the change is complete or make a secret safe to publish. This example stages no real project data and makes no commit after the selection.
Run the complete local example
Before running: Patch prompts depend on the actual diff. Never pipe these sample answers into a different file; inspect each hunk interactively. Run this complete MIT-licensed example with Git 2.56.0 in an empty directory. It creates stage-example/, including its own local bare remote. It performs no network access and refuses to reuse an existing example directory.
Download the complete example. The printed file is the one that ran.
#!/bin/sh
# SPDX-License-Identifier: MIT
set -eu
export TZ=UTC LC_ALL=C
export GIT_CONFIG_NOSYSTEM=1 GIT_CONFIG_GLOBAL=/dev/null
export GIT_AUTHOR_NAME='Example Author' GIT_AUTHOR_EMAIL='author@example.invalid'
export GIT_COMMITTER_NAME='Example Author' GIT_COMMITTER_EMAIL='author@example.invalid'
export GIT_AUTHOR_DATE='2026-10-27T12:00:00+00:00'
export GIT_COMMITTER_DATE='2026-10-27T12:00:00+00:00'
test "$(git version)" = 'git version 2.56.0'
mkdir stage-example
cd stage-example
git init --template= --bare -q --initial-branch=main origin.git
git init --template= -q --initial-branch=main repo
cd repo
for n in $(seq 1 20); do printf 'line %s\n' "$n"; done > note.txt
git add note.txt
git commit -qm 'Base'
git remote add origin ../origin.git
git push -q -u origin main >/dev/null
awk '{if (NR==2) print "first change"; else if (NR==19) print "second change"; else print}' note.txt > updated.txt
mv updated.txt note.txt
printf 'y\nn\n' | git add -p -- note.txt > ../patch-dialogue
git show :note.txt > ../staged-copy
grep -q '^first change$' ../staged-copy
grep -q '^line 19$' ../staged-copy
grep -q '^second change$' note.txt
test "$(git diff --cached --numstat -- note.txt)" = "$(printf '1\t1\tnote.txt')"
test "$(git diff --numstat -- note.txt)" = "$(printf '1\t1\tnote.txt')"
printf 'First hunk staged; second hunk remains only in working file\n'
git diff --cached -- note.txt | grep '^+first change$'
git diff -- note.txt | grep '^+second change$'
Both runs produced:
First hunk staged; second hunk remains only in working file
+first change
+second change
The script leaves its example directory and its repositories in place. Remove that newly created directory when it is no longer needed; inspect the name first so cleanup does not remove another project. The assertions stop the run if the demonstrated state differs. No command in the example connects to an external remote.
Not covered on this page
- Splitting or manually editing a combined hunk.
- Binary files, conflicts, partial staging of an untracked file or unsaved editor buffers.
- Checking project tests or deciding whether a change is suitable to publish.
Sources
-
Git 2.56.0 add reference. Git v2.56.0; checked 27 October 2026 UTC. ↩
-
Git 2.56.0 diff reference. Git v2.56.0; checked 27 October 2026 UTC. ↩
How we test: methodology. Found a mistake? Corrections.