对于Github上的开源代码,一般都采用fork方式到自己账户下,进行二次开发定制或增强修正一些功能,久而久之,你fork的代码已经与官方代码有了很大的差别,尤其是当官方升级版本后,也想升级自己fork库的代码,那么就需要涉及升级合并两个库。
以Apache 的NiFi项目为例说明,Github库为
自己fork的库地址为
自该文时,Apache已发布正式版1.7.1, 假设自己fork的master是基于1.7.0-SNAPSHOT,现在需要将Apache官方发布版本的tag "rel/nifi-1.7.1"合并到自己开发分支的master上。
为了达到升级合并release tag的目的,首先需要clone自己fork的库:
git clone https://github.com/kemixkoo/nifi.git
然后进入本地的nifi目录(即库工作目录),添加Apache官方NiFi库:
git remote add official https://github.com/apache/nifi.git
然后拉取最新的官方代码:
git fetch official
fetch之后,.git/config里的内容如下:
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = https://github.com/kemixkoo/nifi.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master[remote "offical"]
url = https://github.com/apache/nifi.git
fetch = +refs/heads/*:refs/remotes/offical/*
准备工作已经就绪了,现在就开始正式的代码升级合并,为了保证不破坏原master分支,可临时创建一基于master的升级分支upgrade。
git co -b upgrade origin/master
由于先clone的是自己的fork库,所以默认的origin/master是自己fork的master远程分支,而经过fetch之后official/master是官方的master远程分支。
由于官方的release Tag是以rel开头的,比如rel/nifi-1.7.1,合并升级执行:
git merge rel/nifi-1.7.1
如果有合并冲突,可能有“CONFLICT (content)”之类的信息。可通过执行git status查看具体的冲突文件,在“Unmerged paths”列表下有both开头的,均为冲突文件,具体说明见下表:
状态 | 操作 | 说明 |
both modified | 手动解决冲突 | 文件冲突,需手动解决每一个文件的冲突 |
both deleted | 不做操作 | 同时都删除,无需做任何操作,也许拉取了官方的单个提交导致 |
both added | 不做操作 | 同时都添加而无冲突,无需做任何操作,也许拉取了官方的单个新功能提交导致 |
deleted by us | 检查 | 被我们删除,可能无需做任何操作,需检查依赖 |
deleted by them | 检查 | 被官方删除,需检查是否有依赖,如果也不需要,可不做任何操作 |
added by us | 不做操作 | 由我们新添加,无需做任何操作 |
added by them | 不做操作 | 由官方新添加,可能是新功能,无需做任何操作 |
因此主要关注“both modified”状态的文件,需要手动一个一个仔细的解决冲突,否则将导致比较严重的后果。
解决完冲突后,即可执行添加index操作,并提交
git add .
git ci -m "Upgrade to 1.7.1"
至此,升级合并操作已完成,实际上如果想合并最新的master,也是类似操作,只是将release tag “rel/nifi-1.7.1”替换为官方的master,即
git merge official/master
但是为了保证升级成功,可执行相应CI程序,比如打包,测试等等后继验证流程。
最后说明几点:
- 为何用merge而不用rebase?这是因为,rebase解决冲突是每个提交解决一次,如果有比较多的提交有冲突,那么需要解决n次,这是比较烦恼的,采用merge只需一次即可解决所有的冲突。
- 为何merge没有策略选项,这是因为需要保证所有文件状态都可见,而不采用策略而自动处理,势必导致后期查找问题比较困难。