一句话:Git 回退不是「删历史」,而是移动 HEAD 指针——搞清 reset、reflog 和 force push 就能安全撤销。
写在前面
日常开发里最常见的 Git 误操作:提交了不该提交的内容、本地 reset 过头、或者想把多个 commit 压成一个干净的提交记录。本篇整理 本地回退、误删恢复、远程同步、提交合并 四类场景,命令可直接复制使用。
核心内容
1. 只回退本地提交记录
当你想撤销最近几次 commit,但保留工作区文件时:
bash
# 查看提交历史,找到目标 commit 的 hash
git log --oneline
# 软回退:撤销 commit,保留暂存区和工作区改动
git reset --soft <commit-id>
# 混合回退(默认):撤销 commit 和暂存,保留工作区改动
git reset --mixed <commit-id>
# 硬回退:彻底回到指定版本,丢弃之后所有改动(慎用)
git reset --hard <commit-id>
| 模式 | commit | 暂存区 | 工作区 |
|---|---|---|---|
--soft |
回退 | 保留 | 保留 |
--mixed(默认) |
回退 | 清空 | 保留 |
--hard |
回退 | 清空 | 清空 |
2. reset 之后恢复「误删」的版本
git reset --hard 后以为历史丢了?其实 Git 的 reflog 会记录 HEAD 的每一次移动:
bash
# 查看所有 HEAD 移动记录(含 reset、rebase 等)
git reflog
# 找到 reset 之前的 commit id,恢复
git reset --hard <reflog-id>
reflog 默认保留 90 天,本地误操作基本都能救回来。
3. 回退后同步到远程
本地 hard reset 后,远程分支仍指向旧 commit,需要强制推送:
bash
# 强制推送当前分支到远程(覆盖远程历史)
git push -f -u origin master
# 或更安全的写法(远程有他人新提交时会拒绝)
git push --force-with-lease origin master
注意:强制推送会改写远程历史,多人协作分支上务必先沟通;个人分支或 fork 仓库可放心使用。
4. 多个 commit 合并成一个(squash)
适合把「fix typo」「WIP」等零碎提交整理成一条清晰记录:
bash
# commit_id 是「待合并的多个 commit 之前」的那个 commit
git rebase -i <commit_id>
交互界面中:
- 保留最新一条为
pick - 把要合并的旧 commit 改为
squash(或简写s) - 保存退出后编辑合并后的 commit message
- 若已推送过远程:
git push -f或--force-with-lease
| 指令 | 含义 |
|---|---|
pick |
保留该 commit |
squash |
合并到前一个 pick 的 commit 中 |
fixup |
同 squash,但丢弃该 commit 的 message |
踩坑
git reset --hard不可撤销(reflog 窗口外),执行前确认没有未备份的重要改动。- 在 main/master 上 force push 会影响所有协作者,优先用 revert 保留历史:
git revert <commit-id>。 - rebase -i 改已推送的 commit 会改变 hash,必须 force push;若他人已基于旧 commit 开发,会产生冲突。
- reflog 只在本机,换电脑或 clone 新仓库后无法通过 reflog 恢复。
小结
- 本地回退:
git log找 id →git reset(按 soft/mixed/hard 选粒度)。 - 误操作恢复:
git reflog→git reset --hard <id>。 - 远程同步:
git push --force-with-lease比-f更安全。 - 整理历史:
git rebase -i+ squash,适合个人分支提交洁癖。


全部评论(0)