记录一个IDEA中使用GIT的严重BUG,导致测试分支合并到主分支,以及代码恢复解决方案

前言

在做项目时遇到了一个问题,就是不知道什么操作,无缘无故把test分支代码合并到了master,导致花了好长时间去恢复master分支的代码,所以研究了一下,到底是什么原因导致的这个问题
PS: 后来分析出来根本原因,确定这确实是IDEA的一个BUG,在下面会有详细描述

复现方式

  1. 当我们在test分支时,通过pull拉取更新代码,这时候会有一个进度条
    在这里插入图片描述
    在这里插入图片描述

  2. 进度条走完之前,我们想要去另一个分支看东西,点了checkout分支master,这时候我们切换到master分支
    在这里插入图片描述
    在这里插入图片描述

  3. pull动作走完,这时候会提示合并代码,这时候有两种情况

  • 情况一:如果有文件冲突,会弹出合并窗口,没注意点了合并代码,就会把test分支的代码合并到master分支上
    
  • 情况二:如果没有代码冲突,这时候会直接合并代码,也会把test分支的代码合并到master分支上
    
  1. 这时候可能有的同学把代码提交到远程

这将是一个很严重的问题
经过分析IDEA的日志发现,在点击更新按钮时,IDEA并没有直接执行git pull,而是拆成了两步,第一步fetch 同步线上版本,第二步merge origin/test合并远程test分支到本地HEAD(这里没有指定本地分支,所以会直接合并到HEAD分支上)。
这里就出现一个问题,两个指令就是两个锁,这种见有十秒左右的空档期,在这个空档期我们不小心切换了分支mater,就会导致HEAD指向了切换后的分支master,再执行merge origin/test ,就会导致远程test分支合并到master上,假如有冲突就会弹出合并冲突窗口,没有冲突就直接合并上去了,这里有时候是没有冲突的(我们很有可能刚刚从master拉出来分支A,A往test上合并时处理过冲突,就导致test分支合并到master分支并没有冲突)
这里假如底层使用git pull一个指令也是没有问题的,因为一个指令就是一个锁,你在执行pull过程中想要切换分支时,因为有锁,会切换失败,而不是导致合并错误

IDEA日志显示的操作过程
第一步执行 :fetch 操作
git -c core.quotepath=false -c log.showSignature=false fetch origin --recurse-submodules=no --progress --prune 
第二步执行:merge
git -c core.quotepath=false -c log.showSignature=false merge origin/test --no-stat -v 

在这里插入图片描述

解决办法

下面是分支版本示意图
在这里插入图片描述

情况一:关掉合并窗口,点git》合并代码》中止合并

情况二: 已合并,如果没提交到远程仓库,这时候可以用reset指令将代码恢复到指定版本4,就可以

情况三:已合并,并提交到 远程仓库 的情况下,

通过reset和revert指令,将代码版本恢复到对应版本4,这时候会生成版本6,再提交版本6到远程代码库
具体的操作验证

  1. 查看日志,记录需还原的commit版本号, git log --pretty=oneline
    git log --pretty =oneline
    在这里插入图片描述

  2. 撤销已提交的commit,回滚到测试分支误合并到开发分支的commit版本
    git reset --mixed 回滚版本号
    请添加图片描述

  3. 再次使用git log可以看到当前HEAD指向了测试分支误合并到开发分支的commit版本
    请添加图片描述

  4. 这时候我们的代码区多了很多未暂存的文件
    请添加图片描述

  5. 把撤销的代码文件暂存起来
    git stash save ‘保存撤销的代码’
    请添加图片描述

  6. 再撤销当前commit并且不保留代码(因为这里的代码是从测试分支合并过来的,我们不需要这些代码)
    git revert HEAD^

注: 这里因为是merge节点直接使用git revert HEAD^ 会提示指定主分支,这里用git log -5 指令确定一下哪个是我们要恢复的主分支即可 ,最终确定主分支是第二个merge节点,所以执行git revert HEAD^ -m 2
请添加图片描述

  1. 把贮存区的代码重新应用出来
    git stash list
    git stash apply stash@{0}
    请添加图片描述
  2. 到这里就已经去掉了测试分支的代码,我们就可以push当前代码到远程了

最新方法: 直接执行 git revert 合并节点版本号 -m 主分支编号 即可

#这个案例中为
git revert   版本5 -m 2

这里介绍一下reset 和revert区别,

reset:是移动本地代码head指针到版本4 ,再pull拉取时会再把所有版本都拉取下来,再移动head指针到最新的节点,提交代码也会提示无可用的更新
revert:(git revert 节点5版本号) 进行回滚操作,创建一个新版本节点N,这个版本N是执行了一个与节点5相反的操作抵消调版本5中的所有操作,但是会保留节点5后面所有节点的操作(比如节点5后面有6、7、8修改的文件都会保留)。而且节点N是一个新的提交节点,所以revert后再提交到远程是可以提交上去的

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

huihttp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值