搜索 K
主题
git reset 是 Git 中最常用的撤销操作命令,用于移动 HEAD 指针和当前分支引用,从而实现取消暂存、撤销提交、重置工作区等操作。它是理解 Git 内部工作原理的关键命令之一。
git reset --hard 会永久丢弃工作区和暂存区的未提交修改。使用前请确认不需要这些更改,或已通过 git stash 保存。
git reset [<mode>] [<commit>]
git reset [-q] [<tree-ish>] [--] <pathspec>…
git reset [-q] [--pathspec-from-file=<file>] [<tree-ish>]
git reset --patch [<tree-ish>] [--] [<pathspec>…]要理解 git reset,必须先理解 Git 内部管理的三个区域(通常称为「三棵树」):
| 区域 | 说明 |
|---|---|
| Working Directory(工作区) | 你在编辑器中看到的实际文件 |
| Staging Area / Index(暂存区) | git add 后的文件快照,等待被提交 |
| HEAD(版本库) | 当前分支最新提交指向的快照,git commit 后更新 |
git reset 的核心作用就是控制这三棵树的状态回退到哪一步。
| 模式 | HEAD | 暂存区 (Index) | 工作区 (Working Dir) | 安全性 |
|---|---|---|---|---|
--soft | ✅ 移动 | ❌ 不变 | ❌ 不变 | 安全 |
--mixed | ✅ 移动 | ✅ 重置 | ❌ 不变 | 安全 |
--hard | ✅ 移动 | ✅ 重置 | ✅ 重置 | 危险 |
soft 只动头,mixed 加暂存,hard 全部清。
--soft:只移动 HEAD(提交记录回退,但修改保留在暂存区)--mixed:移动 HEAD + 重置暂存区(修改回到工作区,变成未 add 状态)--hard:移动 HEAD + 重置暂存区 + 重置工作区(所有修改全部丢弃)实际上 git reset 共有五种模式,除了常见的三种外,还有 --merge 和 --keep:
| 模式 | HEAD | 暂存区 | 工作区 | 安全性 |
|---|---|---|---|---|
--soft | ✅ | ❌ | ❌ | 安全 |
--mixed | ✅ | ✅ | ❌ | 安全 |
--hard | ✅ | ✅ | ✅ 全部重置 | 危险 |
--merge | ✅ | ✅ | ✅ 仅重置与目标提交不同的文件 | 较安全 |
--keep | ✅ | ✅ | ✅ 仅重置与目标提交不同的文件(保护本地修改) | 较安全 |
--merge:安全地中止合并 --merge 会重置暂存区,并将工作区中与目标提交不同的文件重置,但会保留你本地未暂存的修改(前提是这些修改的文件没有在 reset 涉及的提交中被改动)。如果发现工作区有未暂存的修改会与 reset 冲突,则操作会被拒绝。
# 典型场景:中止一个有冲突的合并
git merge feature-branch
# 产生了合并冲突,不想继续了
git reset --merge
# 等价于 git merge --abort
# 另一个场景:回退提交,但保留不冲突的本地修改
git reset --merge HEAD~1--merge vs --hard--hard 无条件丢弃所有未提交的修改;--merge 则会检查:如果你有本地修改的文件不在 reset 涉及的变更范围内,这些修改会被保留。如果冲突,reset 会直接报错而不是悄悄覆盖。
--keep:保守的 reset --keep 与 --merge 类似,但更加保守。它会重置暂存区和工作区中与目标提交不同的文件,但如果工作区中存在任何未提交的修改(无论是否与 reset 冲突),都会拒绝执行。
# 只有在工作区干净时才能成功
git reset --keep HEAD~1--keep 的适用场景--keep 最常见的用途是在分支间快速移动 HEAD 时保护未提交的工作:
# 你在 feature 分支上有未提交的修改
# 想把分支指针移动到 origin/feature 的最新提交
# 但不想丢失本地修改
git fetch origin
git reset --keep origin/feature
# 如果本地修改与远程变更冲突,会报错而不是覆盖--soft:只移动 HEAD 将 HEAD 指针移动到指定提交,但暂存区和工作区保持不变。所有被「撤销」的提交中的修改会出现在暂存区中,处于「已 add 待 commit」的状态。
# 撤销最近一次提交,修改保留在暂存区
git reset --soft HEAD~1
# 撤销最近三次提交,所有修改合并到暂存区
git reset --soft HEAD~3你提交了三次琐碎的 commit,想合并成一个有意义的提交:
# 当前历史:C1 → C2 → C3 → C4 (HEAD)
# 想把 C2、C3、C4 合并成一个提交
git reset --soft HEAD~3
git commit -m "feat: 完成用户认证模块"
# 结果:C1 → C5 (HEAD),C5 包含 C2+C3+C4 的所有修改虽然 git commit --amend 更常用,但 --soft 也能做到:
git reset --soft HEAD~1
git commit -m "新的提交信息"--mixed:移动 HEAD + 重置暂存区(默认模式) 这是 git reset 的默认模式(不指定任何标志时的行为)。HEAD 移动到指定提交,暂存区重置为该提交的状态,但工作区保持不变。被撤销的修改会出现在工作区中,处于「未 add」的状态。
# 以下两条命令等价
git reset HEAD~1
git reset --mixed HEAD~1
# 取消暂存某个文件(不改变提交历史)
git reset HEAD file.txt你执行了 git add . 把所有文件都加入了暂存区,但其中某个文件不想提交:
# 取消暂存单个文件
git reset HEAD config/local.yml
# 取消暂存所有文件
git reset HEAD从 Git 2.23 起,可以使用语义更清晰的命令:
git restore --staged file.txt你想撤销上一次提交,并重新选择要提交的文件:
git reset HEAD~1
# 此时所有修改在工作区(未暂存状态)
git add src/feature.ts
git commit -m "feat: 只提交核心功能"
# 剩余修改留在工作区,可以在下次提交--hard:移动 HEAD + 重置暂存区 + 重置工作区 HEAD 移动到指定提交,暂存区和工作区都被强制重置为该提交的状态。所有未提交的修改(包括暂存的和未暂存的)都会被永久丢弃。
# 彻底丢弃最近一次提交及其所有修改
git reset --hard HEAD~1
# 彻底回退到指定提交
git reset --hard abc1234
# 丢弃所有未提交的修改(不改变提交历史)
git reset --hard HEAD--hard 模式下,未提交的修改会永久丢失,无法通过 git reflog 找回(reflog 只记录提交,不记录工作区和暂存区的状态)。
唯一可能的补救:如果文件之前被 git add 过,其 blob 对象可能还在 .git/objects/ 中,可以尝试 git fsck --lost-found 找回。
你的工作区搞乱了,想恢复到最新提交的干净状态:
git reset --hard HEAD你提交了错误的代码,想完全抹除这次提交:
git reset --hard HEAD~1本地分支和远程分支偏离了,想强制与远程保持一致:
git fetch origin
git reset --hard origin/main假设当前状态如下,HEAD 在 C3 提交上,且有未提交的修改:
执行 git reset <mode> HEAD~2(回退两个提交到 C1)后的结果:
git reset 还可以作用于单个文件,但此时不会移动 HEAD,只会将指定文件在暂存区的状态回退。
# 将文件从暂存区移回工作区(取消 git add)
git reset [<commit>] -- <file>
# 等价于(Git 2.23+)
git restore --staged <file># 取消暂存单个文件
git reset HEAD -- src/config.ts
# 取消暂存某个目录下的所有文件
git reset HEAD -- src/
# 将暂存区的文件回退到某个历史版本(工作区不变)
git reset abc1234 -- src/config.ts--hardgit reset --hard -- <file> 是不合法的。如果你想丢弃工作区中某个文件的修改,应该使用:
git checkout -- <file>
# 或 Git 2.23+
git restore <file>--patch 交互模式 git reset --patch(或 -p)允许你逐块选择要从暂存区移除的修改,而不是一次性操作整个文件。
# 交互式选择要取消暂存的代码块
git reset -p
# 针对特定文件
git reset -p -- src/main.ts交互提示中的选项:
| 按键 | 含义 |
|---|---|
y | 取消暂存此代码块 |
n | 保持此代码块在暂存区 |
s | 将当前块拆分成更小的块 |
e | 手动编辑此代码块 |
q | 退出,后续代码块保持不变 |
a | 取消暂存当前文件的此块和后续所有块 |
d | 保留当前文件的此块和后续所有块 |
git reset -p 和 git add -p 是一对互补操作:
git add -p:逐块选择要加入暂存区的修改git reset -p:逐块选择要移出暂存区的修改<commit> 参数的常见写法 | 写法 | 含义 |
|---|---|
HEAD | 当前提交 |
HEAD~1 或 HEAD~ | 上一个提交 |
HEAD~3 | 往前第 3 个提交 |
HEAD^ | 当前提交的第一个父提交(与 HEAD~1 类似) |
HEAD^2 | 当前提交的第二个父提交(合并提交时才有意义) |
abc1234 | 指定 commit SHA(可以只写前几位) |
origin/main | 远程分支的最新提交 |
v1.0 | 标签指向的提交 |
@{2} | HEAD 两次移动前的位置(来自 reflog) |
git reflog 记录了 HEAD 的每一次移动,是 git reset 误操作后的救命稻草。
# 1. 查看 reflog,找到误操作前的 SHA
git reflog
# 输出类似:
# abc1234 HEAD@{0}: reset: moving to HEAD~3 ← 这是误操作
# def5678 HEAD@{1}: commit: 重要的功能提交 ← 这是你想恢复的
# ghi9012 HEAD@{2}: commit: 另一个提交
# 2. 恢复到误操作前的提交
git reset --hard def5678
# 或使用 reflog 语法
git reset --hard HEAD@{1}reflog 记录默认保留 90 天。超过此期限或执行 git reflog expire --expire=now + git gc 后,记录会被清除。
另外,reflog 是本地的,不会被 push 到远程仓库,也不会被 clone 下来。
git reflog 记录的是提交级别的 HEAD 移动。如果你用 --hard 丢弃了从未被 git commit 过的工作区修改,reflog 无法帮你找回。
Git 在执行 reset、merge、rebase 等危险操作前,会自动将当前 HEAD 的值保存到 ORIG_HEAD 引用中。这是一个比 reflog 更直接的恢复手段。
# 执行 reset 后立即后悔
git reset --hard HEAD~3
# 一步恢复(无需查看 reflog)
git reset --hard ORIG_HEADORIG_HEAD 只记录最近一次危险操作前的 HEAD 位置。如果连续执行两次 reset,第一次的 ORIG_HEAD 会被第二次覆盖。需要更完整的历史请使用 git reflog。
# 查看 ORIG_HEAD 指向的提交
git log -1 ORIG_HEAD
# 对比当前 HEAD 和 ORIG_HEAD 的差异
git diff ORIG_HEAD..HEAD当 HEAD 不指向任何分支(detached HEAD)时,git reset 仍然可以使用,但行为有所不同:
# 进入 detached HEAD 状态
git checkout abc1234
# 此时 reset 只移动 HEAD,不影响任何分支
git reset --soft HEAD~1
# HEAD 移到上一个提交,但没有分支跟着移动
# 回到正常状态
git checkout main在 detached HEAD 状态下使用 git reset --hard,被跳过的提交如果没有任何分支或标签指向它们,将成为悬空对象,最终被 git gc 清理。务必先创建分支保存重要提交:
# 在 reset 前先保存当前位置
git branch backup-branch
git reset --hard HEAD~2当你正在合并(git merge)过程中遇到冲突时,可以用 reset 中止合并:
# 开始合并
git merge feature-branch
# 产生冲突...
# 方式 1:使用 reset 中止(回到合并前的状态)
git reset --hard HEAD
# 等价于
git merge --abort
# 方式 2:使用 --merge 模式(保留与合并无关的本地修改)
git reset --mergeMERGE_HEAD合并过程中,Git 会创建 .git/MERGE_HEAD 文件。git reset --hard HEAD 或 git reset --merge 会自动清理这个文件,使仓库回到干净状态。
如果 git rebase 过程中出了问题:
# rebase 过程中遇到冲突,想完全放弃
git rebase --abort
# 这比 git reset 更合适,因为它会恢复 rebase 前的完整状态
# 但如果 rebase 已经完成了,想撤销整个 rebase 的结果
git reset --hard ORIG_HEADgit stash 和 git reset 经常配合使用,形成安全的工作流。
# 有未提交的修改,但想 hard reset
# 先 stash 保存修改
git stash push -m "reset 前的备份"
# 安全地执行 hard reset
git reset --hard HEAD~3
# 如果需要恢复之前的修改
git stash pop
# 注意:如果 stash 的修改与 reset 后的代码冲突,会产生合并冲突# stash 当前修改
git stash
# reset 到目标提交
git reset --hard origin/main
# 查看 stash 中的内容
git stash show -p
# 选择性应用(不自动删除 stash)
git stash apply
# 或完全不应用(丢弃 stash)
git stash drop# 你不小心在 main 上做了提交,想移到 feature 分支
# 当前:main 上有 2 个不该提交的 commit
# 1. soft reset 保留修改在暂存区
git reset --soft HEAD~2
# 2. stash 暂存区的修改
git stash
# 3. 切到正确的分支
git checkout -b feature-branch
# 4. 恢复修改并提交
git stash pop
git commit -m "feat: 正确的功能提交"理解 git reset 的内部实现有助于更深入地掌握它。
Git 的核心是一个内容寻址的文件系统,所有数据以四种对象存储:
# 假设当前状态
git log --oneline
# abc1234 (HEAD -> main) 第三次提交
# def5678 第二次提交
# ghi9012 第一次提交git reset --soft HEAD~1 的内部操作:
实际上 git reset 做了这些事:
.git/refs/heads/main 的内容从 abc1234 改为 def5678.git/index 文件重写为 def5678 提交对应的 tree 快照def5678 的 tree 中记录的状态abc1234 这个 commit 对象仍然存在于 .git/objects/ 中,只是没有任何引用(分支、标签)指向它了。它会在以下情况被清理:
git gc 运行时(自动或手动触发)gc.pruneExpire 值)# 查看 HEAD 指向
cat .git/HEAD
# ref: refs/heads/main
# 查看分支指向的提交
cat .git/refs/heads/main
# def5678...
# 查看某个提交对象的内容
git cat-file -p def5678
# 查看暂存区内容
git ls-files --stage
# 查看悬空对象
git fsck --dangling对已推送的提交执行 reset 后强制推送,是团队协作中最常见也最严重的 Git 事故。
# ❌ 危险操作
git reset --hard HEAD~3
git push --force origin main
# 其他人的 pull/push 全部出问题!
# ✅ 正确做法
git revert HEAD~3..HEAD
git push origin maingit reset --hard 不会删除未跟踪文件(untracked files)。如果你需要完全干净的工作区:
git reset --hard HEAD
git clean -fd # 删除未跟踪的文件和目录
git clean -fdx # 还包括 .gitignore 中的文件(如 node_modules)git reset HEAD~1(mixed 模式)会把修改放回工作区。如果你直接 git commit,会得到一个空提交(因为暂存区是空的)。
git reset HEAD~1
# ❌ 直接 commit → 空提交(暂存区为空)
git commit -m "..."
# ✅ 正确:先 add 再 commit
git add .
git commit -m "..."即使你是唯一的开发者,如果 CI/CD 系统正在基于某个提交构建或部署,reset + force push 可能导致构建失败或部署混乱。
git reset --hard 不会清除 stash 列表。stash 中保存的修改在 reset 后仍然存在:
# stash 不受 reset 影响
git stash list
# stash@{0}: WIP on main: abc1234 some work
git reset --hard HEAD~5
git stash list
# stash@{0}: WIP on main: abc1234 some work ← 仍然在养成以下习惯,大幅降低 reset 误操作的风险:
git stash — 保存当前工作区的修改git branch backup — 创建备份分支--soft 或 --mixed — 除非确定要丢弃修改,否则不用 --hardgit log origin/main..HEAD 确认要推送的提交--force-with-lease 替代 --force — 防止覆盖他人的提交| 对比项 | git reset | git revert |
|---|---|---|
| 原理 | 移动 HEAD,删除提交记录 | 新建一个反向提交 |
| 提交历史 | 改写历史(提交消失) | 保留历史(新增一个撤销提交) |
| 远程协作 | 需要 --force 推送,影响协作者 | 正常 push,不影响协作者 |
| 适用场景 | 本地未推送的提交 | 已推送到远程的提交 |
| 安全性 | 可能丢失数据(--hard) | 安全,不丢失任何数据 |
已推送到远程的提交,用 revert;本地未推送的提交,用 reset。
对已推送的提交使用 reset + force push 会破坏其他协作者的提交历史,可能导致灾难性后果。
| 命令 | 作用 | 是否移动 HEAD | 是否修改暂存区 | 是否修改工作区 |
|---|---|---|---|---|
git reset --soft | 回退提交 | ✅ | ❌ | ❌ |
git reset --mixed | 回退提交 + 取消暂存 | ✅ | ✅ | ❌ |
git reset --hard | 彻底回退 | ✅ | ✅ | ✅ |
git reset HEAD <file> | 取消暂存某文件 | ❌ | ✅ | ❌ |
git checkout -- <file> | 丢弃工作区某文件的修改 | ❌ | ❌ | ✅ |
git restore <file> | 丢弃工作区某文件的修改(2.23+) | ❌ | ❌ | ✅ |
git restore --staged | 取消暂存(2.23+) | ❌ | ✅ | ❌ |
从 Git 2.23 开始,git checkout 被拆分为两个语义更清晰的命令:
git switch:切换分支git restore:恢复文件推荐使用新命令,避免 checkout 的多重含义带来的混淆。
| 目标 | reset | commit --amend |
|---|---|---|
| 修改最后一次提交的信息 | git reset --soft HEAD~1 + 重新 commit | git commit --amend -m "新信息" |
| 补充遗漏的文件到上次提交 | git reset --soft HEAD~1 + add + commit | git add <file> + git commit --amend |
| 合并多次提交 | git reset --soft HEAD~N + 重新 commit | 不支持 |
| 彻底丢弃上次提交 | git reset --hard HEAD~1 | 不支持 |
# 当前历史
# abc1234 fix: 修复空指针
# def5678 fix: 补充单元测试
# ghi9012 feat: 用户登录功能
# jkl3456 chore: 初始化项目
# 想把最近三个提交合并成一个
git reset --soft HEAD~3
git commit -m "feat: 完成用户登录功能(含测试和修复)"
# 结果:jkl3456 → 新提交 (HEAD)git add(取消暂存) # 不小心 git add 了不该提交的文件
git add .
# 取消暂存特定文件
git reset HEAD -- .env
git reset HEAD -- node_modules/
# 或取消所有暂存
git reset HEAD# 工作区和暂存区都乱了,想回到最新提交的干净状态
git reset --hard HEAD
# 如果还有新创建的未跟踪文件,需要额外清理
git clean -fdreset --hard + clean -fd 组合git reset --hard HEAD 只会重置已被 Git 跟踪的文件。新创建的未跟踪文件(untracked files)不受影响。 要彻底清理工作区,需要配合 git clean -fd(删除未跟踪的文件和目录)。
# 本地 main 分支和 origin/main 偏离了
# 放弃本地修改,强制与远程保持一致
git fetch origin
git reset --hard origin/main# 不改变 HEAD,只把某个文件回退到 3 个版本前的状态
git reset HEAD~3 -- src/config.ts
# 此时 src/config.ts 在暂存区是旧版本
# 需要 commit 才能生效
# 或者用 restore(更直观)
git restore --source HEAD~3 -- src/config.ts# 上一次提交包含了太多修改,想拆分
git reset HEAD~1
# 所有修改回到工作区
# 分批 add 和 commit
git add src/auth/
git commit -m "feat: 认证模块"
git add src/api/
git commit -m "feat: API 路由"
git add tests/
git commit -m "test: 添加测试"git reset 和 git reset HEAD 有什么区别?没有区别。当不指定 <commit> 参数时,默认是 HEAD。
# 以下两条命令等价
git reset
git reset HEAD
# 以下两条也等价
git reset -- file.txt
git reset HEAD -- file.txt提交对象并没有被立即删除,它们仍然存在于 .git/objects/ 中,只是没有任何引用指向它们了(成为了「悬空对象」)。
找回方法:
# 通过 reflog 找回
git reflog
git reset --hard <sha>
# 通过 fsck 查找悬空对象
git fsck --lost-found这些悬空对象会在 git gc 运行时被清理(默认在对象创建 2 周后)。
技术上可以,但强烈不推荐:
# 本地 reset
git reset --hard HEAD~1
# 强制推送到远程(危险!)
git push --force origin main
# 或使用更安全的 --force-with-lease
git push --force-with-lease origin main--force-with-lease 比 --force 更安全,它会检查远程分支是否有其他人推送的新提交。如果有,推送会被拒绝。
但最佳实践仍然是对已推送的提交使用 git revert。
git reset HEAD~1 和 git reset HEAD^ 一样吗?在大多数情况下是一样的。但含义略有不同:
HEAD~1:HEAD 的第一代祖先(沿第一父提交回溯 1 步)HEAD^ / HEAD^1:HEAD 的第一个父提交区别体现在合并提交(merge commit)中:
# 合并提交有两个父提交
# C4 (HEAD) ← merge commit
# / \
# C3 C2
# \ /
# C1
#
# HEAD~1 = HEAD^ = HEAD^1 = C3(第一个父提交,通常是你所在的分支)
# HEAD^2 = C2(第二个父提交,通常是被合并进来的分支)
# HEAD~2 = C1(沿第一父提交回溯 2 步)HEAD~1 报错?PowerShell 中 ~ 是用户主目录的别名,可能导致解析问题。解决方式:
# 方式 1:用引号包裹
git reset --soft "HEAD~1"
# 方式 2:使用 HEAD^ 替代
git reset --soft "HEAD^"
# 方式 3:使用 Git Bash 代替 PowerShell--merge 和 --keep 什么时候用?这两个模式在日常开发中不太常见,但在特定场景下非常有用:
--merge:最适合中止一个有冲突的合并。它等价于 git merge --abort,但在回退提交时比 --hard 更安全,因为它会保护与 reset 无关的本地修改。--keep:适合在拉取远程更新时保护本地修改。如果有冲突风险,它会直接拒绝而不是覆盖。简单记忆:不确定用哪个时,优先试 --keep。它是最保守的,不会意外丢失数据。
ORIG_HEAD 和 reflog 有什么区别?| 对比项 | ORIG_HEAD | git reflog |
|---|---|---|
| 记录数量 | 只保留最近一次 | 保留所有(默认 90 天) |
| 覆盖范围 | reset / merge / rebase | 所有 HEAD 移动(含 commit) |
| 使用便捷性 | 直接使用,无需查找 | 需要先查看再选择 SHA |
| 适用场景 | 刚刚执行完想立即撤销 | 需要回到更早的某个状态 |
git reset 默认不会递归地重置子模块。子模块的工作区和提交状态不受影响。如果需要同时重置子模块:
# 重置主仓库
git reset --hard HEAD~1
# 同步子模块到主仓库记录的版本
git submodule update --init --recursivegit reset 只能回退到某个提交,会连带撤销该提交之后的所有提交。如果你只想撤销中间某一个提交,应该使用 git revert:
# reset 会撤销 C3 和 C4
# C1 → C2 → C3 → C4 (HEAD)
git reset --hard HEAD~2 # 回到 C2,C3 和 C4 都消失
# revert 只撤销 C3,保留 C4
git revert <C3-的-SHA> # 创建 C3' 反向提交,C4 不受影响| 目标 | 命令 |
|---|---|
| 取消暂存所有文件 | git reset HEAD |
| 取消暂存单个文件 | git reset HEAD -- <file> |
| 撤销提交,保留在暂存区 | git reset --soft HEAD~1 |
| 撤销提交,保留在工作区 | git reset HEAD~1 |
| 彻底撤销提交 | git reset --hard HEAD~1 |
| 丢弃所有本地修改 | git reset --hard HEAD |
| 丢弃所有修改(含未跟踪) | git reset --hard HEAD + git clean -fd |
| 合并最近 N 次提交 | git reset --soft HEAD~N + git commit |
| 同步远程分支 | git fetch + git reset --hard origin/<branch> |
| 交互式取消暂存 | git reset -p |
| 目标 | 命令 |
|---|---|
| 中止有冲突的合并 | git reset --merge 或 git merge --abort |
| 安全回退(保护本地修改) | git reset --keep HEAD~1 |
| 恢复上一次 reset | git reset --hard ORIG_HEAD |
| 恢复任意 reset 误操作 | git reflog + git reset --hard <sha> |
| 移动提交到另一个分支 | git reset --soft HEAD~N → git stash → 切换分支 → git stash pop + git commit |
| 安全 hard reset(先备份) | git stash push -m "备份" → git reset --hard ... |
| 撤销已完成的 rebase | git reset --hard ORIG_HEAD |
| 查看 ORIG_HEAD | git log -1 ORIG_HEAD |
| 对比 reset 前后差异 | git diff ORIG_HEAD..HEAD |
| 查看悬空对象 | git fsck --dangling |
当你需要撤销操作时,参考以下决策流程:
git reflog — 查看 HEAD 的移动历史,用于恢复 reset 误操作git clean — 删除未跟踪的文件,配合 reset --hard 彻底清理工作区