如何合并没有共同祖先的两个分支? [英] How to merge two branches without a common ancestor?

查看:334
本文介绍了如何合并没有共同祖先的两个分支?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  I1  -  I2  -  M2  -  N  -   -   -  Z 
code>

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

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

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



我可以合并 M1 M2 转换为 M3 ,然后重新绑定,但我不知道如何删除 I1 I2 提交,如果我可以安全删除 M3 提交(我发现了一些建议来保留合并通信

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

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



最优雅的解决方案是重新整理由 N .. Z svn 分支之上提交的更改。

解决方案

免责声明 :我只在玩具仓库中使用过移植点。但它是一个你可能从来没有听说过的晦涩难懂的功能,它可能会对你的情况有所帮助。

您可以使用嫁接点来伪造祖先信息。请参阅什么是.git / info / grafts for?或继续立即到接枝点上的git wiki条目



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

  $ cat .git / info / grafts 

随后,它看起来像 M2 是一个空的提交,只是合并 I2 M1 转化为普通树状结构。 主要缺点 :移植点未提交;因此,它不会检出,但需要手动添加到存储库的每个本地工作副本中。









更新: 使用 git replace --graft



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

  git replace --graft<您的M2提交哈希> <您的M1提交哈希> 

创建嫁接。这存储在 .git / refs / replace / 中。虽然git默认不会获取或推送这些refs,但它们可以使用以下方式在存储库之间同步:

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

StackOverflow:如何推送'refs / replace'而不用在git中推送任何其他文件?


I have started using Git in the middle of my project, where the first two commits are just some initial settings (.gitignore and .gitattributes), and the third commit M2 adds the content of the SVN trunk:

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

I have imported the SVN history in a branch named svn, where M1 is the SVN trunk (with the same content as M2, except .gitignore and .gitattributes):

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

Q: What is the best approach in merging both branches?

I could merge M1 and M2 into M3, and then rebase, but I don't know how to delete the I1 and I2 commits and if I can safely remove the M3 commit (I have found some advices to preserve the merge commits, but in this case M3 it's not necessary anymore).

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

Another way would be to cherry-pick the N .. Z commits into svn branch by hand, but I would like to avoid this approach.

The most elegant solution would be to rebase the changes introduced by N .. Z commits on top of svn branch, but I didn't found yet the required syntax for two branches without a common ancestor.

解决方案

Disclaimer: I've only used "graft points" myself once in a toy repository. But it is an obscure feature which you may not have heard of, and which _may_ be helpful in your situation.

You could use "graft points" to fake the ancestry information. See, e.g., What are .git/info/grafts for? or proceed immediately to the git wiki entry on graft points.

In essence, you would create a file .git/info/grafts that tricks git into thinking that commit M1 is an ancestor of commit M2:

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

Subsequently, it would look like M2 was an empty commit that just merged I2 and M1 into a common tree.

The major downside: the graft point is not committed; therefore, it is not checked out, but needs to be added to each local working copy of the repository manually.



Update: use git replace --graft instead.

Graft points, as described above, have been superseded. Run

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

to create the graft. This is stored in .git/refs/replace/. Although git does not fetch, or push, these refs by default, they can be synchronized between repositories using:

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?)

这篇关于如何合并没有共同祖先的两个分支?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆