基于本文回答

播面 播面

刷题像听歌,多听自然懂
0
评论

git reset 和 git revert 有什么本质区别?

知识点图片

git resetgit revert 都是 Git 中用于“撤销”操作的命令,但它们的本质区别在于对待历史记录的态度

用一句话概括就是:

  • git reset 是“修改历史”(把时间倒流,抹除提交)。
  • git revert 是“追加历史”(用一次新的提交来抵消之前的错误,保留所有痕迹)。

下面为你详细拆解它们的本质区别和使用场景。


1. 本质上的三大区别

① 历史记录的处理方式(毁灭性 vs 建设性)

  • git reset (重置): 它是破坏性的。它会将当前分支的指针(HEAD)向后移动到指定的历史提交上。就好像你把日记本上的最后几页直接撕掉,假装它们从未发生过。
  • git revert (反转/撤销): 它是安全性、建设性的。它不会改变过去的提交,而是新建一个提交,这个新提交的内容正好和你要撤销的提交内容相反(比如你之前加了一行代码,revert 就会删掉这行代码)。就像在日记本上新写一页:“请忽略前天写的那一页内容”。

② 对团队协作的影响(危险 vs 安全)

  • git reset 绝对不要在已经推送到远程的公共分支上使用! 因为它改变了历史,如果你强制推送(git push -f),会导致其他同事的本地仓库与远程仓库历史不一致,引发严重的冲突和混乱。
  • git revert 非常适合在公共分支上使用。 因为它只是增加了一个新的提交,历史记录是顺延的。你可以像推送普通提交一样把它推送到远程,其他同事只需 git pull 即可同步,完全不会有冲突。

③ 作用范围(回退到某个状态 vs 撤销某个具体动作)

  • git reset <commit_id> 撤销的是从当前位置到 <commit_id> 之间的所有提交
  • git revert <commit_id> 仅仅撤销 <commit_id> 那一次提交的更改,不管它是一次最新提交还是历史中间的某次提交。

2. 图解演示

假设你的提交历史是这样的: A -> B -> C (当前HEAD),现在你发现 C 提交写错了。

使用 git reset HEAD~1 (或 reset 到 B):

  • 历史变成了: A -> B (当前HEAD)
  • C 提交从历史线中消失了(变成了孤儿提交,最终会被 Git 垃圾回收)。

使用 git revert HEAD (或 revert 提交 C):

  • 历史变成了: A -> B -> C -> D (当前HEAD)
  • 这里的 D 是一个全新的提交,它的内容是撤销 C 所做的修改。C 依然完好无损地留在历史记录中。

3. 详细参数与使用场景

git reset 的三种模式

当你用 reset 撕掉历史时,你还可以决定要不要保留你写的代码(工作区和暂存区):

  • --soft:只撤销 commit,代码保留在暂存区(适合你想把几次提交合并成一次时)。
  • --mixed (默认):撤销 commit 和暂存区,代码保留在工作区(适合你发现提交错了,想重新修改代码后再提交)。
  • --hard最危险,撤销 commit、暂存区和工作区,代码彻底变回旧版本(除非你有未提交的备份,否则代码彻底丢失)。

适用场景: 本地自己开发的分支,代码还没推送到远程服务器,发现刚才提交得太乱了,想重新整理历史。

git revert

没有任何破坏性参数,直接生成新提交。
如果发生冲突(比如你 revert 一个很早以前的提交,而后面的提交修改了同一行代码),你需要手动解决冲突然后再提交。

适用场景: 代码已经合并到了 mainmaster 等多人协作的公共分支,线上发现 Bug 需要紧急回滚。此时必须用 revert


4. 总结:黄金法则

记住一条 Git 界的黄金法则:
👉 私有分支/本地代码回退,用 git reset(干净利落)。
👉 公共分支/远程代码回退,用 git revert(安全可靠)。

00:00
00:00