Skip to content

撤销暂存区

概述

暂存区(Staging Area)是 Git 的重要概念,文件在被提交前需要先添加到暂存区。本节将介绍如何撤销暂存区的修改。

理解暂存区

Git 的三个区域

工作区 (Working Directory)    暂存区 (Staging Area)    本地仓库 (Repository)
        │                            │                         │
        │      git add               │      git commit         │
        │  ──────────────────────>   │  ────────────────────>  │
        │                            │                         │
        │      git restore           │      git reset          │
        │  <──────────────────────   │  <────────────────────  │
        │       (--staged)           │       (--soft)          │

查看暂存区状态

bash
# 查看状态
git status
# Changes to be committed:
#   modified:   file.txt

# 查看暂存区内容
git diff --cached
git diff --staged

# 查看暂存区文件列表
git diff --cached --name-only

git restore --staged

git restore --staged 是撤销暂存区的推荐命令。

基本用法

bash
# 撤销指定文件的暂存
git restore --staged file.txt

# 撤销多个文件的暂存
git restore --staged file1.txt file2.txt

# 撤销当前目录下所有暂存的文件
git restore --staged .

# 撤销所有暂存的文件
git restore --staged :/

撤销部分暂存

bash
# 交互式选择要撤销暂存的内容
git restore --staged -p file.txt

# 或使用 --patch
git restore --staged --patch file.txt

同时撤销暂存和工作区

bash
# 同时撤销暂存区和工作区的修改
git restore --staged --worktree file.txt

# 或简写为
git restore -SW file.txt

# 同时撤销所有文件
git restore -SW .

git reset HEAD

git reset HEAD 是传统的撤销暂存方式。

基本用法

bash
# 撤销指定文件的暂存
git reset HEAD file.txt

# 撤销多个文件的暂存
git reset HEAD file1.txt file2.txt

# 撤销所有暂存的文件
git reset HEAD

# 或简写为
git reset

reset 的默认模式

bash
# git reset 默认使用 --mixed 模式
# 等同于
git reset --mixed HEAD

# 效果:
# 1. 暂存区被重置到 HEAD
# 2. 工作区保持不变
# 3. 文件从暂存区移回工作区

查看撤销效果

bash
# 撤销前
git status
# Changes to be committed:
#   modified:   file.txt

# 执行撤销
git reset HEAD file.txt

# 撤销后
git status
# Changes not staged for commit:
#   modified:   file.txt

部分撤销暂存

交互式撤销

bash
# 交互式选择要撤销暂存的部分
git reset -p

# 或使用 add 的反向操作
git add -p file.txt  # 添加部分到暂存区
# 然后使用 reset 撤销不需要的部分

使用 git add 覆盖

bash
# 如果只想保留文件的部分修改在暂存区
# 1. 先撤销整个文件的暂存
git restore --staged file.txt

# 2. 重新添加需要的部分
git add -p file.txt

使用补丁方式

bash
# 创建补丁
git diff --cached > staged-changes.patch

# 撤销暂存
git restore --staged .

# 选择性应用补丁
git apply -p staged-changes.patch

撤销场景示例

场景 1:撤销误添加的文件

bash
# 误添加了文件到暂存区
git add wrong-file.txt

# 撤销暂存
git restore --staged wrong-file.txt

# 或
git reset HEAD wrong-file.txt

场景 2:撤销部分文件的暂存

bash
# 添加了多个文件,但只想提交部分
git add .
git status
# Changes to be committed:
#   new file:   src/main.js
#   new file:   src/utils.js
#   new file:   test.js

# 不想提交 test.js
git restore --staged test.js

# 现在只有 src/ 下的文件在暂存区
git status
# Changes to be committed:
#   new file:   src/main.js
#   new file:   src/utils.js
# Untracked files:
#   test.js

场景 3:修改已暂存的文件

bash
# 文件已暂存
git add file.txt

# 又修改了文件
# 此时暂存区和工作区不一致

# 查看差异
git diff file.txt      # 工作区 vs 暂存区
git diff --cached      # 暂存区 vs HEAD

# 选择 1:撤销暂存,保留工作区修改
git restore --staged file.txt

# 选择 2:用工作区版本覆盖暂存区
git add file.txt

# 选择 3:用暂存区版本覆盖工作区
git restore file.txt

场景 4:撤销所有暂存

bash
# 暂存了多个文件
git add .

# 撤销所有暂存
git restore --staged .

# 或
git reset HEAD

场景 5:重新组织提交

bash
# 暂存了多个不相关的修改
git add .
git status
# Changes to be committed:
#   modified:   feature-a.js
#   modified:   feature-b.js
#   modified:   bugfix.js

# 想要分开提交
# 1. 撤销所有暂存
git restore --staged .

# 2. 分别添加和提交
git add feature-a.js
git commit -m "Add feature A"

git add feature-b.js
git commit -m "Add feature B"

git add bugfix.js
git commit -m "Fix bug"

暂存区操作对比

bash
# 添加到暂存区
git add file.txt

# 撤销暂存(保留工作区修改)
git restore --staged file.txt   # 新命令
git reset HEAD file.txt         # 旧命令

# 撤销暂存和工作区修改
git restore --staged --worktree file.txt  # 新命令
git checkout HEAD -- file.txt             # 旧命令
git reset --hard HEAD -- file.txt         # 不支持文件参数

查看暂存区详情

查看暂存区内容

bash
# 查看暂存区与 HEAD 的差异
git diff --cached
git diff --staged

# 查看暂存区与工作区的差异
git diff

# 查看暂存区文件列表
git ls-files --stage

# 查看暂存区文件内容
git show :file.txt

查看暂存区统计

bash
# 查看暂存区文件统计
git diff --cached --stat

# 查看暂存区文件数量
git diff --cached --numstat | wc -l

常见问题

撤销暂存后文件消失

bash
# 如果文件是新添加的(未跟踪)
git add new-file.txt
git restore --staged new-file.txt

# 文件回到未跟踪状态,不是消失
git status
# Untracked files:
#   new-file.txt

撤销暂存后想恢复

bash
# 撤销暂存后,工作区仍有修改
# 如果想恢复暂存,重新 add 即可
git add file.txt

部分撤销失败

bash
# 如果文件有冲突标记
# 需要先解决冲突
git status
# Unmerged paths:
#   both modified: file.txt

# 解决冲突后
git add file.txt

总结

  • git restore --staged 是撤销暂存的推荐命令
  • git reset HEAD 是传统的撤销方式
  • 撤销暂存不会影响工作区修改
  • 可以交互式选择要撤销的部分
  • 合理组织暂存区有助于创建清晰的提交

下一步

学习完撤销暂存区后,建议继续学习: