将初始提交从 master 移到 Git 中的另一个分支

Posted

技术标签:

【中文标题】将初始提交从 master 移到 Git 中的另一个分支【英文标题】:Move initial commits off master to another branch in Git 【发布时间】:2014-10-18 17:38:32 【问题描述】:

我正在尝试迁移到 GitFlow 工作流,并且我想重写存储库的历史记录,以便所有内容都符合新存储库。

目前看起来是这样的:

Master: A - B - C - D - E - F - - - - - - - - - L
                             \                 /
Release:                      \           J - K
                               \         /     \
Development:                    G - H - I       M

我希望它看起来像这样:

Master:  A - - - - - - - - - - - - - - - - - - - L
          \                                     /
Release:   \                               J - K
            \                             /     \
Development: B - C - D - E - F - G - H - I       M

我尝试在这里寻找答案,并找到了answer,但它似乎只在您创建新分支而不是使用已经存在的分支时才有效。

非常感谢。

【问题讨论】:

假设左边是较早的,最右边是当前的,这两张图代表相同的历史。提交不记录分支;分支只是指向单个提交的指针。 看看cherry-pick。 ***.com/questions/9339429/… 【参考方案1】:

正如 larsmans 在his comment 中指出的那样,在 Git 中,分支只是对特定提交的指针/引用。像您在图表左侧所做的那样使用分支名称标记代码行可能会令人困惑。

例如,在过去,提交 GHI 可能确实是 development 分支的祖先的一部分。但是,在您的 repo 的当前状态下,它们属于所有三个分支(masterdevelopmentrelease)的祖先。

认为这三个提交(GHI)在某种程度上与development 分支的关系比与masterrelease 的关系更密切。任何意义,仅仅是因为您的 repo 不记得过去分支引用指向的位置(尽管该信息存储在本地称为 reflog 的东西中)。您的 Git 存储库目前只知道分支引用指向的位置。

因此,当您绘制图表来描述您的存储库处于什么状态时,如果一个分支指向一个提交,则使用相应的分支名称标记该提交本身更有意义。我在下面的所有图表中都这样做了。

原始状态

A - B - C - D - E - F - - - - - - - - - L [master]
                     \                 /
                      G - H - I - J - K [release]
                                       \
                                        M [development]

想要的状态

A - - - - - - - - - - - - - - - - - - - L' [master]
 \                                     /
  B - C - D - E - F - G - H - I - J - K [release]
                                       \
                                        M [development]

要达到这种状态,您应该采取以下三个步骤。

程序

1 - 查看您的 master 分支

git checkout master

之后,HEAD 指向master

A - B - C - D - E - F - - - - - - - - - L [HEAD -> master]
                     \                 /
                      G - H - I - J - K [release]
                                       \
                                        M [development]

2 - 硬重置master 以提交 A

git reset --hard <commit_ID_of_A>

因为L 不再可以通过您的存储库中的任何引用访问,所以它从历史图表中“消失”,您只剩下

A [HEAD -> master]
 \
  B - C - D - E - F - G - H - I - J - K [release]
                                       \
                                        M [development]

3 - 将release 真正合并到master

在这个阶段,如果你只是简单地运行

git merge release

因为master 的尖端是release 的尖端的祖先,所以会发生快进合并,您最终会得到

A - B - C - D - E - F - G - H - I - J - K [HEAD -> master,release]
                                         \
                                          M [development]

这不是你想要的。因此,需要--no-ff 选项来强制执行真正的合并,此处:

git merge --no-ff release

在最后一条命令之后,您的 repo 应该处于所需的状态:

A - - - - - - - - - - - - - - - - - - - L' [HEAD -> master]
 \                                     /
  B - C - D - E - F - G - H - I - J - K [release]
                                       \
                                        M [development]

请注意,我将新提交命名为 L' 而不是 L,因为这两个提交具有不同的父级:L 的父级是 FK,而新提交的父级是 @ 987654360@,分别是AK

【讨论】:

【参考方案2】:

这应该做你想做的,(虽然我不确定你的发布分支)

git checkout master
git reset --hard commit_A # the commit id for A

git merge --no-ff release

【讨论】:

最后一个命令应该是git merge --no-ff release,而不是git merge --no-ff commit_L;在my answer 中了解原因。 @ryenus 我应该删除我对你答案的任何引用,还是应该保持原样? @Jubobs,我想以供将来参考,您可以将其清理以进行澄清,因此有类似需求的人可以通过越来越清晰的阅读来解决他们的问题,顺便说一句,理性正在进行硬重置然后是 no-ff 合并,正如您用这些图表很好地说明的那样,干得好!

以上是关于将初始提交从 master 移到 Git 中的另一个分支的主要内容,如果未能解决你的问题,请参考以下文章

Git克隆一个分支,而不是master

git将某分支的某次提交合并到另一分支

如何将当前分支与 Visual Studio 2019 中的另一个分支进行比较?

git提交本地master分支到远程main分支

如何将一个git的master分支提交添加到另一个git中?

Git提交代码到主分区