我有一个带有master和a分支的存储库,在这两个分支之间有很多合并活动。当分支A基于master创建时,我如何在我的存储库中找到提交?

我的存储库基本上是这样的:

-- X -- A -- B -- C -- D -- F  (master) 
          \     /   \     /
           \   /     \   /
             G -- H -- I -- J  (branch A)

我正在寻找修订A,这不是git merge-base(——all)找到的。


当前回答

使用reflog似乎解决了这个问题git reflog <branchname>显示了所有的分支提交,包括创建分支。

这是来自一个分支,该分支在合并回主节点之前有2次提交。

git reflog june-browser-updates
b898b15 (origin/june-browser-updates, june-browser-updates) june-browser-updates@{0}: commit: sorted cve.csv
467ae0e june-browser-updates@{1}: commit: browser updates and cve additions
d6a37fb june-browser-updates@{2}: branch: Created from HEAD

其他回答

要从分支点查找提交,可以使用这个。

git log --ancestry-path master..topicbranch

如果你喜欢简洁的命令,

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。

我相信我已经找到了一种方法来处理这里提到的所有极端情况:

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'

喜欢。)

使用reflog似乎解决了这个问题git reflog <branchname>显示了所有的分支提交,包括创建分支。

这是来自一个分支,该分支在合并回主节点之前有2次提交。

git reflog june-browser-updates
b898b15 (origin/june-browser-updates, june-browser-updates) june-browser-updates@{0}: commit: sorted cve.csv
467ae0e june-browser-updates@{1}: commit: browser updates and cve additions
d6a37fb june-browser-updates@{2}: branch: Created from HEAD

这是我之前的答案的改进版本。它依赖于来自合并的提交消息来查找分支第一次创建的位置。

它适用于这里提到的所有存储库,我甚至还处理了邮件列表中产生的一些棘手的存储库。我还为此写了测试。

find_merge ()
{
    local selection extra
    test "$2" && extra=" into $2"
    git rev-list --min-parents=2 --grep="Merge branch '$1'$extra" --topo-order ${3:---all} | tail -1
}

branch_point ()
{
    local first_merge second_merge merge
    first_merge=$(find_merge $1 "" "$1 $2")
    second_merge=$(find_merge $2 $1 $first_merge)
    merge=${second_merge:-$first_merge}

    if [ "$merge" ]; then
        git merge-base $merge^1 $merge^2
    else
        git merge-base $1 $2
    fi
}