当前位置: 首页 > news >正文

辨析git reset三种模式以及和git revert的区别:回退到指定版本和撤销指定版本的操作

辨析git reset和git revert

  • git revert:撤销指定版本的修改内容
    • 实例介绍
    • 执行 `git revert C`
    • **revert总结**
  • git reset : 回退到指定版本
    • 模式一:`git reset --hard C` (最暴力、最彻底的模式)
    • 模式二:`git reset --mixed C` (默认模式)
    • 模式三:`git reset --soft C` (最温柔的模式)
    • reset总结
  • 总结

git revert:撤销指定版本的修改内容

git revert 不是让的项目“回到”版本C的状态
作用是:创建一个全新的提交,这个新提交的内容,刚好是版本C所做修改的“反向操作”

实例介绍

假设项目是一个故事文件 story.txt,历史如下:

  1. Commit A (初始)

    • 文件内容:
      从前有座山。
      
  2. Commit B (发展)

    • 增加了新的一行。
    • 文件内容:
      从前有座山。
      山里有座庙。
      
  3. Commit C (错误的修改)

    • 画蛇添足,加了一句不该加的话。
    • 文件内容:
      从前有座山。
      山里有座庙。
      【庙被拆了。】  <-- 这是Commit C引入的修改
      
  4. Commit D (后续的工作)

    • 没意识到C的错误,继续往下写。
    • 文件内容:
      从前有座山。
      山里有座庙。
      【庙被拆了。】
      和尚下山了。   <-- 这是Commit D引入的修改
      

现在的项目历史是 A -> B -> C -> D


执行 git revert C

目标:希望撤销“庙被拆了”这句错误的话,但必须保留“和尚下山了”这句有用的后续工作。

  1. 分析Commit C:Git会查看 Commit C 到底做了什么修改。它发现 C 的修改是**“增加了‘庙被拆了。’这一行”**。

  2. 执行反向操作revert 的核心就是做反向操作。既然 C 的操作是“增加”,那么它的反向操作就是**“删除‘庙被拆了。’这一行”**。

  3. 创建新Commit E:Git 会把这个“反向操作”作为一个全新的提交,我们叫它 Commit E。

    • 这个 Commit E 的提交信息通常会自动生成为 “Revert ‘Commit C 的提交信息’”。
    • 这个 Commit E 的修改内容,就是从当前最新版本(D的状态)中,删除 “庙被拆了。” 这一行。

revert之后的结果:

  • 新的项目历史: A -> B -> C -> D -> E (Revert C)
  • 最终的文件内容:
    从前有座山。
    山里有座庙。
    和尚下山了。
    

revert总结

  • 我们没有回到 Commit C 的状态(那会丢失“和尚下山了”)。
  • 我们也没有回到 Commit B 的状态(那同样会丢失“和尚下山了”)。
  • 我们只是在最新的状态(D)基础上,精确地“抵消”掉了 C 所带来的变更,同时完好无损地保留了 D 的变更。

git reset : 回退到指定版本

继续用这个生动的故事例子来解析 git reset C 会发生什么。这就像是坐上了时光机,但时光机有不同的模式,对应着 reset 的三个主要选项:--hard, --mixed (默认), 和 --soft

出发前的状态(和之前一样):

  • 项目历史: A -> B -> C -> D (HEAD指针在这里)
  • 当前文件 story.txt 内容:
    从前有座山。
    山里有座庙。
    【庙被拆了。】
    和尚下山了。
    

现在,我们执行 git reset C。这个操作的核心是:HEAD 指针和当前分支(比如 main)的指针,强行移动到 commit C。这就像是宣布:“官方历史只记录到 C 为止!”

commit D 并没有被立即删除,它只是变成了“孤魂野鬼”,不再被任何分支引用。如果后续没有其他操作,它最终会被Git的垃圾回收机制清理掉。

那么,你的工作区(story.txt 文件)和暂存区会发生什么变化呢?这取决于你使用的模式。


模式一:git reset --hard C (最暴力、最彻底的模式)

这就像是霸道总裁的时光机,不仅回到了过去,还把之后的一切痕迹都抹除了。

  • 操作git reset --hard C

  • 时光机的行为:

    1. 历史指针移动: HEAD 指针从 D 移动回 C。历史记录现在看起来是 A -> B -> C
    2. 暂存区重置: 暂存区(Staging Area)的内容被完全重置,使其与 C 的内容一模一样。
    3. 工作区重置: 你的工作目录(硬盘上的 story.txt 文件)被强制更新,使其内容也与 C 的内容一模一样。
  • 结果:

    • 最终历史: A -> B -> C (HEAD)
    • 最终文件 story.txt 内容:
      从前有座山。
      山里有座庙。
      【庙被拆了。】
      
    • 损失: “和尚下山了”这句在 D 中的修改,彻底消失了,无论是在暂存区还是在你的文件里,都找不到了。这是个有损操作,一定要小心!

模式二:git reset --mixed C (默认模式)

如果你只输入 git reset C,Git默认就是使用 --mixed 模式。这像是时光机把你带回去了,但把你之前写的草稿(工作成果)留在了桌子上。

  • 操作: git reset Cgit reset --mixed C

  • 时光机的行为:

    1. 历史指针移动: HEAD 指针从 D 移动回 C。历史记录现在是 A -> B -> C
    2. 暂存区重置: 暂存区的内容被重置,与 C 的内容保持一致。
    3. 工作区不变: 关键区别! 你的工作目录(story.txt 文件)保持不变,它仍然是 D 操作之后的样子。
  • 结果:

    • 最终历史: A -> B -> C (HEAD)
    • 最终文件 story.txt 内容:
      从前有座山。
      山里有座庙。
      【庙被拆了。】
      和尚下山了。
      
    • git status 的状态: Git会告诉你,你的工作目录和暂存区有差异。它会显示“和尚下山了”这句是未暂存的修改 (unstaged change)
    • 意义: Git帮你撤销了 commit D 这个提交行为,但保留了 D 的代码修改。你可以检查这些修改,决定是重新提交、修改后再提交,还是彻底丢弃 (git checkout -- .)。

模式三:git reset --soft C (最温柔的模式)

这就像是时光机仅仅移动了书签,而书的内容和你的草稿都原封不动。

  • 操作: git reset --soft C

  • 时光机的行为:

    1. 历史指针移动: 这是它唯一做的事情! HEAD 指针从 D 移动回 C。历史记录现在是 A -> B -> C
    2. 暂存区不变: 暂存区的内容保持不变,和 D 操作后一样。
    3. 工作区不变: 你的工作目录(story.txt 文件)也保持不变
  • 结果:

    • 最终历史: A -> B -> C (HEAD)
    • 最终文件 story.txt 内容:
      从前有座山。
      山里有座庙。
      【庙被拆了。】
      和尚下山了。
      
    • git status 的状态: Git会告诉你,你有已暂存的修改 (staged changes),这个修改就是 D 所做的 “和尚下山了”。
    • 意义: 这个模式非常适合用于“合并提交”。比如你发现 CD 两个提交其实应该合成一个,你就可以 reset --soft B,然后把 CD 的所有修改一次性重新提交。

reset总结

操作 (git reset C)历史指针 (HEAD)暂存区 (Staging Area)工作目录 (文件)主要用途
--hard回到 C变成 C 的样子变成 C 的样子彻底丢弃 C 之后的所有提交和修改,慎用!
--mixed (默认)回到 C变成 C 的样子保持不变撤销提交但保留代码修改,可以重新整理。
--soft回到 C保持不变保持不变合并多个提交,或只是想修改最后一次提交的信息。

所以,git reset C 确实是“回到过去”,但“回到过去”之后现场会变成什么样,取决于你选择的时光机模式。这与 git revert 那种“向前走,做反向操作来弥补”的思路,有着本质的区别。

总结

git revert 像是在故事的最新结尾(“和尚下山了”之后)补写了一个新章节,内容是“哦,之前说的庙被拆了是假的”,从而优雅地修正了错误,保留了所有历史。

git reset 则是直接乘坐时光机回到“庙被拆了”那一刻,然后粗暴地撕掉了后面“和尚下山了”这一页历史,让故事看起来就像从未发生过一样。


文章转载自:
http://beckoning.wjrtg.cn
http://aden.wjrtg.cn
http://chromodynamics.wjrtg.cn
http://badness.wjrtg.cn
http://brassie.wjrtg.cn
http://ccs.wjrtg.cn
http://canalboat.wjrtg.cn
http://cahot.wjrtg.cn
http://bark.wjrtg.cn
http://bandleader.wjrtg.cn
http://bedell.wjrtg.cn
http://benzpyrene.wjrtg.cn
http://blepharitis.wjrtg.cn
http://canaille.wjrtg.cn
http://beseem.wjrtg.cn
http://apologue.wjrtg.cn
http://adam.wjrtg.cn
http://chaldee.wjrtg.cn
http://brython.wjrtg.cn
http://betatron.wjrtg.cn
http://bpd.wjrtg.cn
http://baignoire.wjrtg.cn
http://ascendant.wjrtg.cn
http://arrhythmia.wjrtg.cn
http://carices.wjrtg.cn
http://bagassosis.wjrtg.cn
http://alphanumeric.wjrtg.cn
http://acidness.wjrtg.cn
http://capelin.wjrtg.cn
http://benchman.wjrtg.cn
http://www.dtcms.com/a/280840.html

相关文章:

  • 零样本轴承故障诊断SC - GAN模型
  • 【PCIe 总线及设备入门学习专栏 5.1.2 -- PCIe EP core_rst_n 与 app_rst_n】
  • React-router
  • 未来大模型在中小型企业如何实现普及
  • PG备份一(逻辑备份)
  • Kafka——生产者消息分区机制原理剖析
  • Java基础教程(009): Java 的封装
  • Samba配置使用
  • 算法学习笔记:23.贪心算法之活动选择问题 ——从原理到实战,涵盖 LeetCode 与考研 408 例题
  • 重学前端005 --- 响应式网页设计 CSS 盒子模型
  • Python函数进阶
  • python 基于 httpx 的流式请求
  • 封装---统一处理接口与打印错误信息
  • Linux下调试器gdb/cgdb的使用
  • Linux系统调优和工具
  • [面试] 手写题-对象数组根据某个字段进行分组
  • mysql官网的版本历史版本下载
  • 令牌获取与认证机制详解
  • 关键点检测数据格式转换(.JSON转TXT)
  • 【超分论文精读】——LightBSR(ICCV2025)
  • 梳理Bean的创建流程
  • mongoDB的CRUD
  • Visual Studio 现已支持新的、更简洁的解决方案文件(slnx)格式
  • 云服务器如何管理数据库(MySQL/MongoDB)?
  • 基于STM32G431无刷电机驱动FOC软硬件学习
  • iOS高级开发工程师面试——常见第三方框架架构设计
  • C++学习笔记五
  • Gemma-3n-E4B-it本地部署教程:谷歌开源轻量级多模态大模型,碾压 17B 级同类模型!
  • SHAP 值的数值尺度
  • Conda 核心命令快速查阅表