假设我已经开发了一个功能,branch1
并使用GitHub Pull Request将其发送出去进行代码审查.在进行审核时,我会做一些后续工作branch2
.
branch2 -> D --> E --> F / branch1 -> A --> B --> C / master M
我的评论家喜欢我的作品!无需更改.我合并了branch1
使用GitHub的Squash和合并功能的pull请求.
运行后git pull
的master
和删除branch1
,我留下了这样的情况:
branch2 -> A --> B --> C -> D --> E --> F / master M --> S
为了发送一个看起来干净的PR branch2
,我想让我的提交树看起来像这样:
branch2 -> D' --> E' --> F' / master M --> S
S
(由"Squash and merge"生成的提交的代码branch1
)是相同的C
,因为它只是被压缩的版本A --> B --> C
.
实现此目的的一种方法是运行如下序列branch2
:
git reset --hard S git cherry-pick D E F
但以这种方式列出所有提交变得乏味,这真的感觉像一个变种.git rebase master
将无法正常工作,当然,因为提交A
,B
并C
需要消失.
从一个祖先提交的压缩版本中修改分支的最佳方法是什么?
使用git rebase
带--onto
.这仍然有点棘手,所以为了简单起见,你会想要做一件与众不同的事情.
顺便说一句,我认为最好用右侧的分支名称绘制这些图形,指向一个特定的提交.这是因为在Git中,提交上多个分支,和分支的名字真的不只是指向一个具体的承诺.它也值得反转内部箭头(因为Git真的以这种方式存储它们)或者只是使用连接线而不是暗示错误的方向.
因此:
D--E--F <-- branch2 / A--B--C <-- branch1 / M <-- master
提交A
至C
真的是两个branch1
和 branch2
,同时承诺D
通过F
是唯一的branch2
.(提交M
和更早的是在所有三个分支.)
是什么做的是全选1款从到达当前分支,但是从不可达的参数,然后将它们复制(带或同等学历),使他们之后的来犯.git rebase upstream
upstream
git cherry-pick
upstream
壁球之后 - "合并"(不是真正的合并),如果你跑git fetch
,然后快进你master
,你有同样的东西你画了,但我留下branch1
并把标签放在左边并添加origin/master
到这里:
D--E--F <-- branch2 / A--B--C <-- branch1 / M--S <-- master, origin/master
(或者,如果你没有快进你的master
,只origin/master
指向提交S
).
您现在想告诉Git D-E-F
使用cherry-pick 进行复制,然后将标签移动branch2
到指向上次复制的提交.你不想要复制A-B-C
,因为他们在会合并S
.你想拷贝到去后S
,到origin/master
现在指向,您是否已经更新master
.因此:
git checkout branch2 git rebase --onto origin/master branch1
的upstream
是现在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
.)
1更确切地说,rebase git patch-id
使用对称差异选择(a)不合并提交和(b)与排除集合中的某些提交不同的提交.也就是说,不是upstream..HEAD
,Git的实际运行git rev-list
上upstream...HEAD
,用--cherry-mark
或类似的,挑出来的提交.实现方式略有不同,具体取决于特定类型的rebase.