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

发布于 2024-11-16 10:55:55 字数 1328 浏览 1 评论 0 原文

我在将开发分支的子树合并回集成分支时遇到问题。

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

我的目录结构是这样的:

[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 为 合并子树,但是当我执行 git read-tree 时,它​​们失败了:

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

我尝试使用 子树script 托管在 github 上,但我不太幸运。当我这样做时:

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

我看到 Dir3 已被合并的证据,并且合并因冲突而失败。

我可以挑选要合并的文件,但这对于一个常见且直接的问题来说似乎不必要地复杂。

I'm having trouble merging a subtree of a development branch back into the integration branch.

I have two branches, one was used for development and one is used for integration. Extensive development has been done in the development branch and I want to merge a portion of it back in. The specific portion that I want to merge is all contained in one subtree of the development branch.

My directory structure is like this:

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

I want to merge Branch B/Dir2/DirA into Branch A/Dir2/DirA. I want File1 and File2 to be merged and File3 and File4 should be created in Branch A. I don't want to pick up Dir3, or any changes in Dir1.

I've tried the steps outlined by kernel.org for merging subtrees, but they fail when I do the git read-tree with:

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

I've tried using the subtree script which is hosted on github, but I am not having much luck with it. When I do:

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

I see evidence that Dir3 has been merged and the merge fails with conflicts.

I could cherry-pick the files to merge, but that seems unnecessarily convoluted for what should be a common and straight-forward problem.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

浪推晚风 2024-11-23 10:55:55

您想要的可能很简单:

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

详细信息

此配方将子树从 Branch_B 复制到 Branch_A,并且(可选)还在 git 的项目历史记录中创建合并提交:

  1. 切换到 Branch_A,以防您尚未到达。

    git checkout Branch_A

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

    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

步骤3中checkout的形式可能看起来很陌生,但官方文档指出,当不使用这种形式时,习惯的分支切换行为实际上只是一种方便:

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

因此,如果您确实提供了显式路径,它不会切换分支,只是从该路径复制文件。

What you want may be simply:

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

Details

This recipe copies a subtree from Branch_B to Branch_A, and (OPTIONALLY) also creates a merge-commit in git's project history:

  1. Switch to Branch_A in case you aren't there already.

    git checkout Branch_A

  2. (OPTIONAL) Establish a merge commit, without changing any files in your workspace (merge strategy "ours"). This "empty" commit just adds the other branch as a second parent, creating a history link. If that's unimportant to you, you may skip this step; it's not required for the subsequent step.

    git merge Branch_B -s ours

    NOTE: only do this in a clean workspace; this command may fail if you have any files modified or staged.

  3. Copy the contents of subtree Dir2/DirA from Branch_B into your workspace, without changing your active branch.

    git checkout Branch_B Dir2/DirA

  4. Commit the files from Branch_B into Branch_A. If you omit --amend then a new commit is created for this step; using it will make the new files part of the earlier merge commit instead.

    git commit --amend

The form of checkout in step 3 may seem unfamiliar, but the official documentation states that the customary branch-switching behavior is actually just a convenience when this form is not used:

If no paths are given, git checkout will also update HEAD to set the specified branch as the current branch.

So if you do supply an explicit path, it will not switch branches, just copy the files from that path.

烟柳画桥 2024-11-23 10:55:55

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

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

分支 A 指向提交 I< /code> 和分支 B 指向提交 H。现在您想要将 B 中的一些更改接管到 A 中。

例如提交 DF 修改了 Dir2EGHDir1Dir3 做了一些事情。因此,实际上您只想将提交 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 为您准备的树中,如下所示这些提交已经合并。

The problem you have is that git isn't designed to do such a thing. Consider the following history that might result in your two branches A and B from the question:

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

with branch A pointing at commit I and branch B pointing at commit H. Now you want to take over some changes in B into A.

For example commits D and F modified Dir2, E, G and H did something to Dir1 and Dir3. So actually you only want to have commits D and F added to your integration branch A.

That means that branch B wasn't created carefully enough and you actually want to redo it into (at least) two clean topic branches. Something like:

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

If there are commits that are touching both, Dir1 and Dir2 then these commits are "bad", as they don't address a single topic, but does several things at once. In this case you might want not only reshuffle the commits, but also change the commits to be good ones using git-rebase -i.

Of course you could just merge branch A and fix-up the resulting tree. But that would make it hardly possible to continue working on the "non-merged" changes in A, because when you merge a descendant of A you would have to fix-up the resulting tree once more, because the changes of E, G and H would not be included in the tree that git prepares for you, as these commits are already merged.

何以笙箫默 2024-11-23 10:55:55

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

Merging subtrees really refers to merging part of an external project into your project. I'd refer to this blog post to accomplish what you want to do: http://jasonrudolph.com/blog/2009/02/25/git-tip-how-to-merge-specific-files-from-another-branch/

枯叶蝶 2024-11-23 10:55:55

我只需将 dirA 设为子模块并为其引入第三个存储库。

I would simply make dirA a submodule and introduce a 3rd repo for it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文