场景
在master
分支外,小明独立开发一个功能f1
分支。f1
中代码量较大且仍在更改,小明希望只将一部分文件合并到master
。其他代码在以后分批次合并。在合并和开发过程中,master
和f1
都会不断修改。
git只支持“全部合并”。
现在小明有file1~file10十个文件需要合并。第一批小明只希望合并file1.
不理想的解法
想法1:发起合并,但只将file1的改动提交到merge commit,清楚其他9个文件的更改。
存在问题:合并之后,master
的文件版本会领先与f1
。git会认为master
先将f1的其他9个文件改动合并过来,然后“清除了这些改动”。这样一来,f1再次修改file2并合并时,会引发冲突,因为master和f1都改过这个文件了。
还有一个问题是,如果f1中剩下的文件没有再改变,第二次尝试f1向master 进行merge
不会有任何改动:因为git认为这些文件都已经合并过了。
所以就有了两难困境:改动f1的文件就会conflict,不改动f1文件就没反应。潜在的危险是:如果文件很多小明一忙,忘记file10在f1
中改动过怎么办?相当于无缘无故丢失了代码;
想法2:创建另一个库res2. 在res1发起合并之后不提交,针对git给出的file change,将f1
中的文件file1直接复制到res2. 这样不会有冲突,但是非常繁琐而且粗暴,也同样存在遗漏文件更改的问题。
想法3:一些博客提到用checkout、rebase等命令合并指定单个文件。但无法应用到多个文件上。
解法
我们要求有2点:1. 利用git的检查机制(而不是人手动复制)保证改动不丢失;2. 减少conflict。
思路:通过merge操作比较不同,通过reset --soft 操作避免master版本领先于f1
从而导致的无法进行下一阶段合并。
执行细节
- master版本为v_m1,f1版本为v_f1
- 将f1合并到master,master版本变更为v_m2;
- 切换到master,通过
reset --soft
将master回退到v_m1,但是保留改动,可以看到file1~file10的十个文件改动。通过git checkout
清除掉其他9个文件的改动,保存file1的改动,成为v_m2’。这个v_m2’ (这个操作实际上就是把别的分支的文件直接覆盖到本分支。但是我用的是sourceTree,sourceTree中这个操作可以很方便地操作多个文件) - master和f1各自更改推进到v_m3和v_f3。
- 在f1分支将master合并过来,称为v_f4。如果file1都被改过,会引发冲突;如果有一方没有改过,git会自动比较+合并,不会冲突;
- 切换到master分支,将f1分支合并过来,重复步骤3。可以看到没有冲突,同时file2~file10的改动仍然显示了出来。满足需求。
【草稿,待完善】