git add -p — Partial Staging
Yeh Git ki sabse underrated command hai — ek baar seekho, phir kabhi git add . use nahi karoge.
A hunk is a contiguous block of changes in a file — a section of added or removed lines surrounded by unchanged context lines.
Git does not think in files for staging — it thinks in hunks. This is the key insight that separates beginners from pros.
git add -p (or --patch) enters interactive mode where Git shows you one hunk at a time and asks: stage this?
This means ONE file can have its changes split across MULTIPLE commits. Bug fix and feature in the same file? Separate commits.
Without -p, you must stage the ENTIRE file. With -p, you stage only the specific changes you want.
If a hunk is too big, press s to split it into smaller hunks. If still too big, press e to manually edit the hunk in your editor.
# A file with 3 separate changes (3 hunks)
cat app.js
# line 1: const express = require("express");
# line 2: const app = express();
# line 3: console.log("DEBUG: starting"); ← DEBUG (skip this)
# line 4: app.listen(3000);
# line 5: // BUG FIX: handle null response ← BUG FIX (commit this)
# line 6: if (user !== null) { authenticate(user); }
# line 7: // FEATURE: add analytics ← FEATURE (separate commit)
# line 8: trackPageView();
# Without -p: all changes go in one commit
git add app.js # stages DEBUG + BUG FIX + FEATURE together
# With -p: you choose which hunks to stage
git add -p app.js
# Git shows hunk 1 (DEBUG): press n (skip)
# Git shows hunk 2 (BUG FIX): press y (stage this)
# Git shows hunk 3 (FEATURE): press n (skip)
# Now only the bug fix is staged!
git add -p, Git computes the diff between your working directory and the staging area, then breaks it into hunks — contiguous blocks of changes separated by unchanged context lines. Each hunk is presented to you one at a time. This is why one file can produce multiple commits — each hunk can go into a different commit.git add -p shows each hunk and waits for your command. Here are all the options:
y— yes, stage this hunkn— no, skip this hunks— split the hunk into smaller pieces (if possible)e— open editor to manually choose which lines to stage (most control)q— quit; do not stage this hunk or any remaining hunksa— stage this hunk AND all remaining hunks in this file (dangerous!)d— skip this hunk AND all remaining hunks in this file?— show help
git add -p <filename> — patch a specific file. git add -p — patch all changed files.
The -p flag works with other commands too: git reset -p, git stash -p, git checkout -p.
# Start interactive patch mode
git add -p app.js
# Git shows:
# @@ -2,6 +2,8 @@
# const express = require("express");
# const app = express();
# +console.log("DEBUG: starting"); ← added line (green)
# app.listen(3000);
# Stage this hunk [y,n,q,a,d,s,e,?]?
# Press y → stage it
# Press n → skip it
# Press s → split into smaller hunks
# Press e → open editor, manually delete lines you don't want
# After staging selected hunks:
git diff --staged # shows only the staged hunks
git diff # shows the remaining unstaged hunks
# Commit the carefully selected changes
git commit -m "fix: handle null user response"
# Stage the remaining feature hunk
git add -p app.js # press y for the analytics hunk
git commit -m "feat: add page view analytics"
y, n, and s. The e option is for surgical precision when changes are mixed together on adjacent lines. Avoid a — it stages everything remaining, defeating the purpose of using -p in the first place.Use case 1: Bug fix + debug code in the same file. Stage the fix, skip the console.logs.
Use case 2: Two features started in the same file. Stage one, commit, then stage the other. Separate commits for separate features.
Use case 3: Refactoring mixed with style changes. Stage the refactor (logic change) separately from formatting. Reviewers will thank you.
Use case 4: Accidental changes. IDE auto-format, trailing whitespace — skip the accidental changes, stage only the intentional ones.
Use case 5: WIP code mixed with a critical hotfix. Stage only the hotfix, leave WIP unstaged. Ship the fix now, finish the feature later.
Partial staging is how professionals maintain clean, logical commits despite messy working directories.
# Real scenario: mixed changes in auth.js
git diff auth.js
# + console.log("DEBUG: checking auth"); ← debug, skip
# + if (token && !isExpired(token)) { ← bug fix, stage
# + return validateSession(token); ← bug fix, stage
# + } ← bug fix, stage
# + sessionStorage.clear(); ← refactor, maybe stage
# + trackLogout(); ← new feature, skip
# Use -p to separate concerns
git add -p auth.js
# Hunk 1 (DEBUG): press n
# Hunk 2 (bug fix): press y
# Hunk 3 (clear + feature): press e to edit
# In editor: keep the sessionStorage.clear() line
# Delete the trackLogout() line
git diff --staged
# Only shows the bug fix + sessionStorage.clear()
git commit -m "fix: validate token before auth and clear stale session"
# Stage the feature separately later
git add -p auth.js # the trackLogout() is still there
git commit -m "feat: add logout tracking"Sometimes Git's automatic hunk boundaries are too coarse — two logical changes are grouped into one hunk.
Press s to split: Git breaks the hunk into smaller pieces at natural boundaries (unchanged lines between changes).
If s still isn't fine enough, press e to open your editor with the hunk displayed.
In the editor: lines starting with + will be staged. Lines starting with - will be removed from staging.
To NOT stage an added line: change the + to a space (keep the line but don't stage it), or delete the line entirely.
To NOT stage a removed line: change the - to a space (keep the line in the file, don't stage the removal).
Manual editing is the surgical tool — precise control over exactly which lines are staged.
# Git shows a hunk with mixed changes
# Stage this hunk [y,n,q,a,d,s,e,?]? s
# Sorry, cannot split this hunk further
# Time for manual editing
# Stage this hunk [y,n,q,a,d,s,e,?]? e
# Editor opens with:
# @@ -2,6 +2,8 @@
# const app = express();
# +console.log("DEBUG"); ← want to SKIP this
# -// old auth check ← want to KEEP this removal
# +if (token) { ← want to STAGE this addition
# + validate(token); ← want to STAGE this addition
# +}
# To skip the console.log line:
# Option 1: Delete the line entirely
# Option 2: Replace + with a space
# console.log("DEBUG");
# Save and close editor → only the selected lines are staged
e (manual edit), the most common error is leaving the + or - sign when you meant to remove it. Remember: + means "stage this addition", - means "stage this removal", space means "leave as is, don't stage". If you mess up, just close the editor without saving — Git will abort the patch for that hunk.-p isn't just for git add. It works with other commands too!
git reset -p: interactively UNSTAGE hunks. Made a mistake staging? Selectively unstage without resetting everything.
git stash -p: interactively choose which hunks to stash. Stash only the WIP code, keep the bug fix staged.
git checkout -p: interactively discard hunks from working directory. DANGEROUS but precise.
The interface is identical: y/n/s/e/a/d/q for all of them.
git reset -p is the "undo" of git add -p. Together they give you full control over the staging area.
# Oops, staged too much — selectively unstage
git reset -p app.js
# Git shows each staged hunk
# "Unstage this hunk [y,n,q,a,d,s,e,?]?"
# Press y to unstage, n to keep staged
# Stash only specific changes — leave the rest
git stash -p
# Git shows each hunk
# "Stash this hunk [y,n,q,a,d,s,e,?]?"
# Press y for WIP code, n for ready-to-commit code
# Only the selected hunks go into the stash
# Precisely discard unwanted changes
git checkout -p app.js
# "Discard this hunk from worktree [y,n,q,a,d,s,e,?]?"
# Press y for accidental changes (like IDE formatting)
# Press n for intentional changes
# WARNING: discarding is PERMANENT, no undo
# The -p flag family:
git add -p # stage selectively
git reset -p # unstage selectively
git stash -p # stash selectively
git checkout -p # discard selectively
git add -p, you already know how to use git reset -p, git stash -p, and git checkout -p. The y/n/s/e/a/d/q options are identical across all commands. Learn once, apply everywhere. This is why mastering -p is such a high-leverage investment.Lo kar liya — Key Points:
- ✅ A hunk is a contiguous block of changes — Git's unit of change for staging, not the entire file
- ✅ git add -p enters interactive mode: Git shows each hunk and asks whether to stage it (y/n/s/e/a/d/q)
- ✅ y = stage, n = skip, s = split into smaller hunks, e = manually edit which lines to stage
- ✅ Partial staging lets you create clean, logical commits from messy working directories
- ✅ git reset -p selectively unstages, git stash -p selectively stashes — same interface
- ✅ Use case: separate bug fixes from debug code, features from refactoring, intentional from accidental changes
- ✅ The e option gives surgical control — edit the hunk in your editor to stage exactly the lines you want
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login