Git:事后如何分离出一个功能分支

时间:2015-03-30 16:00:14

标签: git feature-branch

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

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

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

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

有什么更好的方法呢?

4 个答案:

答案 0 :(得分:2)

如果您的develop分支已发布且您不想重写其历史记录(这是最简单的方法),那么您确实可以在develop中还原您的更改,开始新的featureBB之上更改了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


branchcheckout -b ......)

答案 2 :(得分:0)

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

答案 3 :(得分:0)

如果您想避免修改分支develop的已发布历史记录(如@thill's answer中所述),并且还希望避免还原已恢复的提交,例如@Mykola Gorov's answer,您还可以< / p>

  1. featureB
  2. 创建分支develop
  3. 将功能B的提交还原为分支develop。在单个提交revert B中执行此操作可能是明智的,因为这是历史记录中的一个操作。
  4. 使用策略develop将分支featureB合并到ours。这不会更改分支featureB中的任何文件,但会将已恢复的提交标记为2.已经合并到featureB中。因此,如果您稍后将功能分支featureB合并回develop,结果将包含提交revert B
  5. featureB合并回develop时,您可能希望将featureB作为提交的第一个父级。 (例如,您将develop合并到featureB,然后将develop设置为featureB,而不是相反。)我想这样的回归不会让人感到困惑等等。 (?)