将初始提交从主控移到Git中的另一个分支 [英] Move initial commits off master to another branch in Git
问题描述
我试图迁移到GitFlow工作流程,并且我想重写存储库的历史记录,以使其全部符合新的存储库。
在看起来像这样的一刻:
Master:A - B - C - D - E - F - - - - - - - - L
\ /
发行:\ J - K
\ / \
开发:G - H - IM
我希望它看起来像这样:
$ b $ \\ / \
开发:B - C - D - E - F - G - H - IM
我试过在这里搜索答案,并且找到了 answer ,但它似乎只在你创建新的时才起作用分支,而不是使用已经存在的分支。
非常感谢您提前。 G
, H
和 I
是只有开发
分支的祖先。但是,在您目前的回购状态下,它们属于所有三个分行( master ,
development
)的祖先,和 release
)。
认为这三个提交( G
, H
和 I
)在某种程度上更多地与<$ c $相关c> development 分支比 master
或 release
分支不再有任何意义,你的repo不记得过去分支引用的地方(尽管这些信息本地存储在称为 reflog 的东西)。您的Git仓库只知道分支引用指向目前的位置。
因此,当您绘制图形来描述您的仓库所处的状态时,如果某个分支指向一个提交,使用相应的分支名称标记提交本身更有意义。我在下面的所有图表上都这么做了。
原始状态
A - B - C - D - E - F - - - - - - - - L [master]
\ /
G - H - I - J - K [发行]
\
M [开发]
所需状态
A - - - - - - - - - - - - - - - - - - L'[master]
\ /
B - C - D - E - F - G - H - I - J - K [发行]
\
M [开发]
要在这种状态下结束,您应该采取以下三个步骤。
h2>
1 - 查看您的 master
分支
git checkout master
master
分支 git checkout master
at HEAD
指向 master
:
A - B - C - D - E - F - - - - - - - - - L [HEAD - > master]
\ /
G - H - I - J - K [发布]
\
M [开发]
2 - 对 master
进行硬重置以提交A
git reset --hard< commit_ID_of_A>
由于 L
在您的回购中参考,它从历史图表中消失,您只需留下
A [HEAD - > ; master]
\
B - C - D - E - F - G - H - I - J - K [发布]
\
M [开发]
3 - 将 release
真正合并到 master
在这个阶段,如果您只是运行
git合并版本
因为 master
是 release 的提示的祖先,则会发生快速合并,并且您最终会
A - B - C - D - E - F - G - H - I - J - K [HEAD - > master,release]
\
M [开发]
你想要什么。因此,执行真正的合并需要 - no-ff
选项,在这里:
git merge --no-ff release
在这最后一条命令后,您的回购应该处于期望的状态:
A - - - - - - - - - - - - - - - - - - - - L'[HEAD - > master]
\ /
B - C - D - E - F - G - H - I - J - K [发布]
\
M [开发]
请注意,我昵称新提交 L'
而不是 L
,因为这两个提交有不同的父项: L
的父项为 F
和 K
,而新提交的父项 L'
是 A
和 K
。
I'm trying to migrate to the GitFlow workflow, and I want rewrite the history of the repository so that all of it complies with the new repository.
At the moment it looks like this:
Master: A - B - C - D - E - F - - - - - - - - - L
\ /
Release: \ J - K
\ / \
Development: G - H - I M
I would like it to look like this:
Master: A - - - - - - - - - - - - - - - - - - - L
\ /
Release: \ J - K
\ / \
Development: B - C - D - E - F - G - H - I M
I've tried searching for an answer here, and I found an answer, but it only seems to work if you are creating the new branch, rather than using an already existing branch.
Many thanks in advance.
In Git, as pointed out by larsmans in his comment, a branch is simply a pointer/reference to a particular commit. Labelling codelines with branch names as you did on the left-hand side of your graph can be confusing.
For instance, it may have been true that, in the past, commits G
, H
, and I
were part of the ancestry of the development
branch only. However, in the current state of your repo, they belong to the ancestries of all three branches (master
, development
, and release
).
To think that those three commits (G
, H
, and I
) are, in some way, still more related to the development
branch than to master
or release
no longer makes any sense, simply because your repo doesn't remember where branch references pointed to in the past (although that information is stored locally in something called the reflog). Your Git repo only knows where the branch references are pointing to at the present.
Therefore, when you draw a graph to describe what state your repo is in, if a branch points to a commit, it makes more sense to label the commit itself with the corresponding branch name. I did so on all my graphs below.
Original state
A - B - C - D - E - F - - - - - - - - - L [master]
\ /
G - H - I - J - K [release]
\
M [development]
Desired state
A - - - - - - - - - - - - - - - - - - - L' [master]
\ /
B - C - D - E - F - G - H - I - J - K [release]
\
M [development]
To end up in this state, you should take the following three steps.
Procedure
1 - Check out your master
branch
git checkout master
After that, HEAD
points to master
:
A - B - C - D - E - F - - - - - - - - - L [HEAD -> master]
\ /
G - H - I - J - K [release]
\
M [development]
2 - Do a hard reset of master
to commit A
git reset --hard <commit_ID_of_A>
Because L
is no longer reachable by any reference in your repo, it "vanishes" from the history graph and, you're simply left with
A [HEAD -> master]
\
B - C - D - E - F - G - H - I - J - K [release]
\
M [development]
3 - Do a true merge of release
into master
At this stage, if you were to simply run
git merge release
because the tip of master
is an ancestor of the tip of release
, a fast-forward merge would take place, and you would simply end up with
A - B - C - D - E - F - G - H - I - J - K [HEAD -> master,release]
\
M [development]
which isn't what you want. Therefore, the --no-ff
option is required to enforce a true merge, here:
git merge --no-ff release
After this last command, your repo should be in the desired state:
A - - - - - - - - - - - - - - - - - - - L' [HEAD -> master]
\ /
B - C - D - E - F - G - H - I - J - K [release]
\
M [development]
Note that I nicknamed the new commit L'
instead of L
because those two commits have different parents: the parents of L
are F
and K
, whereas the parents of the new commit, L'
, are A
and K
.
这篇关于将初始提交从主控移到Git中的另一个分支的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!