温馨提示:本文翻译自stackoverflow.com,查看原文请点击:git - Merge a branch into the folder of another branch
git

git - 将一个分支合并到另一个分支的文件夹中

发布于 2020-03-27 11:56:26

我有一个分支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

查看更多

查看更多

提问者
Alan
被浏览
211
Mark Adelsberger 2019-07-04 02:59

您不能直接将其合并。

There is some confusion in the comments about whether git's rename detection would help here. Based on how you say the branch was created (with filter-branch), it most likely won't. That's because the new branch probably doesn't have a common ancestor with the old branch.[1]

So first you have to solve the problem of getting git to recognize corresponding files from the branches; and then you have to solve the problem that it still won't know the most recent common ancestor for the two current states of that file, so the merge won't go smoothly. (Each file that exists on both branches will conflict on, most likely, the entire file, not really merging anything.)

这是由于“不同分支上的内容不同”而引起的问题之一。这不是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将查看O之间的修补程序,该修补程序B符合重命名检测的条件(只要移动的文件变化不大)。

filter-branch可能创造了完全不同的历史

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

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

默认情况下,合并将失败(没有共同的历史记录),并且如果您没有使其失败(通过说允许不相关的历史记录),则合并的行为就好像合并基础为空TREE(即没有文件)。从补丁到A创建foo/file,并从该补丁,以B创建file,但是没有打补丁的一条路径都删除该文件并创建它的其他,所以重命名检测不会发生。合并将创建文件的第二个副本。