使用合并提交将提交移动到新分支

时间:2021-04-11 23:30:30

标签: git git-branch rebase branching-and-merging

我有这样的线性历史

----a--b--c--d--e--f----    main

我想将一系列提交移动到一个新分支,并在旧分支中创建一个合并提交,像这样创建一个非线性历史

----a-------x--d'--e'--f'-- main
      \    /
       b--c

其中 x 是新的合并提交。

我该怎么做?

请注意,移动的提交不是最近的提交(请参阅 here)。

3 个答案:

答案 0 :(得分:2)

您可以很容易地做到这一点,但您将重写 main 的历史记录,这是不推荐的,可能必须强制推送到远程。

无论如何,这或多或少是您的初始情况(我使用的是 master 而不是 main,我只使用了 e):

$ git log --oneline --graph --all
* d5de97b (HEAD -> master) e
* 97f47d1 d
* 7c33da9 c
* 295b3c7 b
* 18622aa a

好的,我建议将 bc 转换为分支 feature 上的提交,该分支将在 master 之前合并到 d。准备好? (其中一些步骤,例如某些 checkout 移动,可能是不必要的,但我并没有停下来担心这一点。)

$ git branch holdmyplace        # prevent losing any commits
$ git branch feature 7c33da9    # call `c` by a branch name `feature`
$ git reset --hard 18622        # slide `master` all the way back to `a`...
$ git merge --no-ff feature     # ...and merge `feature` with a merge commit!
$ git checkout holdmyplace      # okay, now return to the placeholder branch...
$ git rebase --onto master feature holdmyplace 
                                # ...and append it to `master`
$ git checkout master           # finally, return to master...
$ git reset --hard holdmyplace  # ...and slide it back up to the end!
$ git branch -d holdmyplace     # we no longer need the placeholder branch

现在我们有:

$ git log --oneline --graph --all
* 0d58dd1 (HEAD -> master) e
* 7831073 d
*   2bd7688 Merge branch 'feature'
|\  
| * 7c33da9 (feature) c
| * 295b3c7 b
|/  
* 18622aa a

这就是你所说的你想要的。

答案 1 :(得分:2)

我会这样做:

git checkout a
git merge --no-ff c
git cherry-pick c..main
# at this point you are on a revision that has a history like what you asked for
# now it's time to move main
git branch -f main
git checkout main

如果您将该分支推送到其他存储库,您将不得不强制推送新的,因为您重写了它的历史记录。 (为了以防万一,您重写历史还有其他考虑)。

答案 2 :(得分:1)

让我们从创建一些指针开始,让事情变得更简单。

git branch base <a>
git branch feat <c>

图表看起来像这样。

----a--b--c--d--e--f----    main
    ^     ^
  base  feat

现在我们将 feat 合并到 base,创建合并提交。

git switch base
git merge --no-ff feat

图表现在看起来像这样。

----a------x          base
     \    /
      b--c--d--e--f-- main

现在我们将 main 变基到 base 上,将其移到新的合并提交上。

git switch main
git rebase --onto base feat

最后,我们可以清理不再需要的指针。

git branch -d base
git branch -d feat

我们最终得到的图表如下所示。

----a------x--d'--e'--f'-- main
     \    /
      b--c