posts
Git 撤销未推送的提交
撤销本地已提交但还没 push 的提交的操作流程:先查清楚有哪些未推送提交,再按是否保留工作区改动选择 reset 模式。
本地已经 commit、但还没 push 的提交,可以直接用 git reset 把分支指针移回去,不会产生新提交,也不会影响远程。下面是一套可直接照搬的操作流程。
一、先查清楚有哪些未推送的提交
动手前务必确认范围,尤其是有 merge 提交时,“领先 N 个提交” 这个数字可能是虚高的。
# 1. 看本地领先远程多少
git branch -vv | grep "^\*"
# 2. 列出未推送的提交(区分 merge / 非 merge)
git log --oneline origin/当前分支..HEAD
git log --oneline --no-merges origin/当前分支..HEAD
# 3. 确认远程和本地各自指向哪
git log -1 --oneline origin/当前分支
git log -1 --oneline HEAD
# 4. 看工作区有没有未提交改动(决定用哪种 reset)
git status
坑点:如果最近做过 merge(比如
Merge origin/dev into feature/xxx),git log origin/分支..HEAD会把 merge 带进来的那一大堆提交也算进去,可能显示“领先 90+”,但其中真正属于你的新提交往往只有最顶上那一个 merge。
二、执行回退
把分支指针移回远程最新点,等于撤销所有未推送的提交:
# --mixed 为默认行为,可省略
git reset origin/当前分支
三、验证结果
# 确认 HEAD 落点
git log -1 --oneline HEAD
# 与远程的差异,期望输出 0 0(不领先也不落后)
git rev-list --left-right --count origin/当前分支...HEAD
四、关键决策点:选哪种 reset 模式
git reset 有三种模式,区别在于对暂存区和工作区的处理:
| 场景 | 命令 | 效果 |
|---|---|---|
| 只想撤销提交,文件一个不动 | git reset --soft origin/分支 |
指针回退,暂存区 / 工作区原样保留,改动变成“已暂存” |
| 撤销提交 + 清空暂存区,文件保留 | git reset origin/分支(=--mixed) |
改动变成“未暂存”,可重新挑选要提交的内容 |
| 彻底丢弃提交和工作区改动 | git reset --hard origin/分支 |
工作区完全恢复到远程状态,不可恢复(未跟踪文件不受影响) |
目标位置的选择:
- 用
origin/分支= 直接对齐远程最新;- 用
HEAD~1= 只退一步(本地领先很多、但只想退最近一个提交时用)。
五、记住三点
- 先查清楚再动手:
git log origin/分支..HEAD看准到底有几个真未推送的提交,别被 merge 制造的虚高数字误导。 - 有未提交改动时慎用
--hard:它会连带丢弃工作区改动,不可逆。 - 后悔了能找回:短期内用
git reflog拿到刚才被撤销的 commit hash,再git reset --hard <hash>即可恢复。