GIT:分支功能分支而不是开发分支

时间:2014-07-30 21:58:25

标签: git

通常当我们有feature1,feature2和feature3时,它们会从devel开始分支。 我不小心只是继续分支而不是切换回开发,尽管feature2从feature1和feature3分支离开了功能2。

我该如何解决这个问题?

编辑图片:

I would like this:
---------------
  \
    A - B - C - D - E

to become this:
---------------
  \   \     \
   A   B-C   D-E

2 个答案:

答案 0 :(得分:2)

由于每个分支只有一个或两个提交,使用cherry-pick就足够了(不需要为一个或两个提交重新设置)。

首先备份您的本地存储库(不要相信互联网!)

记下A,B,C,D和E的哈希值。然后:

只是做:

# Switch to devel
git checkout devel
# Rename branches into temporary branch names
git branch -m feature1 tmp1 && git branch -m feature2 tmp2
                            && git branch -m feature3 tmp3
# Create feature1 branch and cherry-pick the required commit
git checkout -b feature1 && git cherry-pick A
# Switch to devel
git checkout devel
# Create feature2 branch and cherry-pick the required commits
git checkout -b feature2 && git cherry-pick B C
# Switch to devel
git checkout devel
# Create feature3 branch and cherry-pick the required commits
git checkout -b feature3 && git cherry-pick D E
# Switch to devel
git checkout devel
# Delete temporary branches
git branch -D tmp1 tmp2 tmp3

答案 1 :(得分:2)

为了完整性,这里是如何使用git rebase(带有可选的--onto)来移动这些提交。首先,让我们更新“当前”绘图以添加一些特定的标签和提交。为了便于重新定义和普遍性,我假设feature1连接在devel的提示后面,并且您希望将新分支移动到提示(标记为{{的提交) 1}})。

如果没有额外的提交(以便*直接连接到*等),这一切仍然有效。

如果有额外的提交,但您希望从提示中恢复A,则此示例中feature目的地应为--onto

现在:

devel~2

第1步,将...-o--o--* <-- devel \ A <-- feature1 \ B--C <-- feature2 \ D--E <-- feature3 交互式地转移到feature3。这样做会创建一个带有一堆devel命令的文本文件,每个命令都会执行pick。您想要选择提交git cherry-pickD。告诉rebase“上游”(不良名称)是E,并且您希望它通过执行devel来启动整个操作:

git checkout feature3

此处,rebase会找到$ git rebase -i devel feature3 选择的所有提交(devel..feature3A包括E,但devel已经提交的两个额外提交中的任何一个都没有,并将选择--onto目标devel。然后你最终进入编辑器,在那里你可以删除除最后两次提交之外的所有提交(DE)。然后Rebase将:

  • 移动到分支devel的尖端,在新的未命名分支上(分离的HEAD模式)
  • cherry-pick commit D,将其添加到未命名的分支
  • cherry-pick commit E,将其添加到未命名的分支
  • 最后,使用git reset的管道等效项使feature3指向最新的提交。

现在树看起来像这样:

            D'-E'   <-- feature3
           /
...-o--o--*         <-- devel
     \
      A             <-- feature1
       \
        B--C        <-- feature2
            \
             D--E   [abandoned, except for reflogs]

(如果您将--onto devel~2添加到原始git rebase -i,则会在D'-E'处提交devel~2链,这是最左边的o您仍然需要指定上游,您可以将其列为develdevel~2:在这种情况下无关紧要。)

现在你可以git rebase -i devel feature2。这可以用同样的方式:签出分支feature2,在devel..feature2(这次是AC)中找到提交,并打开一个编辑器会话让你修改git将运行的cherry-pick命令集。这次您只需删除一行(对于提交A)。然后,Git再次在提交*处启动一个新的分离-HEAD匿名分支,使用BC的樱桃选择增长它,然后移动feature2分支:

            D'-E'   <-- feature3
           /
...-o--o--*         <-- devel
    |      \
     \      B'-C'   <-- feature2
      |
      A             <-- feature1
       \
        B--C        [abandoned]

最后,您可以重新定位feature1。在这里,您无需为交互烦恼,因为提交A是您唯一要复制的内容,而git rebase只会选择一个。{/ p>

结果与git cherry-pick相同。您需要更少的git命令,但需要对交互式“选择”序列进行更多编辑。

哪种方式“更好”?也不是,真的。重命名旧分支然后删除它们将丢弃它们的reflog,这可能是一个功能,因为它使原始AE提交能够更快地收集垃圾,或者可能是一个缺点,如果你我想再看看他们。