Git 这样回退代码,才足够优雅

今日推荐为什么不建议你用a.equals(b)判断对象相等
SpringBoot中的线程池,你真的会用么?
代码对比工具,就用这7个!
在 IDEA 中的各种调试技巧,轻松定位 Bug(超级全面)

后端接口如何提高性能?

16 个写代码的好习惯

来源:https://zhenbianshu.github.io

从接触编程就开始使用 Git 进行代码管理,先是自己玩 Github,又在工作中使用 Gitlab,虽然使用时间挺长,可是也只进行一些常用操作,如推拉代码、提交、合并等,更复杂的操作没有使用过,看过的教程也逐渐淡忘了,有些对不起 Linus 大神。

出来混总是要还的,前些天就遇到了 Git 里一种十分糟心的场景,并为之前没有深入理解 Git 命令付出了一下午时间的代价。

先介绍一下这种场景,我们一个项目从 N 版本升到 A 版本时引入了另一项目的 jar 包,又陆续发布了 B、C 版本,但在 C 版本后忽然发现了 A 版本引入的 jar 包有极大的性能问题,B、C 版本都是基于 A 版本发布的,要修复 jar 包性能问题,等 jar 包再发版还得几天,可此时线上又有紧急的 Bug 要修,于是就陷入了进退两难的境地。

最后决定先将代码回退到 A 版本之前,再基于旧版本修复 Bug,也就开始了五个小时的受苦之路。

基础试探

revert

首先肯定的是 revert,git revert commit_id 能产生一个 与 commit_id 完全相反的提交,即 commit_id 里是添加, revert 提交里就是删除。

但是使用 git log 查看了提交记录后,我就打消了这种想法,因为提交次数太多了,中途还有几次从其他分支的 merge 操作。”利益于”我们不太干净的提交记录,要完成从 C 版本到 N 版本的 revert,我需要倒序执行 revert 操作几十次,如果其中顺序错了一次,最终结果可能就是不对的。

另外我们知道我们在进行代码 merge 时,也会把 merge 信息产生一次新的提交,而 revert 这次 merge commit 时需要指定 m 参数,以指定 mainline,这个 mainline 是主线,也是我们要保留代码的主分支,从 feature 分支往 develop 分支合并,或由 develop 分支合并到 master 的提交还好确定,但 feature 分支互相合并时,我哪知道哪个是主线啊。

所以 revert 的文案被废弃了。

Reset

然后就考虑 reset 了, reset 也能使代码回到某次提交,但跟 revert 不同的是, reset 是将提交的 HEAD 指针指到某次提交,之后的提交记录会消失,就像从没有过这么一次提交。

但由于我们都在 feature 分支开发,我在 feature 分支上将代码回退到某次提交后,将其合并到 develop 分支时却被提示报错。这是因为 feature 分支回退了提交后,在 git 的 workflow 里,feature 分支是落后于 develop 分支的,而合并向 develop 分支,又需要和 develop 分支保持最新的同步,需要将 develop 分支的数据合并到 feature 分支上,而合并后,原来被 reset 的代码又回来了。

这个时候另一个可选项是在 master 分支上执行 reset,使用 --hard 选项完全抛弃这些旧代码,reset 后再强制推到远端。

`master> git reset --hard commit_id  
master> git push --force origin master  
`

但是还是有问题,首先,我们的 master 分支在 gitlab 里是被保护的,不能使用 force push,毕竟风险挺大了,万一有人 reset 到最开始的提交再强制 push 的话,虽然可以使用 reflog 恢复,但也是一番折腾。

另外,reset 毕竟太野蛮,我们还是想能保留提交历史,以后排查问题也可以参考。

升级融合

rebase

只好用搜索引擎继续搜索,看到有人提出可以先使用 rebase 把多个提交合并成一个提交,再使用 revert 产生一次反提交,这种方法的思路非常清晰,把 revert 和 rebase 两个命令搭配得很好,相当于使用 revert 回退的升级版。

先说一下 rebase,rebase 是”变基”的意思,这里的”基”,在我理解是指[多次] commit 形成的 git workflow,使用 rebase,我们可以改变这些历史提交,修改 commit 信息,将多个 commit 进行组合。

介绍 rebase 的文档有很多,我们直接来说用它来进行代码回退的步骤。

  • 首先,切出一个新分支 F,使用 git log 查询一下要回退到的 commit 版本 N。

  • 使用命令 git rebase -i N, -i 指定交互模式后,会打开 git rebase 编辑界面,形如:

`pick 6fa5869 commit1  
pick 0b84ee7 commit2  
pick 986c6c8 commit3  
pick 91a0dcc commit4  
`
  • 这些 commit 自旧到新由上而下排列,我们只需要在 commit_id 前添加操作命令即可,在合并 commit 这个需求里,我们可以选择 pick(p) 最旧的 commit1,然后在后续的 commit_id 前添加 squash(s) 命令,将这些 commits 都合并到最旧的 commit1 上。

  • 保存 rebase 结果后,再编辑 commit 信息,使这次 rebase 失效,git 会将之前的这些 commit 都删除,并将其更改合并为一个新的 commit5,如果出错了,也可以使用 git rebase --abort/--continue/--edit-todo对之前的编辑进行撤销、继续编辑。

  • 这个时候,主分支上的提交记录是 older, commit1, commit2, commit3, commit4,而 F 分支上的提交记录是 older, commit5,由于 F 分支的祖先节点是 older,明显落后于主分支的 commit4,将 F 分支向主分支合并是不允许的,所以我们需要执行 git merge master 将主分支向 F 分支合并,合并后 git 会发现 commit1 到 commit4 提交的内容和 F 分支上 commit5 的修改内容是完全相同的,会自动进行合并,内容不变,但多了一个 commit5。

  • 再在 F 分支上对 commit5 进行一次 revert 反提交,就实现了把 commit1 到 commit4 的提交全部回退。

这种方法的取巧之处在于巧妙地利用了 rebase 操作历史提交的功能和 git 识别修改相同自动合并的特性,操作虽然复杂,但历史提交保留得还算完整。

rebase 这种修改历史提交的功非常实用,能够很好地解决我们遇到的一个小功能提交了好多次才好使,而把 git 历史弄得乱七八糟的问题,只需要注意避免在多人同时开发的分支使用就行了。

遗憾的是,当天我并没有理解到 rebase 的这种思想,又由于试了几个方法都不行太过于慌乱,在 rebase 完成后,向主分支合并被拒之后对这些方式的可行性产生了怀疑,又加上有同事提出听起来更可行的方式,就中断了操作。

文件操作

这种更可行的方式就是对文件操作,然后让 git 来识别变更,具体是:

  • 从主分支上切出一个跟主分支完全相同的分支 F。

  • 从文件管理系统复制项目文件夹为 bak,在 bak 内使用 git checkout N 将代码切到想要的历史提交,这时候 git 会将 bak 内的文件恢复到 N 状态。

  • 在从文件管理系统内,将 bak 文件夹下 除了 .git 文件夹下的所有内容复制粘贴到原项目目录下。git 会纯从文件级别识别到变更,然后更新工作区。

  • 在原项目目录下执行 add 和 commit,完成反提交。

  • 这种方式的巧妙之处在于利用 git 本身对文件的识别,不牵涉到对 workflow 操作。

小结

最后终于靠着文件操作方式成功完成了代码回退,事后想来真是一把心酸泪。

为了让我的五个小时不白费,复盘一下当时的场景,学习并总结一下四种代码回退的方式:

  • revert 适合需要回退的历史提交不多,且无合并冲突的情景。

  • 如果你可以向 master 强推代码,且想让 git log 里不再出现被回退代码的痕迹,可以使用 git reset --hard + git push --force的方式。

  • 如果你有些 geek,追求用”正规而正统”的方式来回退代码,rebase + revert 满足你的需求。

  • 如果你不在乎是否优雅,想用最简单,最直接的方式,文件操作正合适。

git 真的是非常牛逼的代码管理工具,入手简单,三五个命令组合起来就足够完成工作需求,又对 geeker 们非常友好,你想要的骚操作它都支持,学无止境啊。

推荐文章

1、14个项目!

2、Spring Boot + Security + MyBatis + Thymeleaf + Activiti 快速开发平台项目

3、推荐几个支付项目!

4、写博客能月入10K?

5、一款基于 Spring Boot 的现代化社区(论坛/问答/社交网络/博客)

更多项目源码
1、这或许是最美的Vue+Element开源后台管理UI2、推荐一款高颜值的 Spring Boot 快速开发框架
3、一款基于 Spring Boot 的现代化社区(论坛/问答/社交网络/博客)
4、13K点赞都基于 Vue+Spring 前后端分离管理系统ELAdmin,大爱5、想接私活时薪再翻一倍,建议根据这几个开源的SpringBoot
  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
<p style="color:#666666;"> <span style="font-size:14px;">本门课程重实战将基础知识拆解到项目里让你在项目情境里学知识。</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">这样的学习方式能让你保持兴趣、充满动力时刻知道学的东西能用在哪、能怎么用。</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">平时不明白的知识点放在项目里去理解就恍然大悟了。</span> </p> <p style="color:#666666;"> <span></span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>一、融汇贯通</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">本视频采用了前后端分离的开发模式前端使用Vue.js+Element UI实现了Web页面的呈现后端使用Python 的Django框架实现了数据访问的接口前端通过Axios访问后端接口获得数据。在学习完本章节后真正理解前后端的各自承担的工作。</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>二、贴近实战</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">本系列课程为练手项目实战:学生管理系统v4.0的开发项目包含了如下几个内容:项目的总体介绍、基本功能的演示、Vuejs的初始化、Element UI的使用、在Django中实现针对数据的增删改查的接口、在Vuejs中实现前端增删改查的调用、实现文件的上传、实现表格的分页、实现导出数据到Excel、实现通过Excel导入数据、实现针对表格的批量化操作等等所有的功能都通过演示完成、贴近了实战</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>三、课程亮点</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">在本案例中最大的亮点在于前后端做了分离真正理解前后端的各自承担的工作。前端如何和后端交互</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>适合人群:</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">1、有Python语言基础、web前端基础想要深入学习Python Web框架的朋友;</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">2、有Django基础但是想学习企业级项目实战的朋友;</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">3、有MySQL数据库基础的朋友</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="font-size:14px;"><img alt="" src="https://img-bss.csdnimg.cn/202009070752197496.png" /><br /> </span> </p> <p style="color:#666666;"> <span style="font-size:14px;"><br /> </span> </p>
<div style="color:rgba(0,0,0,.75);"> <span style="color:#4d4d4d;"> </span> <div style="color:rgba(0,0,0,.75);"> <span style="color:#4d4d4d;"> </span> <div style="color:rgba(0,0,0,.75);"> <div style="color:rgba(0,0,0,.75);"> <span style="color:#4d4d4d;">当前课程中商城项目的实战源码是我发布在 GitHub 上的开源项目 newbee-mall (新蜂商城)目前已有 6300 多个 star</span><span style="color:#4d4d4d;">本课程是一个 Spring Boot 技术栈的实战类课程课程共分为 3 大部分前面两个部分为基础环境准备和相关概念介绍第三个部分是 Spring Boot 商城项目功能的讲解让大家实际操作并实践上手一个大型的线上商城项目并学习到一定的开发经验以及其中的开发技巧。<br /> 商城项目所涉及的功能结构图整理如下:<br /> </span> </div> <div style="color:rgba(0,0,0,.75);">   </div> <div style="color:rgba(0,0,0,.75);"> <p style="color:#4d4d4d;"> <img alt="modules" src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9uZXdiZWUtbWFsbC5vc3MtY24tYmVpamluZy5hbGl5dW5jcy5jb20vcG9zdGVyL3N0b3JlL25ld2JlZS1tYWxsLXMucG5n?x-oss-process=image/format,png" /> </p> </div> <p style="color:rgba(0,0,0,.75);"> <strong><span style="color:#e53333;">课程特色</span></strong> </p> <p style="color:rgba(0,0,0,.75);">   </p> <div style="color:rgba(0,0,0,.75);">   </div> <div style="color:rgba(0,0,0,.75);"> <ul> <li> 对新手开发者十分友好无需复杂的操作步骤仅需 2 秒就可以启动这个完整的商城项目 </li> <li> 最终的实战项目是一个企业级别的 Spring Boot 大型项目对于各个阶段的 Java 开发者都是极佳的选择 </li> <li> 实践项目页面美观且实用交互效果完美 </li> <li> 教程详细开发教程详细完整、文档资源齐全 </li> <li> 代码+讲解+演示网站全方位保证向 Hello World 教程说拜拜 </li> <li> 技术栈新颖且知识点丰富学习后可以提升大家对于知识的理解和掌握可以进一步提升你的市场竞争力 </li> </ul> </div> <p style="color:rgba(0,0,0,.75);">   </p> <p style="color:rgba(0,0,0,.75);"> <span style="color:#e53333;">课程预览</span> </p> <p style="color:rgba(0,0,0,.75);">   </p> <div style="color:rgba(0,0,0,.75);">   </div> <div style="color:rgba(0,0,0,.75);"> <p style="color:#4d4d4d;"> 以下为商城项目的页面和功能展示分别为: </p> </div> <div style="color:rgba(0,0,0,.75);"> <ul> <li> 商城首页 1<br /> <img alt="" src="https://img-bss.csdnimg.cn/202103050347585499.gif" /> </li> <li> 商城首页 2<br /> <img alt="" src="https://img-bss.csdn.net/202005181054413605.png" /> </li> <li>   </li> <li> 购物车<br /> <img alt="cart" src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9uZXdiZWUtbWFsbC5vc3MtY24tYmVpamluZy5hbGl5dW5jcy5jb20vcG9zdGVyL3Byb2R1Y3QvY2FydC5wbmc?x-oss-process=image/format,png" /> </li> <li> 订单结算<br /> <img alt="settle" src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9uZXdiZWUtbWFsbC5vc3MtY24tYmVpamluZy5hbGl5dW5jcy5jb20vcG9zdGVyL3Byb2R1Y3Qvc2V0dGxlLnBuZw?x-oss-process=image/format,png" /> </li> <li> 订单列表<br /> <img alt="orders" src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9uZXdiZWUtbWFsbC5vc3MtY24tYmVpamluZy5hbGl5dW5jcy5jb20vcG9zdGVyL3Byb2R1Y3Qvb3JkZXJzLnBuZw?x-oss-process=image/format,png" /> </li> <li> 支付页面<br /> <img alt="" src="https://img-bss.csdn.net/201909280301493716.jpg" /> </li> <li> 后台管理系统登录页<br /> <img alt="login" src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9uZXdiZWUtbWFsbC5vc3MtY24tYmVpamluZy5hbGl5dW5jcy5jb20vcG9zdGVyL3Byb2R1Y3QvbWFuYWdlLWxvZ2luLnBuZw?x-oss-process=image/format,png" /> </li> <li> 商品管理<br /> <img alt="goods" src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9uZXdiZWUtbWFsbC5vc3MtY24tYmVpamluZy5hbGl5dW5jcy5jb20vcG9zdGVyL3Byb2R1Y3QvbWFuYWdlLWdvb2RzLnBuZw?x-oss-process=image/format,png" /> </li> <li> 商品编辑<br /> <img alt="" src="https://img-bss.csdnimg.cn/202103050348242799.png" /> </li> </ul> </div> </div> </div> </div>
©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值