在GitHub“压缩并合并"后重新设置分支掌握 [英] Rebase branch after GitHub "Squash and merge" onto master

查看:45
本文介绍了在GitHub“压缩并合并"后重新设置分支掌握的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我已经在 branch1 上开发了一个功能,并使用Gi​​tHub Pull Request将其发送出去以进行代码审查.在审核过程中,我在 branch2 上做了一些后续工作.

  branch2->D->E->F/分支1->A->B->C/硕士M 

我的评论者喜欢我的工作!无需更改.我使用GitHub的压缩并合并

,合并对 branch1 的提取请求功能.

master 上运行 git pull 并删除 branch1 后,我会遇到这种情况:

  branch2->A->B->C->D->E->F/大师M->小号 

要为 branch2 发送清晰的PR,我想让我的提交树看起来像这样:

  branch2->D'->E'->F'/大师M->小号 

S 处的代码(由"Squash and merge"为 branch1 生成的提交)与 C 相同,因为它只是 A->的压缩版本B->C .

一种实现此目的的方法是在 branch2 上运行这样的序列:

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

但是以这种方式列出所有提交会很乏味,而且确实像重新设置一样,使我们感到.当然, git rebase master 不起作用,因为 A B C 的提交需要消失.

从一个先祖提交的压缩版本中重新建立分支的最佳方法是什么?

解决方案

git rebase -onto 一起使用.这仍然有些棘手,因此为了简化起见,您将需要更早地做一件事.

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

因此:

  D--E--F<-分支2/A--B--C<-分支1/M<-硕士 

通过 C 提交 A 确实在 branch1 branch2 上,而在 branch2 上,通过 D F 的提交仅是 .(提交 M 和更早版本在所有三个分支上.)

git rebase 上游 所做的是选择全部 1 提交可从当前分支获取,但是无法从 upstream 参数到达,然后将其复制(使用 git cherry-pick 或同等功能),以便它们正确显示在 上游 提交之后.

壁球合并"(不是真正的合并)之后,如果您运行 git fetch ,然后快进您的 master ,您将拥有相同的东西画了,但是我留了 branch1 并将标签放在左侧,并在此处添加 origin/master :

  D--E--F<-分支2/A--B--C<-分支1/M--S<-母版,来源/母版 

(或者,如果您尚未快速转发 master ,则只有 origin/master 指向提交 S )./p>

您现在要告诉Git用cherry-pick复制 D-E-F ,然后将标签 branch2 指向最后复制的提交.您不想要复制 A-B-C ,因为它们已合并到 S 中.您希望副本位于 S 之后, origin/master 现在指向该副本,无论您是否已更新 master .因此:

  git checkout branch2git rebase-到origin/master branch1 

上游 现在是 branch1 ,而不是 master ,但是-onto 告诉Git将副本放置在哪里: branch1 仅用于界定不复制的 .因此,现在Git复制 D-E-F 并更改 branch2 指向此处:

  D--E--F [已放弃]/A--B--C<-分支1/M--S<-master ?,来源/master\D'-E'-F'<-分支2 

现在,您可以删除名称 branch1 .(现在,如果您还没有的话,您可以快速转发 master -何时执行该操作并不重要,实际上,您不需要自己的 master >).


1 更准确地说,rebase选择的提交是(a)不合并提交,并且(b)与某些提交中的 git patch-id 没有相同的 git patch-id 排除集,使用对称差.也就是说,Git实际上是在 上游上运行 git rev-list 而不是 上游 .. HEAD ... HEAD ,带有-cherry-mark 或类似名称,以选择提交.具体实现方式会有所不同,具体取决于重新设置的特定类型.

Let's say I've developed a feature on branch1 and sent it out for code review using a GitHub Pull Request. While it's being reviewed, I do some follow-on work on branch2.

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

My reviewer loves my work! No changes are required. I merge the pull request for branch1 using GitHub's Squash and merge feature.

After running git pull on master and deleting branch1, I'm left with this situation:

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

To send out a clean-looking PR for branch2, I'd like to get my commit tree looking like this:

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

The code at S (the commit generated by "Squash and merge" for branch1) is identical to C, since it's just the squashed version of A --> B --> C.

One way to achieve this would be to run a sequence like this on branch2:

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

But listing all the commits out this way gets tedious, and this really feels like a rebase. git rebase master won't work, of course, since commits A, B and C need to disappear.

What's the best way to rebase a branch off a squashed version of one of its ancestor commits?

解决方案

Use git rebase with --onto. This is still a bit tricky, so to make it easy you will want to do one thing different, earlier.

I think it's better, by the way, to draw these graphs with the branch names at the right side, pointing to one specific commit. This is because in Git, commits are on multiple branches, and branch names really do just point to one specific commit. It's also worth reversing the internal arrows (because Git really stores them that way) or just using connecting lines so as not to imply the wrong direction.

Hence:

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

Commits A through C really are on both branch1 and branch2, while commits D through F are only on branch2. (Commits M and earlier are on all three branches.)

What git rebase upstream does is select all1 commits reachable from the current branch, but not reachable from the upstream argument, then copy them (with git cherry-pick or equivalent) so that they come right after the upstream commit.

After the squash-"merge" (not really a merge), if you run git fetch and then fast-forward your master, you have the same thing you drew, but I leave branch1 in and put the labels on the left and add origin/master here:

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

(Or, if you don't fast-forward your master yet, only origin/master points to commit S).

You now want to tell Git to copy D-E-F with cherry-pick, then move the label branch2 to point to the last commit copied. You don't want to copy A-B-C as they're incorporated in S. You want the copies to go after S, to which origin/master now points—whether or not you've updated master. Hence:

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

The upstream is now branch1 instead of master, but the --onto tells Git where to place the copies: branch1 is only serving to delimit what not to copy. So now Git copies D-E-F and changes branch2 to point there:

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

and now you can delete the name branch1. (And now you can fast-forward master if you didn't yet—it does not really matter when you do it, and in fact you don't need your own master at all.)


1More precisely, rebase selects commits that are (a) not merge commits and (b) do not have the same git patch-id as some commit in the excluded set, using a symmetric difference. That is, rather than upstream..HEAD, Git actually runs git rev-list on upstream...HEAD, with --cherry-mark or similar, to pick out commits. The implementations vary slightly depending on the particular kind of rebase.

这篇关于在GitHub“压缩并合并"后重新设置分支掌握的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆