将单分支历史转换为许多较小的合并分支

时间:2018-02-20 06:47:37

标签: git rebase

问题

基本上,我养成了在开发过程中忘记分支的坏习惯。这让我留下了大量的提交内容,很难看出一个功能的开始和下一个功能的完成。

可能的解决方案

提交是按顺序我只是希望能够将单个主分支分成几个较小的功能分支,这些分支合并回主服务器。

当前的Git Repo:

-- A -- B -- C -- D -- E -- F -- G -- H => master

理想的Git Repo:

       B -- C => feature1 
     /       \
-- A --------- D -- E --------- H => master
                     \        /    
                       F -- G => feature2

我尝试过的事情

我已经阅读了其他一些类似的问题,但无法找到任何描述我的问题。我已经尝试了git rebase,但在这种情况下我不确定如何使用它,显然也可能需要--onto选项。

非常感谢任何帮助,因为这将使我的存储库更好看!

3 个答案:

答案 0 :(得分:4)

<强> LEGEND

  • A'表示来自提交A的补丁和消息,但是不同的提交哈希值,因为父级已更改。
  • branch-name*表示branch-name是当前结帐分支HEAD
-- A -- B -- C -- D -- E -- F -- G -- H => master


       B -- C -- D
     /            \
-- A ------------- M1 -- E ------------ M2 => master
                          \            /    
                            F -- G -- H
  

请注意,在您的图表中,您已将之前的非合并提交DH标记为最后的合并提交。我不相信这是你想要的,因为在这些提交中你通常会有不同的补丁和消息,你想要与合并提交分开。我在最终结果中分别添加了M1M2

你应该能够使用它:

git checkout master

git reset --hard A

-- A => master*
    \
      B -- C -- D -- E -- F -- G -- H

git checkout -b feature1 D(不需要,但可以作为标签)

                   => feature1
                 /                       
      B -- C -- D -- E -- F -- G -- H
     /
-- A => master*

git merge --no-ff feature1

                   => feature1
                 /                       
       B -- C -- D -- E -- F -- G -- H
     /            \
-- A ------------- M1 => master*

git cherry-pick E

                     => feature1
                   /                       
       B -- C --  D -- E -- F -- G -- H
     /             \
-- A -------------- M1 -- E' => master*

git checkout -b feature2 H

                     => feature1
                   /                       
       B -- C --  D -- E -- F -- G -- H => feature2*
     /             \
-- A -------------- M1 -- E' => master

git rebase --onto E master

  

重置为掌握,樱桃挑选从EH的所有内容,并使用rebase。

  

请注意,我们在此处选择E而不是E'因为--onto是关于正在重新分支的分支的历史记录,而不是我们在之上重新定位的内容。等效为git rebase --onto F^ master,其中F^表示Git中F的父级。

                     => feature1
                   /                       
       B -- C --  D -- E -- F -- G -- H
     /             \
-- A -------------- M1 -- E' => master
                            \
                             F' -- G' -- H' => feature2*

git checkout master

                     => feature1
                   /                       
       B -- C --  D -- E -- F -- G -- H
     /             \
-- A -------------- M1 -- E' => master*
                            \
                             F' -- G' -- H' => feature2

git merge --no-ff feature2

                   => feature1
                 /                       
      B -- C -- D -- E -- F -- G -- H
     /           \
-- A ------------ M1 -- E' --------------- M2 => master*
                          \               /    
                            F' -- G' -- H' => feature2

当没有任何名为ref的提交指向它们的提交时,最终结果将被丢弃:

      B -- C -- D => feature1
     /           \
-- A ------------ M1 -- E' --------------- M2 => master*
                          \               /    
                            F' -- G' -- H' => feature2

答案 1 :(得分:2)

我可能会遵循这种模式:

git checkout -b master_backup master

然后

git checkout master
git reset --hard [SHA position]

注意SHA位置只是您想要开始的提交哈希。

现在

git checkout -b feature-name master
git cherry-pick [sha-1]^...[sha-2]

注意,^符号使樱桃挑选范围包含[sha-1]

然后终于

git checkout master
git merge --no-ff feature

继续执行您要添加到主拓扑中的每个功能的最后4个步骤

答案 2 :(得分:0)

“理想”图形有点模棱两可,因为未明确指定合并提交。在图表中,DH似乎是合并提交,但它们不应该是。

以下是重建历史图表的一种可能解决方案:

git checkout master
git reset A --hard
git cherry-pick D
git branch feature1 C
git merge feature1 --no-ff
git cherry-pick E
git branch feature2
git cherry-pick H
git checkout feature2
git cherry-pick F G
git checkout master
git merge feature2 --no-ff

请注意,到目前为止feature1feature2是本地分支。如有必要,您可以将它们推送到遥控器。 Besieds,master已被重写。您可能需要强制推送它以在远程存储库中更新它。