你的措辞(“rebase [a small change made to master] into feature”)对我来说似乎有点奇怪,因为通常你会将 feature 重新设置为 master。 (“进入”这个词并不适用。)除此之外,我认为绘制提交图总是有帮助的。您可以使用gitk 或类似的查看器来绘制它,或者git log --graph,也许还可以使用--oneline 来绘制一个垂直方向的图形。但这里我会画一个水平的,单个大写字母代表特别有趣的提交,小写的os 代表更无聊的提交。
出于我们的目的,我将省略任何已配置的上游(origin/master 和/或origin/feature)。如果它们确实存在,您可能希望将它们添加到您自己的绘图中,然后注意当git rebase 复制提交时,它不会移动任何 other 标签(包括这些远程-跟踪分支)指向现有提交:它只移动一个标签,即当前分支的标签。
... - A - o - o - o - F <-- master
\ \
B - C - D - E - G <-- HEAD -> feature
幸运的是,这与您的预变基设置相当接近,并且准确地反映了您的 git merge 的结果。在您进行合并之前和之后,提交A 是feature 与master 分离的原始基数;提交B 到E 是在feature 上进行的;各种不太有趣的o 提交是在master 上进行的;并提交F 是大师的提示。您在分支 feature 上(因此 HEAD 命名为分支 feature,而 git status 表示“在分支功能上”)并且您运行 git merge master 并进行了合并并提交。
此合并在feature 上创建了最尖端的提交,即提交G,这是一个合并提交。
之后,您检查了分支master(使HEAD 指向名称master)并进行了移动master 尖端的新提交,所以让我们将其添加到我们的图表中-so-远:
... - A - o - o - o - F - H <-- HEAD -> master
\ \
B - C - D - E - G <-- feature
最后,你想在master 的(新提示)上重新设置feature,所以你做了git checkout feature:
... - A - o - o - o - F - H <-- master
\ \
B - C - D - E - G <-- HEAD -> feature
现在你运行命令git rebase master。
rebase 所做的是复制 提交。
首先,它必须找到要复制的提交。它应该复制的提交是那些可以从当前分支访问的提交——即,从名称feature——但不是从你指定为上游的分支,即master。
这是我们遇到一个相当大的问题的地方。看看recent git rebase documentation的这段(相当密集的):
由当前分支中的提交所做但不在当前分支中的所有更改
被保存到一个临时区域。这与git log <upstream>..HEAD 显示的提交集相同;或git log 'fork_point'..HEAD,如果--fork-point 处于活动状态(请参阅下面--fork-point 的说明);或git log HEAD,如果指定了--root 选项。
分叉点本身有点复杂,但我们现在可以忽略它,因为使用命令git rebase master 意味着它已关闭。因此,您可以看到要使用 git log master..HEAD 重新设置的提交。这是提交 B、C、D、E 和 G(除了变基通常会抛出合并)。
鉴于master 和feature 的合并基数 是提交G,您可能想知道为什么在这里包含B 到E。问题是,虽然合并提交G 指向提交F(可从主控访问),但提交F 不会(也不能)“指向”G。因此,当我们从master(新提交H)的尖端开始并向后工作时,我们得到H、F、所有无聊的os、A,以及A之前的所有内容:这些是提交排除。当我们从feature 的尖端开始(提交G)并向后工作时,我们得到G、E、D、C 和B,然后再点击第一个排除的( A)。因此,这些是变基的候选者。
如果您允许 rebase 继续进行并解决所有冲突,您将得到:
B' - C' - D' - E' <-- HEAD -> feature
/
... - A - o - o - o - F - H <-- master
\ \
B - C - D - E - G [abandoned]
(假设所有要复制的提交都有要复制的实际更改;提交G 不需要复制,因为这次它不会贡献任何东西)。