使用Git,如何记录两个特定分支之间的所有合并提交记录?

4
我的Git仓库有分支masterBranchABranchBBranchC。现在所有这些分支都已经合并到了主分支master中,可能多次合并(出于任何原因,这是一个假设的场景)。我想找到所有将BranchA合并到master的合并提交记录。在提问之前,我已经做了以下工作:
git log master ^BranchA --merges --oneline

这会给我所有在master中但不在BranchA中的合并提交。这实际上给了我所有我要找的提交,但也可能给了我不想要的提交,比如从BranchBBranchC合并到master中的提交。
示例输出:
10bdc8b Merge branch 'BranchA'
383693a Merge branch 'BranchB'
8af3b5c Merge branch 'master' of 192.168.0.0:/path/to/repo.git
aa0f22c Merge branch 'master' into BranchC
72bbf3a Merge branch 'BranchA'
fac1157 Merge branch 'BranchB'

我希望找到一个解决方案,输出只有 10bdc8b72bbf3a。不要仅仅查找名为 'BranchA' 的提交;我知道在这种情况下可以工作,但是可能会遇到合并提交具有自定义消息的情况,因此它可能不总是有效。

编辑

目前已经有一些好的回答,但是不幸的是,我遇到了一个墙壁,不知道该如何跨越。考虑以下场景:

   F                               <-BranchB
  / \        
 /   \        
A-----B----C-----D--E----K----L    <-master
       \        /    \       /
        \      /      \     /
         G----H--------I---J       <-BranchA

现在,我的目标是找到从BranchA合并到master的所有合并提交。通过观察图表,我可以看到我正在寻找L和D。然而,让我无法以编程方式解决这个问题的曲线球是合并提交I,在此提交中,将master合并到BranchA。
在这种情况下,如果我们对master中的所有提交使用“branch --contains”方法,我们会得到L、D和B。但是,如果我们对master中不在BranchA中的所有提交使用branch --contains,则只会得到L。两种方法都无法获得所需的输出。
同样地,如果我们使用git merge-base来查找父级,我们只会得到L。
据我所知,似乎没有一个好的方法来区分B和D,因为这两个提交都在BranchA的历史记录中。我可以通过观察它们来判断它们是不同的,但Git似乎没有一个好的方法来区分它们。
2个回答

1

在git中,没有单一的命令可以获取特定分支的所有合并记录,但您可以结合使用branch --contains和合并父级遍历来接近。忽略章鱼式合并提交,在我们感兴趣的主分支上,我们需要第二个合并父级:

bash$ for commit in \
        $(git log --format=%h --merges --max-parents=2 master ^topic); do \
          [[ $(git branch --contains ${commit}^2) =~ topic ]] && \
          echo $commit; done

当然,你必须确保没有快进合并,也就是在合并时必须指定--no-ff开关,否则你将失去上面脚本所依赖的必要的双亲分支。
还有一个额外的考虑因素,它是否会增加复杂性取决于你具体的使用情况。在下面的例子中,
I--A--M---N---O---F  ← master
 \   /       /   /
  `-B-------D ← / ← topicA
     \         /
      `--C----E ← topicB
提交B是合并提交M的父提交,也是ED的祖先。当你查询master上的合并提交时,你将得到提交F,O,M,然后当你查询哪些是topicA分支合并时,你将得到M,O,但当你询问哪些是topicB分支合并时,你将得到M,这主要是因为B是两个分支的祖先。

很好,你的Bash脚本需要做一个小修改。"git log --format=%h --merges master"需要改为"git log --format=%h --merges master ^<desired branch>"。否则,你会得到所有在所需分支创建之前合并的提交记录。此外,我们可以指定--max-parents=2来避免章鱼合并提交...但我还不确定我想如何处理这些提交。 - jacobhyphenated
@jacobhyphenated 很好的建议 - 已经根据您的建议更新了答案。 - mockinterface

0

我认为在Git中没有直接获取这个的方法,但是我有一个解决方案。如果是我,我会用Python来解决它。其他人可能会用Bash。

首先,我会获取A中合并提交的列表以及它们所合并的父提交:

git log --merges --format="%H %P" A

我会迭代结果中的每一行,查看第三个哈希值(假设所有合并都只有两个父级)。该行上的第一个哈希是合并提交本身的哈希 - 如果此合并是在A和B之间,则这就是我们想要的答案。第二个哈希是A分支中的父级。第三个哈希是另一个父级,我们要测试其是否属于B。因此,对于每个(第三个)哈希,我将调用

git merge-base B <hash>

如果结果与我输入的哈希值相同,那么这个提交(行首的第一个哈希值)就是将分支B合并到分支A的提交。


我有时候会在使用git merge-base时感到困惑,但在这种情况下,“git mergebase B <第一个提交>”是否等同于我们要做的<第三个提交>呢? - jacobhyphenated

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接