git log 一看,上一条 commit 把调试用的 print 也带进去了,还没 push。这种时候不用慌,git取消commit 在本地就能做,历史还没推到远程。

没推送:reset 回退提交

git reset --soft HEAD~1 撤销最近一次提交,改动留在暂存区,改完重新 commit 就行。--mixed 是默认模式,改动退回工作区;--hard 连改动一起丢掉,执行前确认没有要留的代码。

git reset --soft HEAD~1; git commit -m 'fix: remove debug code'
  • --soft:只撤提交,改动留在暂存区。
  • --mixed:改动退回工作区,需要重新 add。
  • --hard:提交和改动一起丢,慎用。

只想改提交信息或者补一个文件,用 git commit --amend,它会重写最近一次提交。连着提交了好几条都要撤,把 HEAD~1 换成 HEAD~3。已经 push 的分支别随便 amend,远程和本地会对不上。

已推送:revert 更安全

git revert 提交号 会生成一条反向提交,把那次改动抵消,历史保留,同事拉代码不会出问题。代价是 log 里多一条记录,正式项目一般接受这种做法。合并提交要用 -m 指定主线,不然会报错。revert 之后又想恢复那次改动,把反向提交再 revert 一次就行,历史依然清楚。

git revert a1b2c3d

误删了还能捞回来

reset --hard 之后发现删错了,git reflog 能看到 HEAD 的移动记录,找到之前的提交号,再 reset 回去就回来了。reflog 默认保留一段时间,别拖太久。

提交撤销了但文件还没提交,先 git restore --staged 文件名 把它撤出暂存区,再按需要改。已推送又想彻底删掉提交,只能 git push --force-with-lease,风险是别人基于旧提交做的工作会乱,公共分支别这么干,个人分支确认没人用再推。

团队共用的分支,改历史前先说一声,比事后解释省事。动手前最好建个备份分支,出问题还能回来。