如何判断集成分支是否包含特性分支

How to determine if integration branch contains feature branch

我正在做删除本地分支的可怕工作。我从我们的集成分支获取最新的:

git fetch origin dev

然后我想将 origin/dev 与本地功能分支进行比较。但是我不想签出origin/dev。我相信目标是确保 origin/dev 的 git 日志包含每个功能分支的提示(最新提交)。

以下命令对我的情况不是很有效:

git branch --contains <commit-id>
  1. 不清楚如何使用当前分支以外的分支。
  2. 我没有比较分支的commit-id,但是我有分支名称。

所以我正在寻找替代命令:

git branch origin/dev --contains-branch <some-feature-branch>

是否有可以执行此操作的命令?

git branch --contains所做的是:

  1. HEAD 解析为提交哈希。如果您在分支 br 上,这会将 name br 解析为提交哈希。 (让一些变量 h 代表这个散列。)
  2. 对于所有分支名称:

    • 将名称解析为提交哈希。我们将此称为 b 作为分支哈希。
    • 测试祖先性:bh 的祖先吗?
    • 如果 b h 的祖先,打印该分支的名称。

命令现在完成:它列出了分支的名称,其分支尖端提交包含在该分支中。

你的问题很相似,但更简单。您想要将名称 origin/dev 解析为某个散列 h。然后,对于分支名称的某些子集——您关心的功能名称——您想要:

  • 将名称解析为哈希 ID b.
  • 测试祖先性:bh 的祖先吗? (换句话说:这个分支的 tip 提交是否包含在 origin/dev 中,是因为它是 origin/dev 的 tip 提交的祖先?)
  • 如果是,打印名称。

有一个命令实现了这个 "is-ancestor" 测试,但有点令人惊讶:它是 git merge-base。命令:

git merge-base $b $h

如果 $b 是 $h 的祖先则报告成功(退出零),否则报告失败(退出非零)。它实施的 "is ancestor" 测试与 git branch --contains 使用的相同,因此这直接提供了您想要的答案。

剩下的问题是找到所需的分支名称。 git for-each-ref 命令就是专门为此而设计的。

因此:

hname=origin/dev
h=$(git rev-parse $hname) || die "cannot get commit hash ID for $hname"
git for-each-ref --format='%(refname:short) %(objectname)' refs/heads/feature |
    while read name b; do
        if git merge-base --is-ancestor $h $b; then
            echo $name is contained within $hname
        fi
    done

(注:未经测试)。这里的 refs/heads/feature 代表名为 feature/* 的分支;如果你有一个不同的模式,你需要匹配,使用那个不同的模式,或者使用 refs/heads 本身并在循环中放一些东西来跳过 "uninteresting" 分支名称,或者任何需要的东西。

有关详细信息,请参阅 git merge-base and git for-each-ref (and git rev-parse 的文档。

要列出可从 origin/dev 到达的分支提示,您可以使用

git branch --merged origin/dev

请注意,如果它是本地分支机构(我假设不是您的情况),它会列出 origin/dev

如果您想围绕 git branch 编写脚本,请注意这是一个 "porcelain" 命令,即它的输出格式并非一成不变,可能会在 [= 的未来版本中发生变化21=].