先别执行 reset --hard,也不要 push -f。撤销提交后想恢复,第一步是确认那次提交对象是否仍在本地仓库里:只要 git reflog 还能看到对应的 SHA,无论用过 reset、revert 还是切错过分支,通常都能把代码找回来。真正难恢复的只有两种情况:工作区文件从没提交过、又被 git clean -fd 删掉;以及远程仓库被强推覆盖、且本地唯一的克隆也已经做过 gc。下面的顺序是先留退路、再定位、再动手。
适用场景:本地已提交但想撤回,或撤回后发现代码不对。动作:先
git tag backup/before-recover HEAD打标签,再用git reflog --date=iso找目标提交,未推送用git reset,已推送用git revert,错分支用git cherry-pick。验证:git diff <commit> HEAD --stat为空、git status干净、git fsck无异常。边界:未提交的文件被删除只能靠编辑器本地历史或 stash 找回;强推覆盖的远程提交需要其他克隆或平台审计记录。
Git撤销提交的代码怎么恢复原状态
「恢复原状态」在多数人手里其实指三种不同结果,先分清是哪一种,命令完全不一样:把工作区文件恢复成某次提交的样子、把分支指针退回某次提交、把某次提交的改动从历史里抵消掉。确认办法是看 git status 和 git reflog 两个输出:git status 显示 nothing to commit, working tree clean 说明文件层面已经对齐,问题在历史层面;显示一堆 deleted: 或 modified: 说明只是工作区被改动。
git reflog --date=iso | head -30 是判断的关键位置,输出每行形如 a1b2c3d HEAD@{3}: reset: moving to HEAD~1,冒号后就是那次动作的类型。看到 reset: moving to,说明分支指针被移动过,原来的提交大概率还在列表更下方;看到 commit (amend),说明是改写上一次提交;看到 rebase (finish),说明历史被整体重排,需要按 rebase 的方式找回。把 reflog 里你怀疑的那个 SHA 记下来,下一步所有操作都围绕它做。
# 0. 动手前先留退路,标签名写死,避免依赖 date 命令
git tag backup/before-recover HEAD
# 1. 找出被撤销的那次提交
git reflog --date=iso | head -30
git log --oneline --graph --all -n 30
# 2. 看清那次提交到底改了什么
git show a1b2c3d --stat
git show a1b2c3d -- path/to/file
# 3. 按场景选一条
git revert a1b2c3d # 已推送到共享分支
git reset --soft a1b2c3d^ # 未推送,想保留改动重新组织提交
git reset --hard a1b2c3d # 未推送,确认丢弃工作区改动(不可逆)
git cherry-pick a1b2c3d # 提交在别的分支上,只想把改动拿过来
执行前把 a1b2c3d 换成 reflog 里查到的真实 SHA。--hard 之前务必确认 git status 没有未提交的改动,或者先 git stash push -u -m before-recover。
Git撤销提交的代码先定位在哪一层
改错位置的代价是反复回滚。按下面五层顺序判断,命中即停:
- 工作区层:改动没提交过。检查
git status、git diff。这一层用git restore <file>或git checkout -- <file>,跟 reflog 无关。 - 暂存区层:已
git add未提交。检查git status里Changes to be committed段,git diff --cached看内容。用git restore --staged <file>撤回暂存。 - 本地分支层:已提交未推送。检查
git log @{u}..HEAD --oneline,有输出说明领先远程,可以安全reset。 - 远程共享层:已推送。检查
git log HEAD..@{u} --oneline与平台 Commits 页面,这层只能revert,不要强推。 - 历史重写层:做过 rebase、amend、filter-branch。检查
git reflog是否出现rebase、commit (amend)字样,恢复要回到 rebase 之前的 SHA。
判断依据是远程跟踪分支:git branch -vv 会显示每个分支的 upstream 和领先/落后数量,[ahead 2] 表示这两次提交还没推送,属于可以安全改写的范围。
Git撤销提交的代码:先看这四个位置
- 日志(reflog 与全分支图):
git reflog --date=iso看操作流水,git log --oneline --graph --all --decorate -n 40看分支关系,git fsck --lost-found找悬空提交(dangling commit),被删除的分支提交常出现在这里。 - 命令输出:
reset、revert、cherry-pick的回显。冲突时git status会列出both modified文件;git revert --abort、git cherry-pick --abort、git rebase --abort用于退出卡住的状态。注意git stash list是否还留着之前的暂存。 - 配置项:
git config --list --show-origin | grep -E 'alias|user|hooks'。别名被改写成带reset --hard的自定义命令、core.hooksPath指向的钩子在提交时改动文件,都可能让“撤销”行为和预期不一致;.git/config里的[branch "xxx"] remote/merge决定@{u}指向哪个远程分支。 - 面板字段:GitHub 仓库的
Commits、Branches、Settings → Branches(分支保护是否禁止强推);GitLab 的Repository → Commits与Settings → Repository → Protected branches;Gitee 的代码 → 提交。另看Pull requests里是否有未关闭的 MR 引用着被撤销的提交。
Git撤销提交的代码:按可能性从高到低排除
一、reset --hard 把工作区未提交的改动一起丢了。 确认动作:git reflog 里能看到那次 reset,但 git status 干净且文件内容不对。处理:已提交部分用 git reset --hard <reset前的SHA> 找回;未提交部分查 git stash list,再看编辑器的 Local History(VS Code 的 Timeline、JetBrains 的 Local History → Show History),这类内容不进 Git 对象库,reflog 帮不上。

二、revert 之后又想恢复被抵消的改动。 确认动作:git log --oneline -n 5 看到 Revert "..." 提交。处理:对那个 revert 提交再执行一次 git revert <revert的SHA>,等价于把改动加回来,这是共享分支上最稳的做法。
三、强推覆盖了远程提交。 确认动作:git ls-remote origin refs/heads/<branch> 得到的 SHA 与本地 git rev-parse HEAD 不一致,且平台 Commits 页面少了记录。处理:从其他同事的克隆里 git reflog 或平台的事件/审计记录中找原 SHA,git fetch origin <SHA> 后建分支;分支保护开启时强推会被拒绝,先看 Settings → Branches 的规则。
四、提交恢复到错的分支,或者根本不在当前分支上。 确认动作:git log --all --oneline --source | grep <关键词> 看该提交被哪些分支引用。处理:切到正确分支后 git cherry-pick <SHA>,冲突时按 git status 提示逐个解决再 git cherry-pick --continue。
五、文件被 git clean -fd 或误删。 确认动作:git status 里没有相关记录,git log --all -- <path> 也查不到。处理:只能依靠 IDE 本地历史、系统回收站、备份或构建产物里的副本,Git 本身没有记录未跟踪文件。
Git撤销提交的代码:改完怎么确认真的解决了
恢复动作执行完,先跑三项核对:git status 应为 working tree clean;git diff <目标SHA> HEAD --stat 输出为空表示与目标状态一致;git log --oneline --graph --all -n 20 确认分支指针落在预期位置、没有多余的分叉。若涉及远程,用 git ls-remote origin refs/heads/<branch> 与本地 git rev-parse HEAD 对比 SHA,一致才算推送同步完成。
观察窗口不建议只看命令回显:至少再完成一次正常提交加推送,并跑一次本地构建或测试(npm run build、mvn -q test 之类,按项目实际脚本替换),确认文件内容与编译结果都正常,才算稳定。如果这次撤销影响过共享分支,还要等下一次 CI 运行结束、相关 MR 重新指向正确提交后再收尾。
回滚办法在第 0 步已经准备好:git reset --hard backup/before-recover 可以退回动手前的状态,远程分支则用 git push origin backup/before-recover:refs/heads/<branch> 重建(分支保护会拦截时改走 MR)。确认无误后再删除临时标签:git tag -d backup/before-recover。标签保留期间不要执行 git gc --prune=now,否则悬空对象被清理,reflog 之外的找回路径会断掉。