侧边栏壁纸
博主头像
一笑痕

人生若只如初见,
是可喜亦或者是可悲?

  • 累计撰写 247 篇文章
  • 累计收到 7 条评论

git stash --keep-index 留下暂存区,也藏起暂存改动

2026-10-27 / 0 评论 / 3 阅读

git stash --keep-index 留下暂存区,也藏起暂存改动

暂存了一个文件里的部分修改,接着要切换分支处理别的事。普通的 git stash 会把暂存内容也从工作区拿走;加上 --keep-index 后,暂存版本仍留在当前目录。容易误会的是,这不等于暂存版本没有进 stash。两个临时仓库的对照结果把这两件事分开了。

留在工作区,不代表没被收进 stash

实验从同一份 base 文件开始。先追加 staged 并执行 git add,再追加 unstaged,这样 index 只包含第一处修改,而工作区文件同时含两处。默认执行 stash 后,文件退回 base,index 与工作区都干净;stash 的补丁则包含两行新增内容。

[default]
status:
index diff:
(empty)
worktree diff:
(empty)
file:
base
stash diff:
diff --git a/note.txt b/note.txt
index df967b9..913ae38 100644
--- a/note.txt
+++ b/note.txt
@@ -1 +1,3 @@
 base
+staged
+unstaged

加上 --keep-index 后,状态变成 M note.txt。空格位置很重要:首列的 M 表示 index 相对提交有改动,第二列为空,说明工作区没有额外的 unstaged 差异。文件里仍有 base 和 staged 两行。可 stash 里的补丁仍然同时列出 staged 与 unstaged。

[--keep-index]
status: M  note.txt
index diff:
diff --git a/note.txt b/note.txt
index df967b9..12caafd 100644
--- a/note.txt
+++ b/note.txt
@@ -1 +1,2 @@
 base
+staged
worktree diff:
(empty)
file:
base
staged
stash diff:
diff --git a/note.txt b/note.txt
index df967b9..913ae38 100644
--- a/note.txt
+++ b/note.txt
@@ -1 +1,3 @@
 base
+staged
+unstaged
== experiment complete ==

这里的「保留」描述的是执行完成后的当前 index 与工作区,不是在 stash 里只存未暂存部分。忘了这一点,稍后再应用 stash,暂存那行可能会以为是重复修改。需要取回时先检查目标分支是否已经有同一改动。

两种命令留下的状态不同

操作 执行后 index 执行后工作区 stash 内容
git stash push 干净 干净 staged 与 unstaged 修改
git stash push --keep-index 保留 staged 修改 没有额外 unstaged 修改 staged 与 unstaged 修改

表格里 stash 内容看起来相同,这是本次实验最值得记住的地方。选项名容易让人以为 Git 只保存未暂存部分,实际动作是让已经暂存的部分继续留在 index。比较 git stash show -p stash@{0} 才能看到保存边界;只看 git status,会漏掉 stash 里仍有暂存版本这件事。

这个行为适合先提交已暂存部分、把未暂存内容暂时收起的工作流。例如先跑针对暂存内容的检查,确认后提交,再恢复 stash 继续处理剩余修改。这里有个实际取舍:我会把它用于短暂切换,不会把它当作「只 stash unstaged」的快捷写法,因为 stash 里仍带着已暂存版本,恢复时更需要留意重复应用和冲突。

恢复前先看清应用范围

git stash apply 会把 stash 的差异应用到当前目录,但不会自动删除 stash 条目;git stash pop 在应用成功后还会尝试移除该条目。保留 index 的工作流中,当前目录原本已经有 staged 修改,而 stash 本身也含那部分内容。Git 会依据共同基线和补丁尝试合并,不能把「一定产生重复行」当成结论,结果取决于当前内容有没有变化。

在临时仓库里试验的安全边界很简单:先看 git status --short,再用 git stash show -p 查看补丁。若暂存区里已有的修改已经提交到新分支,恢复前尤其要确认 stash 是否包含同一修改。必要时先复制仓库或建临时 worktree,再试 apply。宁可多看一眼补丁,也不在有未提交内容的真实工作区里试一个自己没把握的 pop。

这次脚本使用两个全新的临时仓库,分别运行默认 stash 与 --keep-index,日志保留完整输出。行为在本机 Git 2.50.1(Apple Git-155)实测;其他版本或 stash 配置可能影响显示细节,跨版本没有额外验证。临时目录会在脚本退出时清除,原仓库没有被改动。

    🤞 分享