git revert后导致合并代码丢失
起因
我有一个开发分支antd3.x和一个主分支develop,我在合并antd3.x到develop的时候发现有些修改没有合并进来。
查找问题
然后就去网上查,发现这篇文章《git合并丢失代码问题分析与解决》给我了一些启发。
其中说到git merge的原理是三方合并,简单来说就是假设我有a和b两个分支,我要合并b到a,这个时候git 其实还会去找到a和b的最近的父节点c,将c作为基础的分支,然后对abc进行比较,如果有一个文件xxx.js,xxx.js的内容abc三个分支上同一行都不一样那么就会报conflict,因为git也不知道该保留谁的代码,就会让你自行决断;如果只有一个分支比如b上面的xxx.js的同一行代码和c分支上的不一样那么git就会自作主张的认为应该保留b上面的修改,看到这我就有了方向,我应该去找我此次合并的两个分支的那个最近的父节点,问题应该就出在他上面。
通过执行 git merge-base antd3.x develop 找到了他俩base节点2344a88,然后查看该节点的代码发现那些没有合并进来的修改已经存在于这个base节点上了,怪不得进行三方合并的时候没有合并进来,因为git发现develop分支上对比base分支没有这些修改,于是这些修改就被删除掉了。但是到这一步我又有疑问了,我没有手动的删除过develop上的这些修改,为啥这些修改会没有了呢,于是我查看log发现我曾经通过 git revert 撤销过一个合并,而这个合并恰巧就是那个修改的内容,到这块问题基本就清楚了,下面我总结一下。
总结
让我们从头捋一下这个问题的前因后果:
- 我有三个分支develop、antd3.x和std-08,其中antd3.x是根据develop拉取的,std-08是根据antd3.x拉取的
- 此时我想要合并antd3.x到develop分支上,执行代码 git merge --no-ff antd3.x
- 发现antd3.x上面的有些修改(x)没有合并到develop上
- 通过 git merge-base antd3.x develop 找到了他俩base节点2344a88
- 发现base节点上面存在修改x
- 通过 git log 发现develop分支上曾经执行过 git revert
- 本来当时是想把std-08合并到antd3.x上结果合并到了develop上,也就是此时修改x合并到了develop分支上
- 然后执行了 git revert 撤销了此次合并,并正确合并std-08到antd3.x上,这就导致了antd3.x和develop的共同父节点变成了std-08的最后一次提交2344a88
- 所以后续再想合并antd3.x到develop上时,进行三方合并,发现base节点上的修改在develop上面被删除了,所以合并的结果就是删除这些修改,但是实际上这些修改我们是想保留的
解决方案
解决方案有两个:
1.在develop上执行 git reset commitId 到合并std-08之前的那次提交然后 git push -f origin ,这样develop的commit历史就不包含那次合并了
2.在develop上执行 git revert HEAD~ 把之前revert的再revert掉,这个我没有试过
思考
其实这个教训充分暴露了我对 git revert 和 git reset 的区别不甚了解,可以看下这篇文章《git revert 用法》,对它俩的区别解释的很清楚,其实就是 git revert 的撤销原理就是删除掉之前的提交然后执行commit,这样所有的commits都会保留下来,也就埋下了隐患,在我的场景里就是在git 合并的时候寻找的base节点就是develop revert之前的那个commit,如果是 git reset 就不会保留这个commit,也就不会把它作为base节点,合并的时候就不会有问题。我看了下网上还有另一种解释就是执行完 git revert 后,git就认为你不在需要这些修改,以后再合并的时候如果有这样的修改要合并,git就会忽略,我没有验证过这种说法的真实性,如果有人清楚的话,还请不吝赐教。
git revert后导致合并代码丢失的更多相关文章
- git 分回滚后无法合并代码问题
git reset & git revert 区别: 1. git revert是用一次新的commit来回滚之前的commit,git reset是直接删除指定的commit. 2. 在回滚 ...
- 代码回滚:git reset、git checkout和git revert区别和联系
git reset.git checkout和git revert是你的Git工具箱中最有用的一些命令.它们都用来撤销代码仓库中的某些更改,而前两个命令不仅可以作用于提交,还可以作用于特定文件. 因为 ...
- git使用,多分支合并代码解决冲突,git删除远程分支,删除远程master默认分支方法
git使用,多分支合并代码解决冲突,git删除远程分支,删除远程master默认分支方法提交代码流程:1.先提交代码到自己分支上2.切换到devlop拉取代码合并到当前分支3.合并后有变动的推送到自己 ...
- 项目管理---git----快速使用git笔记(七)------coding.net项目管理多人操作的流程规范--合并代码审核
我们在前面已经介绍了coding.net和本地git的基本用法. 但是多人协作开发时情况会复杂得多,所以我们最好有一些规范来保证项目多人开发顺利进行. 比如说 规范一 master代码分支 需要开启 ...
- git 合并代码
分支 dev 及衍生分支 dev-ctj 一.rebase 1.git checkout dev-ctj 2.git rebase -i head~num[num 是本分支的提交数,多个提交数先合并为 ...
- eclipse git如何切换分支,拉取代码,合并代码,解决冲突等
(如果想看eclipse拉取git项目,移步到我上一篇文章)以下步骤是eclipse运用git的切换分支,拉取合并代码的基本操作: 1.切换远程分支:鼠标右键项目--team--switch to - ...
- git的几种实用操作(合并代码与暂存复原代码)
总述 git工具也用了很久,自己也写了几篇使用教程,今天继续给大家分享一些我工作中使用过的git操作. 1.git合并远程仓库的代码 2.git stash保存当前的修改 这两种情况大家应该都 ...
- git合并代码到主分支
git合并login分支到master分支 1.首先查看源码状态 git status 2.添加到暂存区 git add . git status //添加到暂存区后再次查看源码状态 3.提交代码到本 ...
- 合并代码操作 | git fetch 与 git pull
前言 首先我们要说简单说git的运行机制.git分为本地仓库和远程仓库,我们一般情况都是写完代码,commit到本地仓库(生成本地仓的commit ID,代表当前提交代码的版本号),然后push到远程 ...
随机推荐
- GCD介绍:Dispatch_source
[转自:GCD介绍(三): Dispatch Sources] 何为Dispatch Sources 简单来说,dispatch source是一个监视某些类型事件的对象.当这些事件发生时,它自动将一 ...
- 采用prometheus 监控mysql
1. prometheus 是什么 开源的系统监控和报警工具,监控项目的流量.内存量.负载量等实时数据. 它通过直接或短时jobs中介收集监控数据,在本地存储所有收集到的数据,并且通过定义好的rule ...
- Ubuntu18.04配制阿里巴巴的源
配制阿里巴巴的源步骤 使用阿里巴巴的开源镜像:https://opsx.alibaba.com/mirror 然后选择ubuntu的帮助选项,复制ubuntu18.04镜像源 设置root账户密码: ...
- hdu1024 Max Sum Plus Plus 滚动dp
Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
- Gradle学习系列(三)
上一篇我们已经学习了 Gradle 打包,那么这一节 就开始讲讲本章的第二版块:打包及使用Gradle过程中的常见错误问题. 有时候我们需要编辑一个开源项目之类的,希望把它导入了我们自己的IDE工具中 ...
- springboot: mybatis逆向工程
第一步: pom文件配置 黄线的部分是所要配置的 <?xml version="1.0" encoding="UTF-8"?> <projec ...
- SSM上传EXCLE到数据库 和 从数据库导出为EXCLE
SSM上传EXCLE到数据库 和 从数据库导出为EXCLE package com.ABC.controller; import java.io.BufferedInputStream; import ...
- UBUNTU 无法解析域名 解决方法
莫名其妙的,ubuntu 无法访问外网. ping www.taobao.com www.baidu.com 提示无效的主机名 但是ping 外网ip 都是可以PING通的. 所以断定是 dns问题 ...
- 使用WSW将Nginx创建为Windows系统服务
我们都知道Windows Service是一种特殊的应用程序,它的好处是可以一直在后台运行,相对来说,比较适合一些需要一直运行同时不需要过多用户干预的应用程序,这一类我们称之为“服务”,在Window ...
- Spring中线程池的应用
多线程并发处理起来通常比较麻烦,如果你使用spring容器来管理业务bean,事情就好办了多了.spring封装了Java的多线程的实现,你只需要关注于并发事物的流程以及一些并发负载量等特性,具体来说 ...