Skip to content

重置提交

概述

git reset 是 Git 中最强大但也最危险的命令之一。它可以移动分支指针,改变提交历史。理解 git reset 的三种模式对于安全地操作 Git 至关重要。

git reset 三种模式

模式概览

                    --soft              --mixed (默认)       --hard
                    │                   │                    │
HEAD 指针           │ 移动              │ 移动               │ 移动
暂存区              │ 不变              │ 重置               │ 重置
工作区              │ 不变              │ 不变               │ 重置

三种模式对比

模式HEAD暂存区工作区用途
--soft移动不变不变撤销提交,保留修改
--mixed移动重置不变撤销提交和暂存
--hard移动重置重置完全撤销,丢弃所有

--soft 模式

工作原理

# 重置前
HEAD -> C (暂存区和工作区都有 C 的内容)
        |
        B
        |
        A

# git reset --soft HEAD~1 后
HEAD -> B (暂存区和工作区仍保留 C 的修改)
        |
        A

# 提交 C 被撤销,但修改保留在暂存区

使用场景

bash
# 场景 1:撤销最近的提交,重新提交
git commit -m "WIP: feature"
# 发现提交信息不对,或想修改内容
git reset --soft HEAD~1
# 修改后重新提交
git commit -m "Add feature X"

# 场景 2:合并多个提交
git reset --soft HEAD~3
git commit -m "Combined commit"

# 场景 3:拆分提交
git reset --soft HEAD~1
# 重新选择要提交的内容
git add file1.txt
git commit -m "First part"
git add file2.txt
git commit -m "Second part"

操作示例

bash
# 查看当前状态
git log --oneline -3
# c3d4e5f (HEAD -> main) Third commit
# b2c3d4e Second commit
# a1b2c3d First commit

# 软重置到上一个提交
git reset --soft HEAD~1

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

# 暂存区保留了第三次提交的修改
# 可以重新编辑或直接提交

--mixed 模式

工作原理

# 重置前
HEAD -> C (暂存区和工作区都有 C 的内容)
        |
        B
        |
        A

# git reset --mixed HEAD~1 后
HEAD -> B (暂存区被重置,工作区保留 C 的修改)
        |
        A

# 提交 C 被撤销,修改保留在工作区(未暂存)

使用场景

bash
# 场景 1:撤销提交和暂存
git commit -m "Wrong commit"
git reset HEAD~1
# 等同于 git reset --mixed HEAD~1

# 场景 2:重新组织提交
git reset HEAD~2
# 修改在工作区,可以重新选择暂存内容

# 场景 3:撤销 git add
git reset file.txt
# 等同于 git restore --staged file.txt

操作示例

bash
# 查看当前状态
git log --oneline -3
# c3d4e5f (HEAD -> main) Third commit
# b2c3d4e Second commit
# a1b2c3d First commit

# 混合重置(默认模式)
git reset HEAD~1
# 或明确指定
git reset --mixed HEAD~1

# 查看状态
git status
# Changes not staged for commit:
#   modified:   file.txt

# 修改在工作区,但未暂存

--hard 模式

工作原理

# 重置前
HEAD -> C (暂存区和工作区都有 C 的内容)
        |
        B
        |
        A

# git reset --hard HEAD~1 后
HEAD -> B (暂存区和工作区都被重置)
        |
        A

# 提交 C 被撤销,所有修改丢失

使用场景

bash
# 场景 1:完全放弃最近的修改
git reset --hard HEAD~1

# 场景 2:恢复到干净状态
git reset --hard HEAD

# 场景 3:同步远程分支
git fetch origin
git reset --hard origin/main

# 场景 4:撤销错误的合并
git reset --hard ORIG_HEAD

操作示例

bash
# 警告:此操作不可逆!
git log --oneline -3
# c3d4e5f (HEAD -> main) Third commit
# b2c3d4e Second commit
# a1b2c3d First commit

# 硬重置
git reset --hard HEAD~1

# 查看状态
git status
# nothing to commit, working tree clean

# 所有修改已丢失
git log --oneline -3
# b2c3d4e (HEAD -> main) Second commit
# a1b2c3d First commit

回退到指定提交

使用提交哈希

bash
# 查看提交历史
git log --oneline
# e5f6g7h (HEAD -> main) Fifth commit
# d4e5f6g Fourth commit
# c3d4e5f Third commit
# b2c3d4e Second commit
# a1b2c3d First commit

# 回退到指定提交
git reset --hard b2c3d4e

# 当前状态
git log --oneline
# b2c3d4e (HEAD -> main) Second commit
# a1b2c3d First commit

使用相对引用

bash
# 回退 1 个提交
git reset HEAD~1

# 回退 3 个提交
git reset HEAD~3

# 回退到上一个提交
git reset HEAD^

# 回退到上上个提交
git reset HEAD^^

# 回退 5 个提交
git reset HEAD~5

使用分支名

bash
# 重置到远程分支
git reset --hard origin/main

# 重置到其他分支
git reset --hard feature

# 重置到标签
git reset --hard v1.0.0

恢复误操作

使用 ORIG_HEAD

bash
# Git 会在危险操作前保存 ORIG_HEAD
git reset --hard HEAD~1

# 恢复到操作前
git reset --hard ORIG_HEAD

使用 reflog

bash
# 查看操作历史
git reflog
# e5f6g7h (HEAD -> main) HEAD@{0}: reset: moving to HEAD~1
# f6g7h8i HEAD@{1}: commit: Fifth commit
# ...

# 恢复到指定操作
git reset --hard HEAD@{1}

# 或使用提交哈希
git reset --hard f6g7h8i

恢复流程

bash
# 1. 查看操作历史
git reflog

# 2. 找到误操作前的提交
# 例如:a1b2c3d HEAD@{5}: commit: Important work

# 3. 恢复
git reset --hard a1b2c3d

# 或使用 reflog 引用
git reset --hard HEAD@{5}

reset 常用技巧

撤销最近 N 个提交

bash
# 撤销最近 3 个提交,保留修改在暂存区
git reset --soft HEAD~3

# 撤销最近 3 个提交,保留修改在工作区
git reset HEAD~3

# 完全撤销最近 3 个提交
git reset --hard HEAD~3

修改最后一次提交

bash
# 方法 1:使用 --amend
git commit --amend

# 方法 2:使用 reset
git reset --soft HEAD~1
# 修改后重新提交
git commit -m "New message"

撤销合并

bash
# 撤销最近的合并
git reset --hard ORIG_HEAD

# 或指定合并前的提交
git reset --hard HEAD~1

同步远程分支

bash
# 本地分支落后于远程
git fetch origin
git reset --hard origin/main

# 注意:这会丢失本地未推送的提交

reset vs revert

bash
# reset:重置历史
git reset --hard HEAD~1
# 删除提交,改变历史

# revert:创建新提交来撤销
git revert HEAD
# 创建新提交,不改变历史

# 选择建议:
# - 本地未推送的提交:使用 reset
# - 已推送的公共提交:使用 revert

安全检查清单

bash
# 在执行 reset --hard 前,检查:

# 1. 是否有未提交的重要修改?
git status

# 2. 是否有未推送的重要提交?
git log origin/main..HEAD

# 3. 是否需要备份?
git branch backup-branch

# 4. 确认操作
git reset --hard HEAD~1

总结

  • --soft:撤销提交,保留暂存区和工作区
  • --mixed:撤销提交和暂存,保留工作区(默认)
  • --hard:完全撤销,丢弃所有修改
  • 使用 reflog 可以恢复误操作
  • 公共分支避免使用 reset,使用 revert

下一步

学习完重置提交后,建议继续学习: