【问题标题】:Git: how to separate out a feature branch after the factGit:事后如何分离出功能分支
【发布时间】:2015-06-03 17:49:49
【问题描述】:

如何将某个功能的某些提交从现有分支移动到功能分支中,并有效地将它们从当前分支中删除 - 就好像该功能是在单独的功能分支中开发的一样?

背景:develop 分支包含对两个功能 A(例如,50 次提交)和 B(10 次提交)的提交,因为它们原本应该在同一个版本中。现在我们正在延迟特征 B。因此,我们希望在 develop 分支中只有特征 A,以及一个包含 A 或 A 和 B 提交的新 featureB 分支,这样如果我们合并两个分支,我们获取develop 分支的当前位置。

一种方法是从develop 分支的当前位置创建featureB 分支,然后将提交从A 反向应用到develop。但是新的developfeatureB 的合并将只是A。

另一种方法是将当前的 develop 重命名为 featureB 并将 A 的所有提交挑选到新的 develop 分支中。但这会有效地修改develop的历史记录,很麻烦。

有什么更好的方法来做到这一点?

【问题讨论】:

    标签: git feature-branch


    【解决方案1】:

    从当前的开发状态创建分支featureB。将代码提交到分支 develop 以进一步开发 featureA。将代码提交到分支featureB 以开发featureB。定期将分支 featureB 与分支 develop 相对应,以便它具有为开发 featureA 而添加的更改。

    【讨论】:

    • 谢谢,但这仅适用于未来的提交。问题是我必须从分支开发中删除或恢复已经存在的 featureB 提交,同时让两个分支都可以合并到当前状态。我的问题是如何做到这一点。
    【解决方案2】:

    如果你的develop 分支已经发布并且你不想重写它的历史(这将是最简单的方法),那么你确实可以恢复你在develop 中的更改,开始一个新的featureB 分支在develop 之上重新调整B 的基础。顺带一提:

     #given history (top - newest)
     #shaA3 <-- develop, HEAD
     #shaB2
     #shaA2
     #shaB1
     #shaA1
    

    还原:

     git revert B2
     git revert B1
    

    现在历史包含:

     #revert of shaB1 <-- develop, HEAD
     #revert of shaB2
     #shaA3
     #shaB2
     #shaA2
     #shaB1
     #shaA1
    

    创建featureB 并重新播放还原的提交:

     git checkout -b featureB
     git rebase -i --onto develop shaB1~1 featureB
    

    注释掉所有提交,除了那些属于功能 B 的提交(shaB1shaB2 在我们的例子中)并完成变基。此时您应该有历史记录:

     #shaB2' <-- featureB, HEAD
     #shaB1'
     #revert of shaB1 <-- develop
     #revert of shaB2
     #shaA3
     #shaB2
     #shaA2
     #shaB1
     #shaA1
    

    要仔细检查一切是否顺利,您可以执行git diff shaA3 - 应为空,git diff develop - 应包含所有所需的 B 更改。

    附:您当然可以使用cherry-pick或revert of reverts将b更改重播为branchB,而不是rebase交互,例如继续开发时:

     git checkout -b branchB
     git revert <revert of shaB1>
     git revert <revert of shaB2>
    

    会给你:

     #revert of revert of shaB2 = shaB2' <-- featureB, HEAD
     #revert of revert of shaB1 = shaB1'
     #revert of shaB1 <-- develop
     #revert of shaB2
     #shaA3
     #shaB2
     #shaA2
     #shaB1
     #shaA1
    

    【讨论】:

    • 感谢您的详细解答!看来您也可以不使用双重反转 - 不过请参阅我的答案 stackoverflow.com/a/29628784/21499 。我想这在历史上看起来更好。
    【解决方案3】:

    到目前为止,如果您可以管理它,最简洁的方法就是编写正确的历史记录并切换参考。调用你要拆分的历史库X

    git checkout -b new-develop X
    git cherry-pick [all the feature_A commits]
    # repeat the cherry-pick as needed or convenient if there's too many 
    git checkout -b new-featureB X
    git cherry-pick [all the feature_B commits]
    # ...
    

    然后用git branch -m 交换名称,强制推送,并让每个人根据需要重新获取和重新定位任何未发布的作品。

    所有其他选择都会给你留下一段非常混乱的历史,如果完全可以避免的话,没有理由把它强加给所有后代。 不要如果出于任何原因沟通出现问题,请避免使用它。

    如果你真的做不到,请查看@MykolaGurov's nicely detailed answer


    (branchcheckout -b...)

    【讨论】:

      【解决方案4】:

      如果您想避免修改分支develop 的已发布历史记录,如@thill's answer,同时又想避免恢复已恢复的提交,如@Mykola Gorov's answer,也可以

      1. develop 创建分支featureB
      2. 将功能B 的提交恢复到分支develop。在单个提交 revert B 中执行此操作可能是明智的,因为这是历史上的一项操作。
      3. 使用策略ours 将分支develop 合并到featureB。这不会更改分支 featureB 中的任何文件,但会将从 2. 恢复的提交标记为已合并到 featureB。因此,如果您稍后将功能分支 featureB 合并回 develop,结果将不再包含提交 revert B

      featureB 合并回develop 时,您可能希望将featureB 作为提交的第一个父级。 (例如,您将develop 合并到featureB 中,然后将develop 设置为featureB,而不是相反。)我想这样恢复不会再混淆责备等了。 (?)

      【讨论】:

        猜你喜欢
        • 2014-07-01
        • 2017-07-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-04
        • 1970-01-01
        相关资源
        最近更新 更多