将初始提交从主控移到Git中的另一个分支 [英] Move initial commits off master to another branch in Git

查看:98
本文介绍了将初始提交从主控移到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 ,但它似乎只在你创建新的时才起作用分支,而不是使用已经存在的分支。



非常感谢您提前。 解决方案在Git中,正如larsmans在他的评论,分支仅仅是指向特定提交的指针/引用。例如,在过去,可能会出现这样的情况,例如,在您使用图表左侧的分支名称标记代码行时,提交 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 

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆