为什么不建议乱用 git push --force?

预计阅读时间:5 分钟

Git 已经 Push 了怎么办?别急着 force push

最让人后背发凉的 Git 场景,往往不是 commit 错了。

而是你已经把错误提交 push 到远程仓库了。

比如:

git push origin main

按下回车后才发现:

  • 测试代码提交上去了
  • 配置文件改错了
  • 一个明显 bug 被推到了远程
  • 更尴尬的是,分支还是 main

这时候很多人的第一反应是:

git reset --hard HEAD~1
git push --force

先别急。

如果代码已经 push,事情就不再只是你本地的事了。因为别人可能已经拉取了你的提交。

Push 之后,为什么更麻烦?

在本地 commit 出错,你可以比较自由地 resetamend、重新提交。

但 push 之后,这个提交已经进入远程历史。

如果团队里有人已经执行了:

git pull

甚至基于你的提交继续开发,那这个 commit 就成了大家共同的历史。

这时候你再强行改历史,就可能影响别人。

所以问题的关键不是“能不能撤回”,而是:

这个提交有没有变成公共历史?

只要答案是“可能已经是”,就要谨慎。

Force Push 为什么危险?

git push --force 的作用很直接:

用你本地的历史,强行覆盖远程历史。

听起来很爽,但危险也在这里。

假设远程仓库现在是这样:

A -- B -- C

你本地 reset 到了 B,然后强推:

git push --force

远程可能就变成:

A -- B

提交 C 从远程历史里消失了。

如果 C 只有你一个人用,问题可能不大。

但如果别人已经基于 C 开发,那他的本地历史就会和远程对不上,后面 pull、merge、rebase 都可能变得很混乱。

这也是为什么很多团队会禁止对 main 分支 force push。

Force push导致历史分叉示意图

更安全的方式:git revert

团队协作里,更推荐用:

git revert commitID

revert 的思路不是删除历史,而是新增一次“反向提交”。

比如原来的错误提交做了这件事:

+ const debug = true

revert 后会生成一个新的 commit,把它撤回来:

- const debug = true

历史会变成这样:

A -- B -- C -- D

其中:

  • C 是错误提交
  • D 是撤销 C 的提交

这样做的好处是:历史没有被改写,别人已经拉取 C 也没关系。大家再拉取 D,就能同步到撤销后的状态。

Reset 和 Revert 最大区别

一句话理解:

reset 是修改历史,revert 是追加历史。

可以这样记:

命令 本质 更适合
reset 回到过去,改掉历史 本地、未 push 的提交
revert 新增一次撤销记录 已 push、多人协作的提交

所以在本地开发时,reset 很好用。

但如果提交已经 push 到远程,尤其是 main、master、develop 这种公共分支,优先考虑 revert

那 force push 永远不能用吗?

也不是。

有些情况下,force push 是可以接受的。

比如:

  • 你自己的个人分支
  • 明确没人基于这个分支开发
  • 团队约定允许重写该分支历史
  • 你清楚知道自己会覆盖什么

但对新手来说,可以先记住一个保守原则:

公共分支不要随便 force push。

如果你必须强推,也最好先和团队确认一下。

总结

这篇记住 3 点:

  1. push 之后,提交可能已经变成公共历史。
  2. git push --force 会覆盖远程历史,团队协作中风险很高。
  3. 已 push 的错误提交,优先用 git revert 生成反向提交。

本文由 楸木 原创,转载请注明出处。

相关推荐

发现更多