我以为最近碰到的这个状况应该不算少见,作一点总结。git
这个repository的流程是 remote master
分支受保护,不直接接受push,新增feature经过pull request合并到master
分支。web
某个组员本身的A分支中的P文件是旧版本,提交了pull request,因为种种缘由没有发现P文件的问题,结果合并到master
分支后,master
分支的P文件部分的代码倒退回了N天前。我尝试经过B分支(最新P版本)发起一个pull request,合并到master
试图将P从新恢复到最新版本。但结果出乎意料,P仍然是旧版本。vim
问题出在git自身的三路合并(three-way merge)机制,若是base和X分支的某一部分代码相同,但和Y分支不一样,合并的结果就会采用Y分支不一样的那部分
再加上以前我对git合并的一个误区,觉得 merge conflicts 给出的结果涵盖了两个分支全部变更。事实上仅属于单一分支的变更不会显示。(本地除了用外部合并工具,还能够git difftool --ours
or git difftool --theirs
or git difftool --base
)bash
如今用图例来展现下合并的时间轴:工具
图示:假设P5版本比P2新, M1是引入旧版本的合并, M2是我尝试修复的合并:fetch
B: P5-----------------P5 / \ master: ---P5(M1 base)---P5(M2 base)---P2(M1)---P2(M2) \ / A: P2----------------------P2
在M2合并的时候,Git(包括GitHub上处理合并冲突的webIDE)生成的冲突文件不会显示仅由P2改动的区域。code
目前我发现的解决方法只能经过外部合并工具(git mergetool
)好比Kaleidoscope, Beyond Compare, vimdiff或者JetBrains家自带的冲突处理工具才能完整看到哪些是仅仅被P2改动的部分。
但彷佛GitHub的pull request不支持用外部合并工具处理冲突。除非在GitHub处理冲突的webIDE上直接粘贴P5,想经过M2更新到P5无解。若是P2不单单包含旧版本,还有新增的feature,人工处理就会很麻烦。three
后来个人解决方法是:在本地用外部合并工具解决冲突后,再提交pull request。
具体操做:从M1 pull到了B分支(这样一来base就变成M1),在本地经过外部合并工具修复回P5(或者git checkout --ours path/to/P
),再发pull request合并到master
。
还有种方法就是 pull master
后,在本地把B分支合并到master
(经过外部合并工具修复回P5),用管理员权限push到 remote master
。rem
GitHub上pull request的Resolve conflicts
慎用
本地git生成的冲突文件慎用。
鉴于以上几点,从此pull request出现冲突时,能够采用以下流程:
(假设pull request对应的分支是feature
)get
feature
fetch到本地,把 remote master
合并到该分支(能够先fetch master
,再合并到本地feature
,或者直接把 remote master
pull到本地的feature
),再用外部合并工具解决冲突,而后push,这时候pull request上显示能够合并,直接点Merge按钮便可。master
不受保护或者可使用管理员权限强行push,则还能够在本地 pull master
后,把feature
合并到master
,再 push master
到GitHub。https://www.git-tower.com/lea...
https://stackoverflow.com/que...
https://git-scm.com/docs/git-...