如何撤销多个提交
撤销多个提交两种方式:保留历史用 git revert 逐个反向(git revert A..B 或 --no-commit 批量),已推送分支必须用它;未推送的用 git reset --hard <目标提交> 直接回到过去。
按"是否已推送"二选一:已推送 → git revert 生成反向提交链(历史不被改写,协作安全);未推送也需按保留需求选择reset模式;--hard会丢弃已跟踪未提交内容,先备份。
方式一:revert(已推送,安全)
# 逐个 revert(从最新到最旧)
git revert e4f5a6b c3d4e5f a1b2c3d
# 范围写法(不含 A 本身)
git revert a1b2c3d..e4f5a6b
# 压成一个撤销提交
git revert --no-commit a1b2c3d..e4f5a6b
git commit -m "撤销本周的错误变更"
冲突时按提示解决后 git revert --continue,放弃用 --abort。
方式二:reset(未推送,干净)
git reset --hard a1b2c3d # 移动当前分支并重置索引/工作区;其他引用可能仍保留后续提交
想保留改动内容(撤销提交但不丢代码):
git reset --soft a1b2c3d # 索引和工作区保持不变,相对新HEAD常呈现为暂存差异
怎么选
| 场景 | 选择 |
|---|---|
| 已推送、共享分支 | revert |
| 未推送、个人分支 | reset |
| 只撤销其中一个(非连续的) | revert 单个提交 |
| 想顺便清理历史 | reset 或 rebase -i drop |
常见问题(FAQ)
Q:revert 顺序有讲究吗?
有:线性历史通常从较新提交开始撤销,但依赖关系决定实际冲突;范围按可达图选择,可能含侧分支/merge提交,先用git log核对,merge需明确-m父线,不能保证自动无误。
Q:revert 之后还能把这些改动请回来吗?
git revert <revert提交>(撤销撤销),或找到原提交重新 cherry-pick。
Q:中间某个提交 revert 冲突很大怎么办?
它的后续提交依赖了它。要么连同后续一起 revert,要么接受手工解决冲突的工作量。