[英]GIT: Branched off feature branch instead of development branch
So normally when we have feature1, feature2, and feature3, they branch off of devel. 因此,通常当我们有feature1,feature2和Feature3时,它们会脱离devel。 I accidentally just continued branching rather than switching back to devel though so feature2 branches off of feature1 and feature3 branches off of feature 2.
我不小心只是继续分支而不是切换回devel,尽管如此,Feature2从Feature1分支出来,Feature3从Feature 2分支出来。
How can I fix this? 我怎样才能解决这个问题?
EDIT for pic: 编辑图片:
I would like this:
---------------
\
A - B - C - D - E
to become this:
---------------
\ \ \
A B-C D-E
As there is only one or two commits per branch, using cherry-pick will be enough (no need to rebase for one or two commits). 由于每个分支只有一两次提交,因此使用cherry-pick就足够了(无需为一两次提交重新设置基准)。
First backup your local repository (do no trust the internet!) 首先备份您的本地存储库(不信任互联网!)
Write down the hash of A, B, C, D and E. Then: 写下A,B,C,D和E的哈希。然后:
Just do: 做就是了:
# 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
For completeness, here's how to use git rebase
(with optional --onto
) to move these commits. 为了完整
--onto
,这是使用git rebase
(带有可选的--onto
)移动这些提交的方法。 First, let's update the "current" drawing to add some specific labels and commits. 首先,让我们更新“当前”图形以添加一些特定的标签和提交。 For ease of rebasing and yet generality, I'll assume that
feature1
connects behind the tip of devel
, and that you'd like to move the new branches to the tip (the commit marked with *
). 为了便于重新
feature1
并保持通用性,我将假设feature1
连接在devel
尖端的后面,并且您想将新分支移动到尖端(用*
标记的提交)。
If there are no extra commits (so that *
connects directly to A
, etc) this all still works. 如果没有多余的提交(因此
*
直接连接到A
,等等),那么所有这些仍然有效。
If there are extra commits but you want to keep the feature
s back from the tip, the --onto
destination should be devel~2
in this example. 如果有额外的提交,但你要保持
feature
从尖端的背部,在--onto
目的地应为devel~2
在这个例子。
Now: 现在:
...-o--o--* <-- devel
\
A <-- feature1
\
B--C <-- feature2
\
D--E <-- feature3
Step 1, rebase feature3
interactively onto devel
. 第1步,
feature3
交互方式将feature3
devel
。 What this will do is create a text file with a bunch of pick
commands, each of which will do a git cherry-pick
. 这样做是使用一堆
pick
命令创建一个文本文件,每个命令都会执行git cherry-pick
。 You want to pick commits D
and E
. 您要选择提交
D
和E
Tell rebase that the "upstream" (poor name) is devel
, and that you want it to start the whole operation by doing git checkout feature3
: 告诉rebase“上游”(名字不好)是
devel
,并且您希望它通过执行git checkout feature3
来启动整个操作:
$ git rebase -i devel feature3
Here, rebase will find all commits selected by devel..feature3
(this is A
through E
inclusive, but not either of the two extra commits already on devel
), and will choose as its --onto
target, devel
. 在这里,变基会发现所有提交选定
devel..feature3
(这是A
通过E
包容性,而不是两个额外提交已经在任devel
),并且将选择作为其--onto
目标, devel
。 Then you end up in the editor, where you can delete all but the last two commits ( D
and E
). 然后,您进入编辑器,在其中可以删除除最后两个提交(
D
和E
)以外的所有提交。 Rebase will then: 重新设定基准将:
devel
, on a new unnamed branch (detached HEAD mode) devel
的尖端(分离的HEAD模式) D
, adding it to the unnamed branch D
,将其添加到未命名分支 E
, adding it to the unnamed branch E
,将其添加到未命名分支 git reset
to make feature3
point to the latest commit. git reset
的管道等效功能,使feature3
指向最新提交。 Now the tree looks like this: 现在树看起来像这样:
D'-E' <-- feature3
/
...-o--o--* <-- devel
\
A <-- feature1
\
B--C <-- feature2
\
D--E [abandoned, except for reflogs]
(If you add --onto devel~2
to the original git rebase -i
, it will grow the D'-E'
chain from the commit at devel~2
, which is the leftmost o
node. You still need to specify the upstream, which you can list as either devel
or devel~2
: it won't matter in this case.) (如果您添加
--onto devel~2
到原来的git rebase -i
,它会生长的D'-E'
从提交链devel~2
,这是最左边o
节点。您仍然需要指定上游,您可以将其列为devel
或devel~2
:在这种情况下无关紧要。)
Now you can git rebase -i devel feature2
. 现在您可以
git rebase -i devel feature2
。 This works in the same way: check out branch feature2
, find commits in devel..feature2
(which is A
through C
this time), and open an editor session to let you modify the set of cherry-pick
commands that git will run. 这的工作方式相同:检出分支
feature2
,在devel..feature2
查找提交(这次是A
到C
),然后打开一个编辑器会话,让您修改git将运行的cherry-pick
命令集。 This time you need only delete one line (for commit A
). 这次您只需要删除一行(对于提交
A
)。 Git then starts a new detached-HEAD anonymous branch at commit *
again, grows it with cherry picks of B
and C
, and then moves the feature2
branch: 然后,Git在commit
*
再次启动一个新的HEAD匿名分离分支,并使用B
和C
挑选出它,然后移动feature2
分支:
D'-E' <-- feature3
/
...-o--o--* <-- devel
| \
\ B'-C' <-- feature2
|
A <-- feature1
\
B--C [abandoned]
Last, you can rebase feature1
. 最后,您可以为
feature1
。 Here you don't need to bother with interaction, as commit A
is the only one you want to copy and the only one git rebase
will choose. 在这里,您无需打扰,因为提交
A
是您要复制的唯一提交,并且将选择唯一的git rebase
。
The result is the same as with git cherry-pick
. 结果与
git cherry-pick
。 You need somewhat fewer git commands, but a bit more editing for the interactive "pick" sequences. 您需要的git命令要少一些,但是对于交互式“选择”序列需要更多的编辑。
Which way is "better"? 哪种方法更好? Neither, really.
两者都不是。 Renaming the old branches and then deleting them will toss their reflogs, which might be a feature since it enables the original
A
through E
commits to get garbage-collected sooner, or might be a drawback in case you want to look at them again. 重命名旧分支然后删除它们将刷新其reflog,这可能是一个功能,因为它使原始的
A
到E
提交能够更快地被垃圾回收,或者如果您想再次查看它们,则可能是一个缺点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.