【问题标题】:How to rebase only the commits after the latest merge?如何在最新合并后仅重新提交提交?
【发布时间】:2013-09-29 11:38:47
【问题描述】:

考虑以下场景:

  1. 我从 master 签出了一个分支
  2. 我做了一些提交
  3. 我合并了更新的 master
  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 删除合并。这不是我想要的。

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

【问题讨论】:

  • 我的答案是正确的(除了我错误地将操作称为merge --onto:它是rebase --onto)。我已经更新了答案以更接近你想要的。
  • 你得到什么错误信息?
  • 拒绝压缩合并:987ab25995f24554cc7ce1451919327e09c5a18b
  • 好的。我想stackoverflow.com/q/1725708/6309 中提到的reset --soft 可以提供帮助。但不确定确切的顺序。

标签: git git-rebase git-pull


【解决方案1】:

使用我和 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

【讨论】:

    【解决方案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”。
    见“Ancestry References”:

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

    你最终会得到:

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

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

    你可以试试:

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

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

    -p 代表--preserve-merge

    【讨论】:

      【解决方案3】:

      我最终做了以下事情:

      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`"
      

      【讨论】:

      • 听起来不错。比我的回答更准确。 +1
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-14
      • 1970-01-01
      • 1970-01-01
      • 2021-07-22
      • 1970-01-01
      相关资源
      最近更新 更多