如何在没有共同祖先的情况下合并两个分支?

时间:2009-09-28 18:56:55

标签: git merge rebase

我已经开始在我的项目中使用Git,其中前两个提交只是一些初始设置(.gitignore和.gitattributes),第三个提交 M2 添加了内容SVN主干:

I1 -- I2 -- M2 -- N -- .. -- Z

我已在名为 svn 的分支中导入SVN历史记录,其中 M1 是SVN主干(内容与 M2 相同,除了.gitignore和.gitattributes):

A -- B -- ... -- K -- L -- M1

问:合并两个分支的最佳方法是什么?

我可以将 M1 M2 合并到 M3 ,然后进行rebase,但我不知道如何删除 I1 I2 提交,如果我可以安全地删除 M3 提交(我已经找到一些建议来保留合并提交,但在这种情况下 M3 不再需要了。)

A -- B -- ... -- K -- L -- M1
                             \
                              M3 -- N' -- .. -- Z'
                             /
               I1 -- I2 -- M2 -- N -- .. -- Z

另一种方法是手动挑选 N .. Z 提交到 svn 分支,但我想避免这种方法。

最优雅的解决方案是在 svn 分支之上修改由 N .. Z 提交引入的更改,但我没有找不到没有共同祖先的两个分支所需的语法。

3 个答案:

答案 0 :(得分:25)

免责声明我自己只在玩具库中使用过“贪污点”。但这是一个你可能没有听说过的晦涩难懂的特征,而且对你的情况有帮助。

您可以使用“嫁接点”伪造祖先信息。例如,请参阅What are .git/info/grafts for?或立即进入the git wiki entry on graft points

从本质上讲,你会创建一个文件.git/info/grafts,让git认为提交 M1 是提交 M2 的祖先:

$ cat .git/info/grafts
<your M2 commit hash> <your M1 commit hash>

随后, M2 似乎是一个空提交,只是将 I2 M1 合并到一个公共树中。

主要缺点 :嫁接点未提交;因此,它不会被签出,但需要手动添加到存储库的每个本地工作副本中。



更新: 改为使用git replace --graft

如上所述,移植点已被取代。运行

git replace --graft <your M2 commit hash> <your M1 commit hash>

创建移植物。这存储在.git/refs/replace/中。虽然git默认不提取或推送这些引用,但它们可以使用以下命令在存储库之间进行同步:

git push origin 'refs/replace/*'
git fetch origin 'refs/replace/*:refs/replace/*'

StackOverflow: How to push 'refs/replace' without pushing any other refs in git?

答案 1 :(得分:3)

我会做以下事情:

git checkout M1; git cherry-pick I1; git cherry-pick I2;

将.gitignore和.gitattributes添加到包含更好历史记录的分支。

然后只需将新提交设置在那个提交之上:

git filter-branch --parent-filter 'if $GIT_COMMIT = $hash_of_N; then printf -- '-p $hash_of_cherrypicked_I2\n'; else cat; fi'

这样做的缺点是你重写了历史。

所以另一种方法是创建一个类似于the one for the Linux kernel的脚本 并将其放入您的存储库。

答案 2 :(得分:3)

  

最优雅的解决方案是重新定义N .. Z在svn分支之上提交的更改,但是我没有找到没有共同祖先的两个分支所需的语法。

尝试首先将I1和I2挑选到M1上,然后使用命令git rebase --onto M1' M2 Z(其中M1'是M1-I1-I2分支)。我不确定rebase --onto是否在没有共同祖先时起作用,但如果没有,则有可能使用补丁。使用git format-patch生成M2..Z的补丁,然后使用git am将其应用于M1顶部。 Here are some experience reports使用它来转换旧的SVN和CVS存储库。

相关问题