git - 查找创建分支的提交

git - Find commit from which was branch created

是否可以找到创建分支的提交(理想情况下只有提交哈希),即使该分支已经合并

例如:

master   A-B-C-D-E
          \   /
feature    F-G

feature 分支已合并到 master,但它仍然存在并且可以检出。我想找到 feature 分支从 A.

开始

(免责声明 : 题外话答案 - 未针对 已合并 分支)


如果featuremaster还没有合并,你可以得到他们的"merge-base"(doc):

git merge-base master feature

它将输出您的提交 A 的长格式哈希。

分支实际上没有 parent 个分支。 (相关:How to find the nearest parent of a Git branch?)您可以很容易地找到 A 的散列,但请考虑下图:

H--I--L--N--O--R---T--U   <-- master
 \     \     \    /
  J--K--M--P--Q--S   <-- feature

您想在这里找到哪些提交? OLH 都是 "where feature started from" 的可行候选者。但也许 feature 没有 任何 开始;也许它是从 P 开始的,它曾经有一个标签 main-feature。有关详细信息,请参阅相关问题。

从你的图表中找到提交 A,我将在此处重现我认为更准确的形式(名称 master 仅直接指向提交 E 例如 -提交 FG 也在分支 master 上!):

A--B--C--D--E   <-- master
 \      /
  F----G   <-- feature

我们可以从提交 E(大师提示)开始,然后退回到提交 D(合并)。当它的 parent 之一是 feature 的提示时,我们知道我们已经命中 D,即提交 G。然后我们从提交 D:

中获取两个 parent 哈希 ID
git rev-parse <hash-of-D>^@

并确保恰好有两个(three-parent 合并使这变得困难),然后在这两个 parent 哈希 ID 上调用 git merge-base --all。这会立即生成提交的哈希 ID A.

当我们在示例图上使用相同的过程时,我们从 U 退回到 T,发现它有两个 parent,第二个是 Sfeature 的尖端,并要求 Git 找到 RS 的合并基础。此 git merge-base --all 的输出是提交 O.

的哈希值

要在 shell 脚本中相对快速地执行此操作,请从:

开始
git rev-list --merges --first-parent master

它生成一个列表,其中包含通过遍历 master 的 first-parent 个后代可到达的所有合并提交哈希 ID。 (您可能需要也可能不需要 --first-parent;如果您一直大量使用 git pullmaster 的第一个 parent 链接可能会被 损坏.) 也就是说,这为我们提供了此处两个图表中的提交哈希 TD(可能还有更多)。如果您省略 --first-parent,请考虑您希望从其他分支合并到 master 的情况中得到什么,并带来来自 feature 相关分支的提交,并决定您是否需要 --topo-order 在你的 git rev-list.

接下来,遍历这些提交,获取它们的 parent 哈希值:

looking_for=$(git rev-parse feature)  # this is the hash ID we're looking for
found=false
for hash in (output of above git rev-list); do
    set -- $(git rev-parse ${hash}^@)
    case $# in
    2) # two parents, good
        if [  == $looking_for ]; then found=true; break; fi;;
    *) # more than two parents, we might go wrong
        echo "commit $hash has $# parents, help"; exit 1;;
    esac
done
if ! $found; then
    echo "unable to find the commit hash you were looking for"
    exit 1
fi

此时,由于 set 解析参数的方式,您在 </code> 和 <code> 中有了所需的提交对,因此:

# found the desired commit pair, so now just invoke git merge-base
set -- $(git merge-base --all  )
case $# in
1) echo "the commit you are looking for is "; exit 0;;
*) echo "I found $# candidate commits $@"; exit 1;;
esac