如何撤销 git add 操作(取消暂存)
撤销暂存:git restore --staged <文件>(Git 2.23+)或旧语法 git reset HEAD <文件>;当前目录及子目录取消暂存用 git restore --staged .,全仓操作先到仓库根目录。只动暂存区,工作区改动原样保留。
Git 2.23 起:git restore --staged <文件>;老版本用 git reset HEAD <文件>。两者通常把该路径的索引内容恢复为 HEAD,而不是从索引移除整个跟踪文件,工作区的改动原样保留,不会丢代码。
用法
git restore --staged src/app.js # 单个文件
git restore --staged . # 当前目录及子目录;全仓先到根目录
git restore --staged src/ # 整个目录
# 旧语法(仍兼容)
git reset HEAD src/app.js
git reset # 全部取消暂存
首个提交前 HEAD 不存在,restore --staged 默认来源不可解析;新文件可用 git rm --cached -- 文件取消暂存并保留磁盘内容。HEAD^ 的示例则要求已有父提交。
三个"区"的关系
工作区 --git add--> 暂存区 --git commit--> 版本库
工作区 <--git restore-- 暂存区 <--git restore --staged-- 版本库状态
git restore --staged:暂存区 → 与 HEAD 一致(改动退回工作区);git restore:工作区 → 与暂存区一致(丢弃未暂存改动)。
常见问题(FAQ)
Q:add 错文件后直接 commit 了怎么办?
没推送:git reset --soft HEAD^ 撤销提交(改动回暂存区),再 git restore --staged 错文件 剔除后重新提交。
Q:新文件 add 后 restore --staged 会怎样?
若 HEAD 中没有该文件则回到未跟踪状态(也可能被忽略规则隐藏),文件本身还在磁盘上。
Q:有没有"只取消暂存但保留部分暂存内容"的操作?
有:git reset -p(交互式选择要取消暂存的块),与 git add -p 是反向操作的好搭档。