git:将子树从一个分支合并到另一个分支

时间:2011-06-21 23:58:28

标签: git branching-and-merging

我无法将开发分支的子树合并回集成分支。

我有两个分支,一个用于开发,一个用于集成。在开发分支中已经进行了广泛的开发,我想将其中的一部分合并回来。我想要合并的特定部分都包含在开发分支的一个子树中。

我的目录结构如下:

[Branch A]              [Branch B]
    |                       |
    +--Dir1                 +--Dir1
    +--Dir2                 +--Dir2
        |                   |   |
        +--DirA             |   +--DirA
            |               |       |
            +--File1        |       +--File1
            +--File2        |       +--File2
                            |       +--File3
                            |       +--File4
                            +--Dir3

我想将Branch B / Dir2 / DirA合并到Branch A / Dir2 / DirA中。我希望合并File1和File2,并且应该在分支A中创建File3和File4。我不想选择Dir3,或者Dir1中的任何更改。

我已经尝试了kernel.org为merging subtrees概述的步骤,但是当我使用git read-tree时它们会失败:

error: Entry 'Dir1/DirA/File1' overlaps with 'Dir1/DirA/File1'.  Cannot bind.

我已经尝试使用github上托管的subtree script,但我没有太多运气。当我这样做时:

git checkout Branch_A
git subtree merge -P Dir2/DirA Branch_B

我看到证据表明Dir3已经合并,合并失败并伴随着冲突。

我可以挑选合并的文件,但这对于应该是一个普通而直截了当的问题似乎有点不必要。

4 个答案:

答案 0 :(得分:1)

你想要的可能只是:

git merge Branch_B -s ours  [OPTIONAL]
git checkout Branch_B Dir2/DirA

详细

此配方将子树从Branch_B复制到Branch_A,(OPTIONALLY)也在git的项目历史中创建合并提交:

  1. 如果您不在,请切换到Branch_A。

    git checkout Branch_A

  2. (可选)建立合并提交,而不更改工作区中的任何文件(merge策略“我们的”)。这个“空”提交只是将另一个分支添加为第二个父,创建历史链接。如果这对你不重要,你可以跳过这一步;后续步骤不需要它。

    git merge Branch_B -s ours

    注意:只能在干净的工作区中执行此操作;如果您修改或暂存了任何文件,则此命令可能会失败。

  3. 将子树Dir2 / DirA的内容从Branch_B复制到您的工作区,而不更改您的活动分支。

    git checkout Branch_B Dir2/DirA

  4. 将Branch_B中的文件提交到Branch_A。如果省略--amend,则会为此步骤创建新的提交;使用它会使新文件成为早期合并提交的一部分。

    git commit --amend

  5. 步骤3中checkout的形式可能看起来不太熟悉,但官方文档指出,当此表单时,习惯性的分支切换行为实际上只是一种便利:< / p>

      

    如果没有给出路径,git checkout也会更新HEAD以将指定的分支设置为当前分支。

    因此,如果您提供显式路径,则不会切换分支,只需从该路径复制文件。

答案 1 :(得分:1)

你遇到的问题是git并不是为了做这样的事情而设计的。请考虑以下历史记录,该问题可能会导致问题中的两个分支AB

C - D - E - F - G - H
 \
  H - I

分支A指向提交I,分支B指向提交H。现在,您希望将B中的一些更改接收到A

例如,提交DF已修改Dir2EGHDir1做了一些事情, Dir3。实际上,您只希望将提交DF添加到集成分支A

这意味着分支B没有足够仔细地创建,并且您实际上想要将其重做为(至少)两个干净的主题分支。类似的东西:

git checkout -b topic_I_want_to_merge_touching_Dir2 C
git cherry-pick D
git cherry-pick F
git checkout -b topic_I_dont_want_to_merge_now C
git cherry-pick E
git cherry-pick G
git cherry-pick H
git checkout B
git merge topic_I_want_to_merge_touching_Dir2

如果有提交同时触及Dir1Dir2,则这些提交“不好”,因为它们不会解决单个主题,而是同时执行多项操作。在这种情况下,您可能不仅要重新调整提交,还要使用git-rebase -i将提交更改为好的提交。

当然你可以合并分支A并修复生成的树。但这样就很难继续处理A中的“非合并”更改,因为当您合并A的后代时,您将不得不再次修复生成的树,因为EGH的更改不会包含在git为您准备的树中,因为这些提交已经合并。

答案 2 :(得分:0)

合并子树实际上是指将外部项目的一部分合并到项目中。我将参考此博客文章来完成您想要做的事情:http://jasonrudolph.com/blog/2009/02/25/git-tip-how-to-merge-specific-files-from-another-branch/

答案 3 :(得分:-2)

我只是让dirA成为一个子模块并为它引入第三个回购。