我有(或者我的目标是!)像这样的回购:
Master *-----*--*----------C---
\ \
Project1 \-*-------A----B----M2---A'--B'---
\ \ \
Project2 \----------*---M1------------M2---
我想合并 M2 ,但我希望 A 和 B 完全忽略。然后,我将手动(例如,挑选)重新创建 A' 和 B' ,如果有必要,可以在主设备的新更改之上。
Project2基于Master,但合并了Project1的更改。
期望的结果:
我希望点 M2 在文件方面与 C 完全相同。
我需要Project1拥有自己的线性历史记录,以便Project2可以从中合并。
上下文:Master是Drupal的主要代码库。 Project1是我用来维护特定补丁的分支,我想与几个项目共享。 Project2(和许多其他人)从Project1合并。
我考虑过:
git merge -s recursive -X theirs master
问题在于AFAIK如果发生冲突,它只会选择theirs
。因此,如果A的变化不冲突,它将出现在 M2 ,这意味着A'将是不完整的。
git revert B..A ; git merge C
这会有效但会给我留下一个混乱而漫长的历史。
有git merge -s ours
,但似乎没有git merge -s theirs
。
我不想git reset --hard C
因为这会(我认为)打破了将Project1合并到Project2的可能性。另一种方法是将Project1重新绑定到C,但同样,这意味着我无法合并到Project2中。
答案 0 :(得分:2)
我会反对你的计划 - 你试图欺骗git。 Git不喜欢被愚弄。你也在“伪装”你的历史。 M2,A'和B'都应该是一次提交 - 合并。
但如果你想继续,请这样做:
git merge --no-commit C
rm -rf *
git checkout C .
git commit
如果您要保留任何gitignored文件,请在rm
之前备份它们,然后再恢复它们。
或者,您也可以(实际上更清洁)
git checkout C
git symbolic-ref HEAD refs/heads/Project1
git update-ref MERGE_HEAD C
git commit
答案 1 :(得分:1)
这可以通过“plumbing”命令来完成:
$ git checkout Project1
$ git diff HEAD..master | patch -p1
$ git add -A .
$ git commit-tree `git write-tree` -p master -p Project1 \
-m "Merge to clean Master at v1.2"
0c5290081989cc28ff3977fbfe3951db7b7778b0
$ git reset --hard 0c5290081989cc28ff3977fbfe3951db7b7778b0
git diff HEAD..master
会告诉我如何在一个大的地方( B )和我想去的地方( C )补丁,补丁当然会应用它。
git add -A .
会将工作树中的所有更改添加到索引中。
然后我们使用下一行创建一个合并提交:git-write-tree
从索引创建一个新的树对象,并将其SHA1作为参数输出到git commit-tree
,这将创建一个提交它有两个父母,Project1的当前负责人( B )和主人( C ),并给它一个合适的信息。
Git将创建提交对象,但它不会更新任何分支以使用此提交。最后一行告诉git我们希望将当前分支Project2推进(快速转发)到它生成的提交SHA1。
如果需要,你可以从那里重新创建(例如可以尝试使用樱桃挑选)补丁A'和B'。