有没有办法列出已合并到当前工作树中的分支?以下为结束内容:
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
的结果中过滤掉这些分支?
答案 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。HEAD
中读取)HEAD
标识的提交的祖先? 1 如果是,则打印名称 B 。无论如何,请移至下一个名字。所以如果图的一部分看起来像:
I--J <-- feature2
/
...--F--G--H <-- master (HEAD)
\
K--L <-- feature1
与当前提交git branch --merged
相比,J
将测试的两个提交分别为L
和H
。如果J
是H
的祖先(但不是),则将打印feature2
。如果L
是H
的祖先(但不是),则将打印feature1
。当然,H
是H
的祖先,因此此是打印master
(带有前缀*
表示它是当前的分支)。
如果有一个第四名称指向F
,G
,H
中的任何一个,或指向{{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
也是这样。