Git命令列出合并的分支

时间:2019-10-06 23:00:49

标签: git branch git-branch

有没有办法列出已合并到当前工作树中的分支?以下为结束内容:

git branch -r --merged

但是,这也包括空分支。例如,在当前分支上的最新提交之前的某个时刻,我运行了以下命令:

git checkout -b empty_branch
git push -u origin empty_branch

现在,第一个命令在结果列表中包含 empty_branch 。我发现了一个相关问题,问how to find empty branches in git,但是对于没有提交的分支,可接受的答案不起作用。有什么方法可以检测git中无提交的分支,或者以其他方式从git branch --merged的结果中过滤掉这些分支?

1 个答案:

答案 0 :(得分:1)

您正在解决至少一个关于Git的错误假设。正如Git所说的那样,这不是一个不合理的假设,但是这会使您的整个问题变得有些复杂。

在Git中,至少在最初,分支名称的含义并不像大多数人认为的那样重要。分支名称只是保存一些现有提交的哈希ID。有一个基础实体,人们称其为“分支”,它由分支名称所定义的 提示提交中的某些或全部提交组成。有关(更多)更多信息,请参见What exactly do we mean by "branch"?Think Like (a) Git,但让我们尝试一下快速总结:

  • Git真正的全部目的是 commits 。每个提交都由其自己的唯一哈希ID标识。没有其他提交可以拥有此哈希ID。提交的内容包括快照(由索引而不是工作树制成),但我将尽量避免在此处涉及所有这些冗长的细节,并包括提交作者的姓名和电子邮件地址,对于提交者(通常是同一个人)是相同的,并且有两个日期和时间戳:一个用于作者,一个用于提交者。它们还包括提交者在他/她/他们/代词选择提交时提供的日志消息。也许最重要的是,提交的内容包括应视为该提交的直接前身的任何提交的原始哈希ID。

  • 换句话说,每个提交都有一组 parent 哈希ID,最常见的是一个哈希ID。这些父ID使得提交形成了向后看的链:从 last 提交,我们可以返回到先前的提交。从那里,我们可以再返回一步,依此类推。因此,如果像master这样的分支名称拥有 last 提交的哈希ID,我们应该考虑将其作为分支的一部分,其余的提交就是该提交的父对象,即parent(父级,等等。如果master提示提交的哈希ID是H,其父级是G,而G的父级是F,依此类推,我们有:

    ... <-F <-G <-H   <-- master
    

    这就是分支的含义:它是名称,或者是一系列以H结尾的提交,或者两者都是:我们倾向于猜测某人说“ master时的意思。分支”。

git branch --merged的作用是:

  • 找到当前分支(HEAD)的哈希ID。
  • 对于所有分支名称​​ B 跳过当前分支(从HEAD中读取) oops:Git 跳过当前分支,这很烦人:
    • B 标识的提交是否是由HEAD标识的提交的祖先? 1 如果是,则打印名称​​ B 。无论如何,请移至下一个名字。

所以如果图的一部分看起来像:

             I--J   <-- feature2
            /
...--F--G--H   <-- master (HEAD)
      \
       K--L   <-- feature1

与当前提交git branch --merged相比,J将测试的两个提交分别为LH。如果JH的祖先(但不是),则将打印feature2。如果LH的祖先(但不是),则将打印feature1。当然,HH的祖先,因此此打印master(带有前缀*表示它是当前的分支)。

如果有一个第四名称指向FGH中的任何一个,或指向{{1}之后的任何提交},F也会打印那个名称。

考虑,您想要的是打印所有指向真正祖先的提交的名称,而不是直接指向提交git branch --merged的任何名称。最简单的方法可能是让H打印所有内容,然后从列表中删除其哈希ID与git branch --merged匹配的任何名称。

要删除此类名称,请在每个名称上使用HEAD。使用git rev-parse查找当前分支的哈希ID,即上图中的git rev-parse HEAD的实际哈希ID。然后,再次对H中的每个名称使用git rev-parse,如果结果与第一个git branch --merged相同,则丢弃该名称。否则,请保留该名称。

(您将为此编写一些代码。如果git rev-parse可以做到git for-each-ref并结合一些布尔表达式,则可以这样做,但不能这样做--not并合并。)


1 Git使用的is-ancestor测试允许相等,即等于≤而不是<(或更准确地说,等于precede或等于precede)。 --not也是这样。