9

假设我已经开发了一项功能,branch1并使用 GitHub 拉取请求将其发送给代码审查。在审核期间,我在branch2.

 branch2                   -> D --> E --> F
                          /    
 branch1  -> A --> B --> C
         /
 master M

我的审稿人喜欢我的工作!无需更改。branch1我合并了使用 GitHub 的Squash 和合并功能的拉取请求。

运行并删除后git pullmasterbranch1遇到了这种情况:

 branch2  -> A --> B --> C -> D --> E --> F
         /
 master M --> S

要为 发送一个看起来干净的 PR branch2,我想让我的提交树看起来像这样:

 branch2        -> D' --> E' --> F'
               /
 master M --> S

S(由“压缩和合并”为 生成的提交)处的代码branch1与 相同C,因为它只是A --> B --> C.

实现此目的的一种方法是在以下位置运行这样的序列branch2

git reset --hard S
git cherry-pick D E F

但是以这种方式列出所有提交变得乏味,这真的感觉像是一个变基。当然,因为 commits并且需要消失,git rebase master所以不会工作。ABC

将分支从其祖先提交之一的压缩版本中变基的最佳方法是什么?

4

1 回答 1

19

git rebase与 一起使用--onto。这仍然有点棘手,所以为了简单起见,您需要更早地做一件不同的事情。

顺便说一句,我认为最好用右侧的​​分支名称绘制这些图,指向一个特定的提交。这是因为在 Git 中,提交在多个分支上,而分支名称确实只是指向一个特定的提交。反转内部箭头(因为 Git 确实以这种方式存储它们)或仅使用连接线以免暗示错误的方向也是值得的。

因此:

          D--E--F   <-- branch2
         /    
  A--B--C       <-- branch1
 /
M          <-- master

提交AthroughC确实在branch1 and branch2上,而提交DthroughFbranch2。(提交M和更早在所有三个分支上。)

什么是选择当前分支可访问的所有1 个提交,但不能从参数访问,然后复制它们(使用或等效),以便它们在提交之后立即出现。git rebase upstreamupstreamgit cherry-pickupstream

在 squash-"merge" (不是真正的合并)之后,如果你运行git fetch然后快进你的master,你有你画的一样的东西,但我留下branch1并将标签放在左边并在origin/master这里添加:

          D--E--F   <-- branch2
         /    
  A--B--C       <-- branch1
 /
M--S       <-- master, origin/master

(或者,如果您还没有快进master,只需origin/master指向 commit S)。

您现在想告诉 GitD-E-F使用cherry-pick 进行复制,然后移动标签branch2以指向最后复制的提交。您不想复制A-B-C它们,因为它们已合并到S. 您希望副本继续Sorigin/master现在指向它 - 无论您是否已更新master。因此:

git checkout branch2
git rebase --onto origin/master branch1

upstream是 now而branch1不是master,但是--onto告诉 Git 在哪里放置副本:branch1仅用于分隔不复制的内容。所以现在 Git 复制D-E-F和更改branch2指向那里:

          D--E--F   [abandoned]
         /    
  A--B--C       <-- branch1
 /
M--S       <-- master?, origin/master
    \
     D'-E'-F'   <-- branch2

现在您可以删除名称branch1。(现在你可以快进master,如果你还没有——你什么时候做并不重要,事实上你根本不需要你自己master的。)


1git patch-id更准确地说,rebase使用对称差异选择 (a) 不合并提交和 (b)与排除集中的某些提交不同的提交。也就是说upstream..HEAD,Git 实际上运行git rev-listupstream...HEAD,with--cherry-mark或类似的,而不是 ,以挑选提交。根据特定类型的变基,实现会略有不同。

于 2017-01-25T19:03:19.980 回答