我有一个带有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
它解决了我所有的常规案件。当然,有些边境地区没有被覆盖,但是…你好:-)
下面实现了等价于svn log——stop-on-copy的git,也可以用来查找分支的起源。
方法
前往所有分支
收集目标分支和其他分支的mergeBase
log和迭代
在mergeBase列表中出现的第一次提交时停止
就像所有的河流都流向大海,所有的分支都流向主人,因此我们在看似不相关的分支之间找到了合并基地。当我们从分支头通过祖先返回时,我们可以在第一个潜在的合并基点上停下来,因为理论上它应该是这个分支的原点。
笔记
我还没有尝试过这种兄弟分支和兄弟分支相互合并的方法。
我知道肯定有更好的解决办法。
详细信息:https://stackoverflow.com/a/35353202/9950。
我相信我已经找到了一种方法来处理这里提到的所有极端情况:
branch=branch_A
merge=$(git rev-list --min-parents=2 --grep="Merge.*$branch" --all | tail -1)
git merge-base $merge^1 $merge^2
查尔斯·贝利(Charles Bailey)非常正确,基于祖先顺序的解决方案价值有限;在一天结束的时候,你需要某种记录“这个提交来自分支X”,但这样的记录已经存在;默认情况下'git merge'会使用一个提交消息,例如“merge branch 'branch_A' into master”,这告诉你所有来自第二个父分支(commit^2)的提交都来自'branch_A',并合并到第一个父分支(commit^1),也就是'master'。
有了这些信息,你可以找到'branch_A'的第一次合并(这是'branch_A'真正存在的时候),并找到merge-base,这将是分支点:)
我尝试了Mark Booth和Charles Bailey的仓库,解决方案是有效的;怎么可能呢?唯一不可行的方法是手动更改合并的默认提交消息,从而真正丢失分支信息。
用途:
[alias]
branch-point = !sh -c 'merge=$(git rev-list --min-parents=2 --grep="Merge.*$1" --all | tail -1) && git merge-base $merge^1 $merge^2'
然后你可以使用'git branch-point branch_A'
喜欢。)