Skip to content

撤销暂存区

有时你 git add 了不该暂存的文件,或者需要重新整理暂存区的内容,这时需要取消暂存操作。

git restore --staged(新语法,推荐)

git restore --staged 将文件从暂存区移回工作区(取消暂存),工作区的修改保留:

bash
# 取消单个文件的暂存
git restore --staged README.md

# 取消多个文件的暂存
git restore --staged src/app.js src/utils.js

# 取消所有文件的暂存
git restore --staged .

效果: 文件从"已暂存"变为"已修改未暂存",工作区内容不变。

git reset HEAD(旧语法)

在 Git 2.23 之前的旧语法,仍然有效:

bash
# 取消单个文件的暂存
git reset HEAD README.md
git reset HEAD src/app.js

# 取消所有暂存
git reset HEAD
git reset       # 不带文件参数,取消所有暂存(默认 --mixed)

git reset HEAD <file> 将 HEAD 的内容还原到暂存区,相当于撤销了 git add 操作。

git reset HEAD:取消所有暂存

bash
# 取消所有已暂存的改动(不影响工作区)
git reset HEAD
git reset --mixed HEAD  # 等价,--mixed 是默认模式

实际场景

场景1:误将配置文件加入暂存区

bash
git add .          # 不小心把 .env 也加进去了
git status
# Changes to be committed:
#   new file: .env   ← 危险!

# 取消 .env 的暂存
git restore --staged .env

# 添加到 .gitignore
echo ".env" >> .gitignore
git add .gitignore

场景2:暂存了两个功能的改动,想分开提交

bash
# 错误操作:一次性暂存了所有改动
git add .

# 发现暂存了两个功能:auth 和 ui 改动
git status
# Changes to be committed:
#   modified: src/auth.js    ← 功能1:认证
#   modified: src/ui.js      ← 功能2:界面

# 取消 ui.js 的暂存
git restore --staged src/ui.js

# 先提交认证功能
git commit -m "feat: 实现用户认证功能"

# 再暂存并提交 UI 功能
git add src/ui.js
git commit -m "feat: 更新用户界面样式"

场景3:重新整理暂存区内容

bash
# 先取消所有暂存
git restore --staged .

# 使用交互式暂存,精细选择要暂存的内容
git add -p

与 git restore 的区别

容易混淆的两个命令:

bash
# 撤销暂存区(暂存区 → 工作区)
git restore --staged <file>    # 工作区改动保留

# 撤销工作区(丢弃工作区改动)
git restore <file>             # 工作区改动丢失!

完整的撤销顺序:

HEAD(最近提交)
    ↑ git restore --staged(取消暂存)
暂存区(Index)
    ↑ git restore(丢弃工作区改动)
工作区

新旧语法对比

操作新语法(推荐)旧语法
取消单个文件暂存git restore --staged <file>git reset HEAD <file>
取消所有暂存git restore --staged .git reset HEAD

总结

操作命令工作区改动
取消暂存(新语法)git restore --staged <file>保留
取消暂存(旧语法)git reset HEAD <file>保留
取消所有暂存git restore --staged .保留

取消暂存操作是安全的——它不会删除任何工作区的改动,只是将文件状态从"已暂存"变回"已修改"。