使用不同的树结构将更改从一个repo合并到另一个repo

时间:2014-03-03 22:18:06

标签: git git-branch git-merge git-subtree

我有两个Git repos,foo / master和bar / master:

在foo:

code_root
->dirA
  ->dirB
    -> *some files*

在吧:

code_root
  -> *same files as above*

现在有人对*some files*进行了更改...如何将这些更改合并到*same files as above*

当我说“合并”时,我的意思是我需要提交增量的历史记录(提交消息,日志哈希等)。

3 个答案:

答案 0 :(得分:5)

您可以将更改拆分为子树级别,然后与其他分支合并:

# from your foo project
git subtree split --prefix=dirA/dirB/ --branch=temp-branch [--onto=<onto-sub-note1>] [<commit-sub-note2>]

到子记录1 :似乎因为 bar 项目存在,你必须在某个时间点复制它,并以新的方式启动它库,在这种情况下,如果您希望在此之后进行所有更改,则在引入更改时指定此 bar 提交ID。

提交子注释2 :然后,您需要指定首次复制子项目时使用的提交ID,这样您才能获得此后的更改合并到您已经拥有的 bar 的副本中(这将保留您错过的历史记录)。使用这样的语法将提交ID本身包含在最新的:0abc210^..

您还可以使用--rejoin foo 项目提交回复,如果您希望继续在栏上进行开发,可以更轻松地推送更改来自你的 foo 项目。提交回 foo 是有点无意义的,除了帮助子树命令库它将来更容易分裂更改。

运行split命令后,您将位于 foo 的分支中,该分支只包含这些文件。从那里,您可以与 bar 项目进行正常合并,或者启动一个新项目并将 bar 合并到其中(因为它可能没有正确的历史记录)。在尝试进行合并之前,您可能想要重新分配到分歧点或其他东西。

编辑:此处还有reference for git subtree commands

答案 1 :(得分:1)

所以,你说foo和amp;中的文件基本相同。吧,只是foo中的那些比bar中的那些更新:

如果是,那么你可以采取差异:

diff -b /path_to/foo/dirA/dirB/ /path_to/bar/ > diff.patch

然后将补丁应用到条形码上:

cd bar

patch -p1 < diff.patch

更新:根据OP更新,他正在寻找维护提交历史记录,以上情况不适用。

答案 2 :(得分:1)

查看git bookgit magic。根据确切的更改,也许一轮历史重写(git filter-branch和朋友;或者git rebase --interactive的强力应用,理顺每个提交)可以恢复受损的克隆的理智,然后允许清洁合并。

其他替代方法是将每个提交导出为补丁(实质上是运行git format-patch),从那里恢复提交数据并对要应用的补丁进行反向工程。在执行此操作时,您甚至可以使用机会重写更清晰/更简单的历史记录。

显然,可行性取决于分歧的程度,以及有多少“错误应用”的提交受到威胁。