首页 > 解决方案 > 将一个分支合并到另一个分支的文件夹中

问题描述

我有一个分支 A 有一个名为foo. 另一个名为 B 的分支只有文件夹的内容foo。是否可以将分支 B 合并到分支 A 的文件夹foo中?

分支 A 包含例如

foo/
    hello_world.c
goo/
    AliceAndTom.c

分支 B 仅包含文件夹 foo/ 的内容

./
    hello_world.c
    hello_world.h

合并分支 B 后我想要在分支 A 中的结果:

foo/
    hello_world.c
    hello_world.h
goo/
    AliceAndTom.c

编辑:分支 B 是使用 git 命令创建的git filter-branch --subdirectory-filter dir/to/filter -- subdir_branch

标签: git

解决方案


不能直接合并。

关于 git 的重命名检测是否会有所帮助的评论中存在一些混淆。根据您所说的分支是如何创建的(使用filter-branch),它很可能不会。那是因为新分支可能与旧分支没有共同的祖先。 [1]

所以首先要解决让git从分支中识别对应文件的问题;然后你必须解决它仍然不知道该文件的两个当前状态的最新共同祖先的问题,因此合并不会顺利进行。(两个分支上存在的每个文件很可能会在整个文件上发生冲突,而不是真正合并任何东西。)

这是“不同分支上的不同内容”可能引起的问题之一;这不是 git 的工作方式,它可以使跨分支的更改集成变得非常乏味。

这将是多么乏味取决于自filter-branch运行以来每个分支上的文件更改了多少。我能想到的最一般的程序是:

(1) 编写一个将文件移回其子目录的脚本

(2)filter-branch在较新的分支上运行(使用上述脚本作为树过滤器),创建另一个结构更接近原始分支的分支

(3) 识别新分支中与原始分支中的一次提交相对应的最后一次提交

(4) 使用git replace上面标识的提交替换来自原始分支的相应提交。

(5) 现在您应该能够将新分支合并到原始分支。然后您可以撤消git replace并可能处置新分支。

关于这些步骤中的每一个,都有一些细节需要了解;这不是一个简单的过程,所以如果你想了解它,请参阅相关命令的文档。


[1] - 更具体地说,要应用重命名检测,git 必须查看一个补丁,该补丁既删除一个文件,又创建另一个具有足够相似内容的文件(在不同的路径)。

如果您已经从master分支分支,然后在分支上进行了提交,您在其中移动了文件,那么您现在将看到类似

x -- x -- O -- A <--(master)
           \
            x -- x -- B <--(bramch)

合并branch到 时master,git 会查看 和 之间的补丁OB它符合重命名检测的标准(只要移动的文件没有太大变化)。

filter-branch很可能创造了一个完全独立的历史

x -- x -- x -- A <--(master)

x -- x -- B <--(branch)

默认情况下,合并将失败(没有共同的历史记录),如果您使它不会失败(通过说允许不相关的历史记录),那么它将表现得好像有一个空的合并基础TREE(即没有文件)。从那个到A创建foo/file的补丁,以及从那个到B创建的补丁file,但是这两个补丁都不会删除一个路径上的文件并创建另一个路径,因此不会发生重命名检测。合并将创建文件的第二个副本。


推荐阅读