git stash -p 无效,正确做法是:Git 2.35+ 用 git stash push -p 交互式选择暂存内容;旧版本需先 git add -p 再 git stash --keep-index。

git stash -p 只暂存部分改动,但默认不支持交互式选择
Git 本身没有 git stash -p 这个选项——它会报错 error: unknown option `p'。想暂存部分修改,不能靠 stash 直接实现,得先用 git add -p 把想保留的改动加进暂存区,再用 git stash --keep-index 只 stash 工作区剩余部分。
常见错误是以为 git stash 能像 git add -p 那样分块选择。实际上 stash 是「全有或全无」操作,所谓“部分 stash”本质是:先精确控制暂存区内容,再决定 stash 哪些没暂存的变更。
- 先运行
git add -p,逐块选择要保留(即暂存)的改动 - 确认暂存区已包含你打算留下的修改:
git status --short查看A(added)、M(staged)标记 - 执行
git stash --keep-index:只 stash 工作区里「未暂存」的那些修改,暂存区内容原封不动保留在 index 中 - 切分支后,可直接
git commit暂存的内容;需要恢复工作区改动时再git stash pop
git stash push -p 才是真正的交互式暂存(Git 2.35+)
从 Git 2.35 开始,git stash push 支持 -p 参数,这才是真正意义上能交互选择哪些改动进入 stash 的命令:
-
git stash push -p会启动和git add -p一样的交互界面,让你逐块确认是否把某段修改加入本次 stash - 它不碰暂存区,也不要求你提前
git add;stash 内容完全由你交互决定 - 必须显式用
push,git stash -p仍无效 - 推荐搭配
-m使用:git stash push -p -m "wip: filter api response fields",避免后续混淆
注意:低于 Git 2.35 的系统(比如 CentOS 7 默认 Git 1.8、Ubuntu 20.04 默认 Git 2.25)不支持该功能,强行运行会提示 unknown option `p'。
stash 后发现暂存错了,怎么安全撤回?
stash 本身不可编辑、不可 revert、不可 cherry-pick,一旦 push 进去,就只能 apply/pop 或 drop。所以“暂存错了”通常指两种情况:
- 误把不该暂存的文件(比如本地
.env)塞进去了:用git stash show -p stash@{0}确认内容,没问题就git stash drop stash@{0}删除 - 暂存了部分改动,但 apply 后发现逻辑冲突或遗漏:别急着
git reset --hard,先git stash apply stash@{0}(不 drop),检查git status和git diff,手动调整后再决定是否git stash drop - 想反向撤销某个 stash 的 patch?不行。Git 不提供逆向 patch 工具。唯一办法是:apply 出来 → 手动删掉那几行 → 再 commit,或干脆 drop + 重做
为什么 git stash list 看不到你刚 stash 的内容?
不是丢了,是默认不显示未跟踪文件(untracked)和忽略文件(ignored)的 stash 记录 —— 但更可能是你根本没成功 stash。最常被忽略的两个前提:
-
git stash要求当前分支有至少一次 commit。如果仓库刚git init、还没git commit过,运行git stash会静默失败,且git stash list为空 - 执行前工作区必须「有可 stash 的内容」:如果
git status显示nothing to commit, working tree clean,那git stash实际什么也没做,也不会报错 - 验证是否成功:执行后立刻跑
git status,输出应为nothing to commit, working tree clean;再跑git stash list才应看到新条目
真正容易被忽略的是:stash 是纯本地操作,不写入 reflog 以外的任何远程可见结构,也完全不依赖分支 HEAD 是否有效 —— 它只依赖你当前工作区和暂存区的状态是否满足「有未提交变更」这个条件。


















