通常当我们有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
答案 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-pick
和D
。告诉rebase“上游”(不良名称)是E
,并且您希望它通过执行devel
来启动整个操作:
git checkout feature3
此处,rebase会找到$ git rebase -i devel feature3
选择的所有提交(devel..feature3
到A
包括E
,但devel
已经提交的两个额外提交中的任何一个都没有,并将选择--onto
目标devel
。然后你最终进入编辑器,在那里你可以删除除最后两次提交之外的所有提交(D
和E
)。然后Rebase将:
devel
的尖端,在新的未命名分支上(分离的HEAD模式)D
,将其添加到未命名的分支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
您仍然需要指定上游,您可以将其列为devel
或devel~2
:在这种情况下无关紧要。)
现在你可以git rebase -i devel feature2
。这可以用同样的方式:签出分支feature2
,在devel..feature2
(这次是A
到C
)中找到提交,并打开一个编辑器会话让你修改git将运行的cherry-pick
命令集。这次您只需删除一行(对于提交A
)。然后,Git再次在提交*
处启动一个新的分离-HEAD匿名分支,使用B
和C
的樱桃选择增长它,然后移动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,这可能是一个功能,因为它使原始A
到E
提交能够更快地收集垃圾,或者可能是一个缺点,如果你我想再看看他们。