In git add -p, what do the y, n, s, e and q keys do?
answer
- yes, no, and three more
- one subdivides the hunk
- one hands you the raw patch
- quitting does not undo earlier answers
basics
~20 sAt the git add -p prompt, y stages the shown hunk, n skips it, s splits it into smaller hunks when context lines allow, e opens it in your editor for line-level control, and q quits leaving earlier answers already staged.
solid answer
~50 sInteractive patch mode asks a question per hunk, and five keys cover almost every session: - **y** — stage this hunk. - **n** — do not stage it; the change stays in the working tree. - **s** — split this hunk into smaller ones. Only possible when unchanged context lines separate the changed blocks; otherwise Git tells you it cannot split. - **e** — open the hunk in your editor so you can stage individual lines. Delete a `+` line to leave that addition unstaged; turn a `-` line into a context line by replacing the leading minus with a space to keep that deletion out of the index. - **q** — quit immediately. Hunks you already accepted stay staged; the rest are left alone. The other keys worth knowing are **a** (stage this and all remaining hunks in the file), **d** (skip this and all remaining hunks in the file), and **?** for help.
code
console · 10 lines$ git add -p src/report.js
@@ -12,7 +12,9 @@ function render(rows) {
- const out = rows.map(fmt);
+ const out = rows.filter(Boolean).map(fmt);
+ console.log(out);
return out.join("\n");
}
Stage this hunk [y,n,q,a,d,s,e,?]? s
Split into 2 hunks.go deeper
Recall the two everyday keys, y and n, and know that ? prints the full list of options at the prompt rather than trying to memorise all of them.
Explain s, e and q precisely, including why splitting needs context lines and the asymmetric editing rule for + and - lines in the e editor.
Show the workflow around the keys: survey a large diff first, prefer splitting over hand-editing, and verify with git diff --cached before the commit lands.
Frame this as tooling fluency in service of reviewable history, and know when to stop — a diff that needs heavy hand-editing to split is usually a sign the work should have been sequenced differently.
## The prompt loop After `git add -p`, Git prints one hunk of the working-tree-versus-index diff and waits for a single keypress. Nothing is written to the index until you answer, and the working tree is never touched, so exploring the loop is safe — the worst outcome of a wrong key is a staged hunk you unstage afterwards. ## The five keys that matter **y** applies the hunk to the index. **n** leaves it out; the lines remain on disk and will be offered again next time you run patch mode. **s** subdivides. Git can split a hunk wherever there is at least one unchanged context line between changed regions, because each resulting piece must still apply cleanly on its own. Two edits on adjacent lines cannot be separated this way, and Git says so rather than guessing. **e** is the escape hatch when **s** cannot help. Git writes the hunk into your editor as a patch fragment with a short comment block explaining the rules. The mechanics are worth memorising because they are asymmetric: - To *not* stage an added line, delete the whole `+` line from the patch. - To *not* stage a removed line, replace its leading `-` with a space, turning it into context. - Leave context lines alone; deleting them makes the patch fail to apply, at which point Git offers to let you re-edit. That asymmetry follows from what the index must end up containing: context lines describe the state on both sides, so a deletion you decline has to survive as context. **q** stops the session. It is not a cancel: everything you already said yes to is in the index. If you want to undo that, unstage afterwards. ## The navigation keys **a** and **d** are the bulk answers for the current file — accept everything remaining in it, or skip everything remaining in it — which makes short work of a session where one file is entirely wanted and another entirely not. **g** jumps to a numbered hunk, **/** searches for a hunk matching a regular expression, and **j**, **J**, **k**, **K** move between hunks without deciding, letting you survey a large diff before committing to answers. **?** prints the full key list, which is the honest answer in an interview when you cannot recall a rarer key. ## Using the keys well A good session has a shape. Skim with **j** first if the diff is large, so you know what you are choosing between. Use **s** aggressively — an over-split hunk costs one extra keystroke, while an under-split one drags unrelated lines into the commit. Fall back to **e** only for genuinely interleaved edits, since hand-editing a patch is where mistakes creep in. When you finish, check the result rather than trusting the session: `git diff --cached` shows exactly what you staged and `git diff` shows what is left behind. That pair is the real safety net, and it is also what an interviewer wants to hear you mention — the keys are trivia, but verifying the assembled index before committing is judgment. The same keys work in `git commit -p`, `git restore -p`, `git checkout -p`, `git reset -p` and `git stash push -p`, since all of them drive the same interactive machinery. Only the verb applied to the chosen hunks changes.
- When does s refuse to split a hunk, and what do you do then?Splitting needs at least one unchanged context line between the changed regions, because each piece must still apply on its own. Edits on adjacent lines cannot be separated, and Git says so rather than guessing. Use **e** instead and hand-edit the patch in your editor.
- In the e editor, how do you keep an added line and a removed line out of the staged hunk?Delete the `+` line entirely to drop an addition. For a removal, replace the leading `-` with a space so the line becomes context and survives in the staged result. Never delete context lines — the patch will fail to apply, though Git then offers to let you edit again.
- If you press q halfway through, what state is the repository in?Exactly what you answered so far: hunks you accepted are in the index, everything else is untouched in the working tree. It is a stop, not an undo. Check with `git diff --cached`, and unstage if you would rather start over.
saying these in an interview costs you the question
- Thinks q cancels the session and unstages everything
- Believes n discards the change from the working tree
- Expects s to split any hunk regardless of context
- Deletes context lines when hand-editing a hunk
- Confuses a (rest of file) with staging the whole repository