【问题标题】:Git - merge feature branch on more than one branchGit - 在多个分支上合并功能分支
【发布时间】:2013-12-17 14:42:13
【问题描述】:

我有一些关于 git 和良好实践的问题......

git仓库的状态是:

V1.0  :       B.A--B.B
V1.1  :      /  C.A--C.B
            /  /
master: A--B--C--D

我有一个大师,有 2 个版本:1.0 和 1.1。

必须开发一个新功能,并且必须在 2 个分支上应用:V1.1 和 master。

有什么更好的方法来做到这一点?我想我必须创建一个功能分支,但基于哪个? master 还是 V1.1?

一旦开发得到验证,最好的合并策略是什么?合并?樱桃采摘?变基?

特性分支将被推送到上游,因为我不会是唯一一个参与它的人。还会有多个提交。

感谢您的帮助!


如果特性分支是基于master的,我会有这个:

V1.0  :       B.A--B.B
otherbranch :/  C.A--C.B
            /  /
master: A--B--C--D
                  \
topicbranch:       E--F--G

功能开发完成后,我可以轻松合并 master 和 topicbranch 以将新功能添加到 master 中。

但是如何将提交 E、F 和 G 添加到 otherbranch(就在 C.B 之后)?这就是我认为的地方

checkout otherbranch;
git merge topicbranch;

不起作用,因为它还会添加提交 D。

【问题讨论】:

    标签: git merge feature-branch


    【解决方案1】:

    你是对的:将新主题分支合并到V1.1 将引入提交D。 (将其合并到V1.0 将同时引入C D。)

    我只是假设我们正在处理V1.1;这同样适用于V1.0,除了有时还要处理C。 (而且我不确定你为什么在编辑中将V1.1 更改为otherbranch,但我会在下面使用otherbranch,因为我做了很多复制粘贴......)

    您至少有以下选择:

    • 通过“真正的”合并引入 D(如果需要,可以使用 --no-ff,尽管不是),然后恢复它。
    • --no-commit进行“真正的”合并(就像--no-ff一样),然后反向应用D(最简单的git revert --no-commit,但你也可以git show D | git apply -R -,例如),然后提交结果。
    • 执行“squash”合并,然后删除 D,就像使用任一“真实”合并一样。
    • 樱桃采摘(带或不带--no-commitEFG

    这些都会导致不同的提交图,除了 squash-merging 和“取消应用”D 然后进行一次提交会产生与樱桃采摘 E-through- 相同的图(和文件) G--no-commit 然后提交结果。

    真正的合并给你一个真正的合并提交:

    V1.0  :       B.A--B.B
    otherbranch :/  C.A--C.B-----M
                /  /            /
    master: A--B--C--D         /
                      \       /
    topicbranch:       E--F--G
    

    如果您允许git merge 进行提交(并且它能够自行提交),则生成的树将包含在D 中所做的更改,因为otherbranchtopicbranch 的合并基础是提交C。但是,如果您抑制提交,然后在工作目录中撤回在提交D 中所做的更改,并且只有然后提交生成的工作目录文件,提交M 将忽略D 中的更改。

    缺点是,在将来尝试将 mastertopicbranch 合并到 otherbranch 时,git 会认为 D 的更改在那里(因为它们,你刚刚删除了它们)。

    对 D 进行单独的还原提交会给出此图:

    V1.0  :       B.A--B.B
    otherbranch :/  C.A--C.B-----M--R
                /  /            /
    master: A--B--C--D         /
                      \       /
    topicbranch:       E--F--G
    

    其中R 是“还原D”更改。同样,将来尝试将 mastertopicbranch 合并到 otherbranch 不会尝试引入来自提交 D 的更改,因为 git 可以告诉它们已经被放入。(这和以前的情况是,您将D 取出的事实被明确记录为单独的提交——除非他们去看,否则任何人都不会注意到,但他们可能更容易找到他们是否/何时 去看看,如果这只是混合到合并提交中M。)

    在 git 中,“壁球合并”提交与常规合并提交完全相同,只是 M 只有一个父级。 Git 像往常一样经历相同的合并机制,它只是没有进行最终提交,也没有进行设置,以便您的手册 git commit 将进行双亲提交。所以你得到了这个图表:

    V1.0  :       B.A--B.B
    otherbranch :/  C.A--C.B-----M
                /  /
    master: A--B--C--D
                      \
    topicbranch:       E--F--G
    

    (调用此提交M 是一种谎言,因为它不是合并,而是什么鬼:-))。同样,您可以选择是否在提交M 之前或之后反转D 之前,应用相同的推理。但是,在任何一种情况下,由于M 不是实际 合并提交,因此稍后在分支中合并的尝试将尝试引入D,因为合并基础没有移动。 (当然,它还会尝试再次通过G 引入E。如果幸运的话,git 将能够判断它们已经在其中,并且合并将自动“思考”类似“哦,好的,已经到了,继续!”。如果没有,您将需要进行一些手动清理。)

    最后,精选提交会复制他们的更改,或者使用--no-commit 只是应用他们的更改并跳过提交部分。因此,假设您将所有三个组合成一个提交 N,您将得到如下图:

    V1.0  :       B.A--B.B
    otherbranch :/  C.A--C.B---N
                /  /
    master: A--B--C--D
                      \
    topicbranch:       E--F--G
    

    如果你把它们分开你会得到E'--F'--G'(这些名字表示你会看到的补丁如果你git show提交将基本上匹配你看到的git show的补丁EFG)。如果你将它们组合成一个大的新补丁N,那么N 看起来与M 在壁球合并案例中的外观非常相似,只是你不必“取消应用”@987654391 @,因为您不会提出这些更改。

    无论哪种方式,您都必须为分支 V1.0 重复整个过程。

    (但请注意:如果您有一个提交 N 引入了 E+F+G,那么您可以执行一个 git cherry-pickN。这实际上并不比 @987654397 中的一个樱桃选择更容易@,除了可能要考虑。)

    【讨论】:

    • Woo 感谢您的回答:-) 我将名称从 1.1 更改为 otherbranch 以映射随机用户名给出的解释。我一直在寻找“最干净”的方式来做到这一点,我想我会选择樱桃。
    【解决方案2】:

    一般来说,master 分支是用于开发新功能的。所以你会

    git checkout master HEAD^
    git branch --track topicbranch
    

    您将使用topicbranch 来开发新功能。这样每次更新主分支时,您都可以这样做

    git checkout topicbranch
    git pull
    

    轻松地将更新从上游/主流分支拉入您的分支。

    您所建议的最大问题是特定“版本”永远不应该改变。它应该位于开发历史中,并带有像v1.0 这样的标签来引用它。如果您希望其他主题分支也可以访问您的新主题分支,您可以这样做

    git checkout otherbranch
    git merge topicbranch
    

    并将otherbranch 的上游视为topicbranch


    根据经验,您总是希望使用 git merge 来组合存储库中的两个 ref 并创建单独的分支来保存每个分支。这是因为git merge 具有许多使一切变得更清洁的功能。 git cherry-pick 之类的内容仅适用于您犯了错误或仅在您对一个分支进行更改后才顿悟的情况。

    【讨论】:

    • 'topicbranch' 将基于分支 master。当将它与“otherbranch”合并时,它还将在“otherbranch”中添加“otherbranch”和“master”之间的所有差异。我不想在“otherbranch”中的唯一更改是在“topicbranch”中的提交
    • @KevinN。查看我的编辑以了解如何完全按照您的意愿进行操作。
    • 好的,这样我就不用把 topicbranch 和 master 合并了。但这并不能解决将 topicbranch 与 otherbranch 合并的问题。
    • @KevinN。我已经向你展示了如何做到这一点。 git checkout otherbranch 后跟 git merge topicbranch。虽然可能存在合并冲突,但您必须使用git mergetool 来修复它们。
    • 我仍然认为合并不是解决方案,otherbranch 和 master 有自己的“生命”并且可以非常不同,我唯一不想合并的东西是添加到 topicbranch 中的东西。我已经编辑了原始问题以添加新的状态模式:-)
    猜你喜欢
    • 1970-01-01
    • 2013-12-05
    • 2012-06-21
    • 2021-01-12
    • 2015-11-18
    • 1970-01-01
    • 2021-08-18
    • 2017-07-01
    • 2012-04-30
    相关资源
    最近更新 更多