动手恢复前,先回答三个问题:
不同答案,处理方式完全不同。
| 当前状态 | 先做什么 | 推荐处理 | 避免什么 |
|---|---|---|---|
| 代码还没提交 | git status、必要时 git stash push -u |
用 git restore、git stash、手工移动文件保留现场 |
直接 git reset --hard |
| 已提交,还没 push | git log --oneline -5、git reflog -10 |
可以用 reset、commit --amend、rebase -i 整理本地历史 |
整理前不留备份分支 |
| 已 push,但没人基于它开发 | 先确认远端分支和团队状态 | 优先 git revert,确实要整理历史时先沟通再 push --force-with-lease |
直接 push --force |
| 已 push,且有人基于它开发 | 先通知协作者,确认影响范围 | 用新 commit 修正,公共分支优先 revert |
改写公共历史 |
| secret 已经提交 | 立即废弃并轮换 secret | 再清理 Git 历史和平台缓存 | 只做 revert 就结束 |
| force push 覆盖远端 | 找到仍保留正确提交的人或本地 reflog | 用正确 commit 恢复远端分支 | 继续在错误分支上叠加提交 |
如果不确定自己属于哪一类,先只执行只读命令:
git status
git log --oneline --decorate -10
git reflog -10
git branch -vv
不要急着执行会改写工作区或历史的命令。
先保存现场:
git status
git log --oneline --decorate -10
git reflog -10
如果工作区还有未提交代码,先临时保存:
git stash push -u -m "backup-before-recovery"
你在 main 上提交了本来应该在 feature 分支里的 commit。
git status
git log --oneline -5
git branch feat/right-branch
git reset --hard HEAD~1
git switch feat/right-branch
这会把当前 commit 保留到新分支,并让原分支回到提交前。
如果已经 push,优先新建 PR 修正,不要直接重写公共分支历史。
可以:
git switch -c feat/right-branch <commit-sha>
git push -u origin feat/right-branch
然后在原分支上用 revert 撤销:
git revert <commit-sha>
git reflog
找到 reset 前的位置:
git reset --hard HEAD@{1}
如果不确定,先创建备份分支:
git branch backup-before-recover HEAD@{1}
git reflog
git branch recovered-work <commit-sha>
git switch recovered-work
只要 commit 还在 reflog 里,通常可以救回来。
可以和团队确认后修正历史:
git revert <commit-sha>
优先用 revert,因为它不会改写公共历史。
不要只 revert。
先废弃并轮换密钥,再清理历史,见 Remove Secret from History。
git reflog
git log --oneline --decorate -10
让仍保留旧提交的同事执行:
git log --oneline origin/main -10
git reflog -10
找到正确 commit 后:
git push origin <good-sha>:main
如果分支受保护,需要管理员或平台 owner 处理。
git log --oneline --merges -10
git revert -m 1 <merge-commit-sha>
-m 1 表示保留第一父分支的视角,撤销被合入分支带来的变化。
不要对已经 push 且被别人使用的主分支随意 reset --hard。
立即废弃并轮换 secret。
Git 历史清理不能让已经泄露的 token 重新安全。
推荐使用 git filter-repo 或平台提供的安全处理流程。
git rebase --abort
git status
git add <files>
git rebase --continue
git reflog
git reset --hard <before-rebase-sha>
公共 commit 优先用:
git revert <commit-sha>
这样会新增一个反向 commit,历史清楚,协作者也安全。
git status
git clean -nd
git clean -fd
git restore <file>
git reset --hard
执行前确认没有需要保留的本地改动。
| 状态 | 优先方案 |
|---|---|
| 未提交 | git stash 或 git restore |
| 已提交未 push | reset、commit --amend、交互式 rebase |
| 已 push 无人基于它开发 | 可以协商后重写历史 |
| 已 push 且别人基于它开发 | 优先 git revert |
| 提交了 secret | 先轮换密钥,再清理历史 |