Git 版本回退:reset、revert 与恢复方法
先判断提交是否已推送并被他人使用。仅在本地整理未共享的提交时可以用 reset;撤销共享分支上的改动,通常使用新增撤销提交的 revert。
| 命令 | 分支历史 | 文件内容 |
|---|---|---|
reset | 将当前分支指向指定提交 | 是否改变暂存区和工作区取决于模式 |
revert | 保留原提交,新增撤销提交 | 对指定提交的改动应用反向修改,并非完整恢复到某个历史快照 |
以下示例在目标仓库内执行。main、abc1234 和示例文件路径都要替换成实际值;不要把尖括号或中文括号当成命令参数。
reset 的使用方法
查看版本,确定要回退的时刻
sh
git status --short --branch
git branch --show-current
git log --oneline --decorate -15
git diff
git diff --cached先保存未提交和未跟踪文件,确认没有进行中的 merge、rebase 或 revert。下面的备份分支只保留当前提交,不保存未提交文件;如果已存在同名分支,换一个名字,不要覆盖它。
sh
git branch backup-before-reset
git show --stat abc1234回退操作
三种模式任选一种。目标提交之后的提交会离开当前分支的主线,备份分支仍可保留它们。
| 模式 | 暂存区 | 工作区 | 常见用途 |
|---|---|---|---|
--soft | 保持原样 | 保持原样 | 将本地提交重新整理为待提交改动 |
--mixed(默认) | 重置到目标提交 | 保持原样 | 撤销提交和暂存,保留文件修改 |
--hard | 重置到目标提交 | 重置到目标提交 | 明确丢弃本地改动,恢复目标内容 |
sh
# 保留暂存和工作区改动
git reset --soft abc1234sh
# 保留工作区改动,重新选择需要暂存的文件
git reset --mixed abc1234sh
# 仅在确认已备份、确需丢弃改动时执行
git reset --hard abc1234--hard 会覆盖受影响的已跟踪文件;妨碍写入目标文件的未跟踪路径也可能被删除。执行后用 git status、git log -5 --oneline 和项目自身测试确认结果。
恢复回退前的提交
优先查看 backup-before-reset。没有备份分支时,可从本地 reflog 找到 reset 前的提交:
sh
git reflog --date=local核对旧提交 SHA 后,先建立恢复分支,避免再一次覆盖当前状态。下面仍需将 abc1234 换为实际找到的旧提交。
sh
git branch recovered-before-reset abc1234
git show --stat recovered-before-resetreflog 是当前仓库的本地记录,会过期;已被回收的对象,以及从未提交或暂存过的文件内容,不能指望它恢复。切换到恢复分支前仍需保存当前工作区。
确需改写远端历史时的处理
未推送的本地提交回退无需强推。共享分支优先使用下方 revert;只有仓库维护者和协作者已确认改写范围、备份可恢复且分支规则允许时,才考虑强制更新。
在改写前先获取远端状态,确认当前历史包含远端已有提交,再记录即将替换的完整 SHA。下面以 main 为例,后续命令在同一终端执行:
sh
git fetch origin main
git log --oneline --left-right HEAD...origin/main
reset_old_main=$(git rev-parse refs/remotes/origin/main)如果输出显示尚未处理的远端提交,先停止并协调。完成约定的本地回退及验证后,只更新目标分支:
sh
test -n "${reset_old_main:-}" &&
git push --force-with-lease="refs/heads/main:$reset_old_main" origin HEAD:refs/heads/main远端 SHA 已改变时该命令会拒绝推送,应重新核对新增提交;不要改用 --force 绕过拒绝。推送后对照 git rev-parse HEAD 与 git ls-remote origin refs/heads/main。
revert 的使用方法
先确保工作区、暂存区干净,再查出要撤销的那一个提交。它不是“希望回到的版本”;撤销合并提交还涉及主线父提交,应另外核对,不能直接套用普通提交示例。
sh
git status --short
git log --oneline -15
git show abc1234
git revert --no-commit abc1234--no-commit 只将反向改动放入工作区和暂存区。成功后检查差异、运行项目验证,再明确创建撤销提交:
sh
git diff --cached
git diff --check
git commit -m "Revert the changes from abc1234"若出现冲突,先用 git status 找到冲突文件,手工解决并用 git add -- 实际文件路径 暂存,再依照 Git 提示使用 git revert --continue;结束后检查 git log -1 和暂存区,若 --no-commit 留下的改动尚未提交,再执行上述检查与 git commit。决定取消正在进行的撤销时使用 git revert --abort。
提交到远程
确认撤销提交和验证结果正确后,按仓库的评审流程提交;允许直接推送的 main 分支可执行普通推送:
sh
git push origin HEAD:main若远端有新提交导致拒绝,先同步并重新核对结果,不需要强推。
参考:git reset、git revert、git push 的 lease 保护。
Git 学习路径
如果目标是整理多个提交而非单纯回退,先查看 Git 合并与精简提交;需要重建分支提交记录时,继续阅读 Git 重置提交记录。