如何在 git 的 master 分支上首次提交之前移动后来创建的分支?

How to move later created branch before first commit on master branch in git?

我有我的主分支 master 和一个分支 originalCodeoriginalCode 分支的父级是 master:

                  F  originalCode
                 / 
A - B - C - D - E  master

现在我想在提交 A 之前移动带有提交 ForiginalCode 分支。 我已经尝试过变基和合并,但我无法让它工作,而且我找不到与此相关的类似问题。

目标是拥有共同的历史记录,以准确了解对原始代码(某些脚本)进行了哪些更改。当我开始checkin时,我已经开始使用外部修改版本了。

您执行以下操作:

创建一个包含原始代码库的新根提交:

git checkout originalCode
git checkout --orphan originalCode2
git commit -m "Original code of project foo"

现在我们必须将通向 master 的历史移植到这个新根之上。为此,我们将提交 A 移植到 originalCode2:

之上
echo $(git rev-parse A originalCode2) >> .git/info/grafts

然后重写历史以使新的父母身份永久化:

git filter-branch master

现在您有了预期的历史记录。请注意,此 重写历史记录 并且所有关于已发布的重写历史记录的警告均适用。

最后要把.git/info/grafts最后一行去掉(上面步骤写的)。它很可能是唯一的一行,那么你可以删除 .git/info/grafts.

可能可以使用 git rebase --root originalCode2 master 或涉及 --root 的一些变体而不是 filter-branch,但我没有使用此 rebase 变体的经验。

我会这样做:

  1. 创建并切换到新分支 reordered,该分支稍后将包含重新排序的提交,以指向与 originalCode 相同的提交 (F) :

    $ git checkout -b reordered originalCode
    

    提交图现在看起来像这样:

                      F  originalCode, reordered
                     / 
    A - B - C - D - E  master
    

    这是为了 masteroriginalCode 保持不变。如果出现问题,您可以删除 reordered 并重新开始。

  2. 交互式变基 reordered,在 A:

    之前定位 F

    由于 A 是根提交,您需要指定 --root 选项。

    $ git rebase -i --root reordered
    

    这将打开一个包含如下内容的文本编辑器:

    pick d14a5dd A
    pick 57b6bd9 B
    pick de4e672 C
    pick 6fc8c1f D
    pick 453da48 E
    pick d2443c0 F
    

    剪切 F 行并将其粘贴到 A 行上方。然后保存退出编辑器继续。

    根据您提交的实际内容,您可能需要在变基期间解决合并冲突。

  3. rebase 完成后,提交图应如下所示:

                      F  originalCode
                     / 
    A - B - C - D - E  master
    
    F'- A'- B'- C'- D'- E'  reordered
    

    请注意,由于 --root 变基,有两个系列的提交没有共同的祖先。

  4. 放心,reorderedmaster在内容上没有区别。

    $ git diff reordered master
    

    这应该不会产生任何输出。

    (编辑:我怀疑您想要 master 的内容作为 "newest" 版本,而不是 originalCode 的内容,所以我更改了 diff 相应地。)

    如果有差异,可能是您在解决合并冲突时做错了。

    您还可以使用 gitk.

  5. 等图形存储库浏览器来检查单个提交
  6. 一旦您对 reordered 分支的状态感到满意,您可以删除 originalCodemaster,然后重命名 reorderedmaster,或者您可以移动 master 以指向与 reordered 相同的提交(E')并删除 originalCodereordered 分支.

    $ git checkout -B master reordered
    $ git branch -D reordered originalCode
    

    最终结果应该是这样的提交图:

    F'- A'- B'- C'- D'- E'  master
    

解决一些评论者提出的问题:

如果有其他人克隆了存储库并依赖于 master 分支,您不应该像上面的第 5 步那样删除或移动它。

相反(在第 4 步之后)我建议将新的 reordered 分支合并到 master 中,以提供导致当前状态的替代历史记录,但也保留原始历史记录:

$ git checkout master
$ git merge reordered
$ git branch -d reordered

结果:

    A - B - C - D - E - G  master
                      /
F'- A'- B'- C'- D'- E'