使用Git 1.9/2.0(2014年第一季度)中的
git merge-base --fork-point
命令,您可以请求Git查找最佳公共祖先。您可以在以下链接中了解该新选项的详细信息:“
如何在有人将rebase或reset推送到已发布分支后进行恢复/同步?”和“
如何处理已经被rebase的公共存储库?”。请注意,保留HTML标签,但不要写出解释。
自从John Keeping (johnkeeping
)提交了commit ad8261d,git rebase
就可以使用相同的新选项--fork-point
,如果您需要将分支customers/acme_patches
合并到devel
,这将非常方便。
(我不是在说这在您特定的情况下有意义)
注意:Git 2.16(2018年第一季度)确实澄清和增强了“
merge-base --fork-point
”的文档,因为它清楚地说明了计算的内容,但不清楚其原因/用途。
请参见
commit 6d1700b(由
Junio C Hamano(gitster
)于2017年11月9日提交)。
(由Junio C Hamano -- gitster
--在commit 022dd4a中合并,于2017年11月27日)
merge-base --fork-point
doc: 澄清示例和失败模式
用于解释--fork-point
模式的图示历史从最旧到最新命名了三个关键点提交B3、B2和B1,这很难阅读。
将它们重新标记为B0、B1、B2。
还要说明使用了--fork-point
功能后重置基础后的历史记录。
文本已经提到了引用日志的使用,但描述不清楚我们试图通过使用引用日志获得什么好处。
澄清它是为了找到已知在远程跟踪分支末端的提交。
这反过来需要用户知道基本假设的影响,即,引用日志条目的过期将使确定哪些提交位于远程跟踪分支末端成为不可能,而当存在疑问时我们会失败(而不是给出随机且不正确的结果,甚至没有警告)。
另一个限制是,如果您不是从远程跟踪分支的末端而是从中间派生的,那么它将没有用处。
对它们进行描述。
因此,文档现在的内容如下:
在使用git checkout -b topic origin/master
创建topic
分支并进行操作后,远程追踪分支origin/master
的历史记录可能已经被倒回和重建,导致这种形式的历史记录:
o---B2
/
---o---o---B1--o---o---o---B (origin/master)
\
B0
\
D0---D1---D (topic)
当
origin/master
指向提交 B0、B1、B2 时,现在它指向 B,你的
topic
分支是建立在它指向 B0 的时候开始的,并且你在上面构建了三个提交 D0、D1 和 D。现在你想将你在
topic
上的工作变基到更新的
origin/master
上。
这种情况下,
git merge-base origin/master topic
将返回上图中 B0 的父提交,但是
B0^..D
不是你想要重放在 B 之上的提交范围(它包括了 B0,但你没有写过它;它是另一方在将其提示从 B0 移动到 B1 时丢弃的提交)。
git merge-base --fork-point origin/master topic
是为了帮助这种情况而设计的。它不仅考虑 B,还考虑 B0、B1 和 B2(即你的存储库 reflog 知道的远程跟踪分支的旧提示)来查看你的主题分支是在哪个提交上建立的,并找到 B0,使你只能重放你的主题上的提交,而排除其他方后来丢弃的提交。
$ fork_point=$(git merge-base --fork-point origin/master topic)
将找到B0,并且
$ git rebase --onto origin/master $fork_point topic
“将 D0、D1 和 D 放在 B 之上,以创建此形状的新历史记录:”
o---B2
/
---o---o---B1--o---o---o---B (origin/master)
\ \
B0 D0'--D1'--D' (topic - updated)
\
D0---D1---D (topic - old)
一个警告是你仓库中较老的reflog条目可能会被
git gc
过期。
如果B0不再出现在远程跟踪分支
origin/master
的reflog中,那么
--fork-point
模式显然无法找到它并且失败,避免给出随机和无用的结果(例如没有
--fork-point
选项的相同命令的父级如B0)。
此外,您使用
--fork-point
模式的远程跟踪分支必须是您的主题从其尖端分叉出来的那个。
如果您从比尖端旧的提交中分叉,此模式将无法找到分叉点(想象一下在上面的示例历史记录中B0不存在,
origin/master
从B1开始,移动到B2然后B,当您的主题在
origin/master^
处分叉时,
origin/master
是B1;历史记录的形状与上面相同,没有B0,而B1的父级是
git merge-base origin/master topic
正确找到的,但
--fork-point
模式不会找到它,因为它不是曾经在
origin/master
的顶部的提交之一)。
git merge-base --fork-point
。请参见下面的答案。 - VonC