Skip to content

08 · 暂存工作区与多工作树

切去修 hotfix 时,手头改到一半还不想 commit——用 stashworktree,不要 reset --hard 清空现场。

git stash

作用: 把工作区(和可选的暂存区、未跟踪文件)打成一份现场快照,让工作区回到干净的 HEAD,之后再取回。

改动范围: 工作区 / 暂存区。stash 本身存在本地引用 refs/stash,不进业务分支历史。

典型场景:

  • 正在 feature/login 改着,线上要先修。
  • 切分支时 Git 拒绝,因为改动会冲突。
  • 想试试「丢掉这些改动会不会好」,又不敢真丢。

常用写法:

bash
git stash push -m "登录表单做到一半"
git stash                      # 同 push,无说明
git stash -u                   # 连未跟踪文件一起收走
git stash -a                   # 连被 ignore 的也收(少用)

git stash list
git stash show -p              # 最近一条的 diff
git stash show -p stash@{2}

git stash apply                # 取回最近一条,stash 列表保留
git stash apply stash@{2}
git stash pop                  # apply 成功后删除该条

git stash drop stash@{1}
git stash clear                # 危险:清空整个 stash 列表

pop / apply 有冲突时:工作区会出现冲突标记,stash 条目不会被删除pop 失败 = 没 drop)。解决方式和普通冲突一样,见 09 章

不要这样用:

  • stash 完几天不管,stash 堆成「stash@{12}」,最后不敢 pop。每次加 -m 说明。
  • stash clear 当「清理垃圾」。
  • 以为 pop 冲突后条目一定丢了,于是再 reset --hard——这才会真丢工作区里解到一半的内容。

做错了怎么办:

bash
git stash list
git fsck --unreachable | head    # 高级:掉出引用的 stash 仍可能是 commit

stash 在 reflog 里:

bash
git reflog show stash

drop / clear 后,若 gc 还没跑,可用 git fsck --unreachableWIP on 提交,再 git stash apply <sha>。见 急救手册 · stash

未跟踪文件没有 -u 时不会进 stash,切分支后它们还留在磁盘;clean 才会删它们。

git worktree

作用: 同一个仓库检出第二份工作目录,绑在另一条分支上。两份目录共享 .git 对象,不必 stash 来回切。

改动范围: 新增/删除附加工作目录。主仓库历史不改写。

典型场景:

  • 一边等测试跑,一边要在 main 上热修。
  • review 别人的分支,又不想把自己的工作区弄脏。
  • 长时间并行两个需求,stash 已经不够用。

常用写法:

bash
git worktree list

# 在仓库平级目录再开一份,检出 hotfix
git worktree add ../demo-hotfix hotfix/timeout

# 同时创建新分支
git worktree add -b hotfix/timeout ../demo-hotfix main

git worktree remove ../demo-hotfix
# 目录已被手动删除时:
git worktree prune

限制:同一个分支不能同时检出在两个 worktree 里。

不要这样用: 把 worktree 目录当普通副本随便 rm -rf 后忘记 prune,或把 worktree 连同主仓库一起挪路径(绑定的是绝对路径,挪了要重新 add)。

做错了怎么办: 多出来的目录 worktree remove;列表里残留 stale,worktree prune。对象仍在主仓库,不会因为删附加目录丢掉 commit。

stash 还是 worktree

stashworktree
成本低,一条命令多一个目录
适合几分钟的打断并行几小时到几天
风险忘了 pop;clear 误删占磁盘;路径绑死
未跟踪文件要加 -u各目录独立

上一章:07 · 远程 · 下一章:09 · 冲突处理