如何将某个功能的某些提交从现有分支移动到功能分支中,并有效地将其从当前分支中删除 - 就好像该功能是在单独的功能分支中开发的一样?
背景:分支develop
包含对两个特征A(例如,50个提交)和B(10个提交)的混合提交,因为它们最初应该在同一个版本中。现在我们推迟了功能B.因此,我们希望在develop
分支中只有一个功能A,以及一个包含A或A和B提交的新featureB
分支,这样如果我们合并两个分支,我们得到develop
分支的当前位置。
这样做的一种方法是从featureB
分支的当前位置创建develop
分支,然后反向应用从A到develop
的提交。但是,新develop
和featureB
的合并将只是A。
另一种方法是将当前develop
重命名为featureB
,并将A的所有提交选择到新的develop
分支中。但这会有效地修改develop
的历史,这很麻烦。
有什么更好的方法呢?
答案 0 :(得分:2)
如果您的develop
分支已发布且您不想重写其历史记录(这是最简单的方法),那么您确实可以在develop
中还原您的更改,开始新的featureB
在B
之上更改了develop
重新定位的 #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
并重新播放已恢复的提交:
shaB1
注释掉除属于功能B(在我们的例子中为shaB2
和 #shaB2' <-- featureB, HEAD
#shaB1'
#revert of shaB1 <-- develop
#revert of shaB2
#shaA3
#shaB2
#shaA2
#shaB1
#shaA1
)的提交之外的所有提交并完成rebase。此时你应该有历史:
git diff shaA3
要仔细检查一切进展顺利,您可以执行git diff develop
- 应为空,branchB
- 应包含所有所需的B更改。
P.S。您当然可以使用cherry-pick或revert of reverts将b更改重播为 git checkout -b branchB
git revert <revert of shaB1>
git revert <revert of shaB2>
,而不是使用rebase交互,例如留在开发时:
#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
会给你:
{{1}}
答案 1 :(得分:2)
到目前为止,最简洁的方法是,如果你可以管理它,就是只写正确的历史记录并切换引用。调用要拆分的历史记录的基础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。
(branch
→checkout -b
......)
答案 2 :(得分:0)
从当前的开发状态创建分支featureB
。提交代码以分支develop
以进行featureA的任何进一步开发。提交代码以分支featureB
以开发featureB。定期将分支featureB
重新分支到分支develop
,以便它具有为开发featureA而添加的更改。
答案 3 :(得分:0)
如果您想避免修改分支develop
的已发布历史记录(如@thill's answer中所述),并且还希望避免还原已恢复的提交,例如@Mykola Gorov's answer,您还可以< / p>
featureB
develop
B
的提交还原为分支develop
。在单个提交revert B
中执行此操作可能是明智的,因为这是历史记录中的一个操作。develop
将分支featureB
合并到ours
。这不会更改分支featureB
中的任何文件,但会将已恢复的提交标记为2.已经合并到featureB
中。因此,如果您稍后将功能分支featureB
合并回develop
,结果将不包含提交revert B
。将featureB
合并回develop
时,您可能希望将featureB
作为提交的第一个父级。 (例如,您将develop
合并到featureB
,然后将develop
设置为featureB
,而不是相反。)我想这样的回归不会让人感到困惑等等。 (?)