我有一个带有master和a分支的存储库,在这两个分支之间有很多合并活动。当分支A基于master创建时,我如何在我的存储库中找到提交?
我的存储库基本上是这样的:
-- X -- A -- B -- C -- D -- F (master)
\ / \ /
\ / \ /
G -- H -- I -- J (branch A)
我正在寻找修订A,这不是git merge-base(——all)找到的。
当然我遗漏了一些东西,但在我看来,以上所有的问题都是因为我们总是试图找到历史上的分支点,这导致了各种各样的问题,因为可用的合并组合。
相反,我采用了一种不同的方法,基于两个分支共享很多历史,分支之前的所有历史都是100%相同的,所以我的建议是向前(从第一次提交开始),寻找两个分支的第一个差异。简单地说,分支点就是找到的第一个差值的父点。
在实践中:
#!/bin/bash
diff <( git rev-list "${1:-master}" --reverse --topo-order ) \
<( git rev-list "${2:-HEAD}" --reverse --topo-order) \
--unified=1 | sed -ne 's/^ //p' | head -1
它解决了我所有的常规案件。当然,有些边境地区没有被覆盖,但是…你好:-)
如果你喜欢简洁的命令,
git rev-list $(git rev-list --first-parent ^branch_name master | tail -n1)^^!
下面是一个解释。
下面的命令提供了在创建branch_name之后发生的master中所有提交的列表
git rev-list --first-parent ^branch_name master
因为你只关心那些最早的提交,所以你想要输出的最后一行:
git rev-list ^branch_name --first-parent master | tail -n1
最早提交的父文件不是“branch_name”的祖先,根据定义,它在“branch_name”中,并且在“master”中,因为它是“master”中的某个文件的祖先。两个分支中都有最早的提交。
命令
git rev-list commit^^!
只是一种显示父提交引用的方法。你可以用
git log -1 commit^
之类的。
PS:我不同意祖先顺序无关紧要的观点。这取决于你想要什么。例如,在这种情况下
_C1___C2_______ master
\ \_XXXXX_ branch A (the Xs denote arbitrary cross-overs between master and A)
\_____/ branch B
将C2输出为“分支”提交是非常有意义的。这是开发人员从“master”扩展出来的时候。当他进行分支时,分支B甚至没有合并到他的分支中!这就是本文给出的解决方案。
如果您想要的是最后一次提交——这样从起点到分支“A”上最后一次提交的所有路径都要经过C,那么您就需要忽略祖先顺序。这纯粹是拓扑学上的,让您了解从何时开始同时运行两个版本的代码。这时您将使用基于merge-base的方法,在我的示例中,它将返回C1。