交互式暂存
本教程共 26 篇 · 第 17 篇 · 更新于 2026-07-29 · 约 6 分钟阅读
17. 交互式暂存
本节目标:学会用 git add -p 把一个文件的改动拆分成多个提交,精细控制暂存粒度,让提交历史更清晰。
你改了一个文件,加了两段功能。想分成两次提交,但 git add 一次就把整个文件都放进去了。
交互式暂存就是解决这个问题的。
为什么需要交互式暂存
好的提交历史,每个提交只做一件事。
比如你顺手修了个 typo,又加了个新功能。如果一起提交,以后想回滚 typo 修复就会把新功能也带走。
交互式暂存让你决定:哪些改动进这次提交,哪些留到下次。
进入交互式暂存
git add -p
或者指定文件:
git add -p app.py
Git 会进入 patch 模式,逐个显示文件的”hunk”(改动块),问你要不要暂存。
patch 模式各选项
每个 hunk 会显示 diff 内容,然后问:
Stage this hunk [y,n,q,a,d,s,e,?]?
输入 ? 看帮助:
y - 暂存这个 hunk
n - 不暂存这个 hunk
q - 退出,之前选定的会保存
a - 暂存这个 hunk 和这个文件剩下的所有 hunk
d - 不暂存这个 hunk 和这个文件剩下的所有 hunk
s - 把当前 hunk 拆成更小的 hunk
e - 手动编辑当前 hunk
/ - 搜索匹配正则的 hunk
j - 跳到下一个未决定的 hunk
J - 跳到下一个 hunk
k - 跳到上一个未决定的 hunk
K - 跳到上一个 hunk
g - 跳到指定编号的 hunk
? - 显示帮助
最常用的几个选项
y:暂存这个 hunk
最基础的操作。这个 hunk 进暂存区,下次提交会包含它。
n:跳过这个 hunk
这个 hunk 不进暂存区,留在工作目录里。
s:拆分 hunk
当前 hunk 太大,Git 没法自动拆?输入 s,它会尝试拆成更小的 hunk。
比如一个 hunk 里同时改了函数 A 和函数 B,拆开后就能分别决定。
e:手动编辑 hunk
最强大的选项。Git 会打开编辑器,让你直接编辑这个 hunk。
你可以:
- 删掉某些行,只保留想暂存的。
- 调整上下文。
- 甚至把一个 hunk 拆成两个。
编辑保存后,Git 自动应用。
a 和 d:批量决定
a:这个 hunk 和这个文件剩下的所有 hunk 都暂存。
d:这个 hunk 和这个文件剩下的所有 hunk 都不暂存。
适合”这个文件剩下的我都要/都不要”的场景。
完整流程示例
假设 app.py 里改了三处:
- 修了个 typo。
- 加了日志。
- 重构了一个函数。
你想把 1 和 2 作为”小修小补”提交,3 单独提交。
git add -p app.py
第一个 hunk 是 typo 修复:
Stage this hunk [y,n,q,a,d,s,e,?]? y
第二个 hunk 是日志:
Stage this hunk [y,n,q,a,d,s,e,?]? y
第三个 hunk 是重构:
Stage this hunk [y,n,q,a,d,s,e,?]? n
退出后查看状态:
Changes to be committed:
modified: app.py # 包含 typo 和日志
Changes not staged for commit:
modified: app.py # 包含重构
提交第一批:
git commit -m "修复 typo 并添加日志"
再提交第二批:
git add app.py
git commit -m "重构 calculate 函数"
两个提交,各司其职。
交互式暂存的完整界面
除了 git add -p,还有完整的交互式界面:
git add -i
进入后显示菜单:
staged unstaged path
1: unchanged +0/-1 TODO
2: unchanged +1/-1 index.html
3: unchanged +5/-1 lib/simplegit.rb
*** Commands ***
1: [s]tatus 2: [u]pdate 3: [r]evert 4: [a]dd untracked
5: [p]atch 6: [d]iff 7: [q]uit 8: [h]elp
u:选择要暂存的文件。r:取消暂存选中的文件。p:进入 patch 模式,选择 hunk。d:查看已暂存内容的 diff。a:添加未跟踪文件。
日常用 git add -p 就够了。git add -i 适合需要同时操作多个文件的复杂场景。
其它命令也支持 patch 模式
patch 不只是 git add 的专利:
git reset -p # 从暂存区部分移除
git checkout -p # 部分丢弃工作目录改动
git stash -p # 部分贮藏
用法和 git add -p 一样,逐个 hunk 决定。
实用技巧
配合 git diff 预览
进 patch 模式前,先 git diff 看一遍所有改动,心里有数。
善用 s 拆分
hunk 太大时,s 是救星。拆到足够小,才能精确控制。
编辑器的选择
e 选项会打开编辑器。确保你的 core.editor 配置的是你熟悉的工具。
git config --global core.editor "code --wait" # VS Code
git config --global core.editor "vim" # Vim
什么时候该用交互式暂存
- 一个文件里改了多处,想拆成多个提交。
- 顺手修了 bug,但不想和功能改动混在一起。
- 代码审查前,想把提交整理得更清晰。
本章小卡片
| 命令 | 作用 |
|---|---|
git add -p | 交互式选择 hunk 暂存 |
git add -i | 进入完整交互式暂存界面 |
git add -p <file> | 对指定文件进入 patch 模式 |
y | 暂存当前 hunk |
n | 跳过当前 hunk |
s | 拆分当前 hunk |
e | 手动编辑当前 hunk |
a | 暂存当前及本文件剩余 hunk |
d | 跳过当前及本文件剩余 hunk |
Tip养成”提交前先看 diff”的习惯。
git diff --cached看暂存区,git diff看工作目录。确认无误再 commit。