2

考虑以下场景:

  1. 我从 master 签出了一个分支
  2. 我做了一些承诺
  3. 我合并了更新的主人
  4. 我做了更多的承诺
  5. 现在我想从第 4 点重新提交提交,以便第 2 点的提交不受影响。

所以如果我最初有:

     (1)         (2)
x--x--x--x--x--x--x         master
       \     \
        y--y--Y--y--y       dev
          (2)(3)   (4)

我想得到:

     (1)         (2)
x--x--x--x--x--x--x             master
       \           \
        y--y--------Y'--y'--y'  dev
          (2)      (5)     (5)

如果我只是这样做git rebase master,它将从 2 和 4 重新提交并从 3 删除合并。这不是我想要的。

还有一个选项要做git merge master,然后git rebase -i -p在从 3 合并提交之前并在从 3 合并之后移动最后一个合并,然后将其修复/压缩到从 3 的合并中。更新:它并不那么容易。Git 拒绝压缩两个合并。这个问题:git rebase interactive: squash merge commits together

4

3 回答 3

3

使用我和 VonC 的答案可以实现更自动化的解决方案:

git checkout -b tmp Y
git merge master 
git reset --soft HEAD^^ 
git rev-parse master > .git/MERGE_HEAD 
git commit -C Y
git checkout -
git rebase --onto tmp Y
git branch -d tmp

Y - 是要扩展的合并提交。

它的工作原理是这样的:

x--x--x--x--x--x--x         master
       \     \
        y--y--Y--y--y       dev

x--x--x--x--x--x--x         master
      |      \
       \      Y             tmp
        \    / \
         y--y   y--y        dev

x--x--x--x--x--x--x         master
      |      \     \
       \      Y-----Y'      tmp
        \    / \
         y--y   y--y        dev

x--x--x--x--x--x--x         master
      |            \
      |      -------Y'      tmp
       \    /
        y--y--Y--y--y       dev

x--x--x--x--x--x--x         master
      |            \
      |      -------Y'      tmp
       \    /        \
        y--y          y--y  dev

x--x--x--x--x--x--x           master
       \           \
        y--y--------Y'--y--y  dev
于 2013-09-25T23:17:34.100 回答
2

你从:

     (1)
x--x--x--x--x--x--x         master
       \     \
        y--y--Y--y--y       dev
          (2)(3)   (4)

做一个git rebase --onto

git branch dev1 Y^
git rebase --onto master Y^ dev

Y^引用合并提交的第一个父级Y:这里是 ' y',而不是 ' x'。
请参阅“祖先参考”:

第一个父级是您合并时所在的分支,第二个是您合并到的分支上的提交。

你最终会得到:

     (1)
x--x--x--x--x--x--x             master
       \           \
        y--y        Y'--y'--y'  dev
          (2)      (5)
        (dev1)

这会将您的初始dev分支一分为二,并仅dev在 顶部应用最后一次提交master,同时保持第一次dev提交不变,现在由分支引用dev1

您可以尝试:

git rebase -p --onto master `Y^` dev

看看这是否保留了y(即Y^)和新的 rebase之间的关系Y'。但我怀疑这是可能的。

-p是为--preserve-merge

于 2013-09-24T10:34:42.403 回答
1

我最终做了以下事情:

git rebase -i -p Y^

在文件中,在合并后的一行后添加以下行(大概在第一行之后):

exec sh -c "git merge master; git reset --soft HEAD^^; git rev-parse master > .git/MERGE_HEAD; git commit -C `git rev-parse HEAD`"
于 2013-09-25T22:56:54.173 回答