我试图在Git中得到一个分支头列表。到目前为止,我发现git log --simplify-by-decoration似乎包含了所有分支并显示了头,但它也显示了一个额外的提交,这对我来说是无用的。有没有更好的方法来做这件事,或者这是我应该使用的?所以说清楚点:我希望有一个输出,它能给出我本地仓库中所有分支的头,基本上,我只需要每个头的哈希值,但是我可以从我得到的任何输出中正则化它。
git log --simplify-by-decoration
mefy6pfw1#
您应该能够使用git show-ref命令。git-show-ref documentation
git show-ref
git show-ref --heads -s
00jrzges2#
如果你在一个大型仓库上使用git show-ref --heads -s,一个有分支或标签以外的引用的仓库(比如gerrit repository),请确保使用Git 2.37(Q3 2022)。"git show-ref --heads"(man)(和"--tags")仍然在 * 所有 * 引用上迭代,只是为了丢弃指定区域之外的引用,Git 2.37(Q3 2022)对此进行了修正。参见Taylor Blau ( ttaylorr )的commit c0c9d35(2022年6月3日)。(由Junio C Hamano -- gitster --合并到commit 2246937,2022年6月13日)
git show-ref --heads
--tags
ttaylorr
gitster
builtin/show-ref.c
--heads
签署人:泰勒·布劳当show-ref与--heads或--tags选项结合使用时,它可以避免迭代它不关心的存储库引用部分。但是它没有利用这种潜在的优化。当这个命令被重新引入358ddb6(添加,2006年9月15日,Git v1.4.4-rc1--merge)(添加"git show-ref"(man)内置命令,2006年9月15日)时,for_each_ref_in()确实存在。但是,由于大多数存储库没有太多(任何?)不是分支或标记的引用,这在实践中几乎没有什么区别。尽管对于分支和标签(或者,更可能是服务器操作员,许多隐藏引用)的存储库来说,这会造成很大的不同。例如,一个仓库有500,000个"隐藏"引用(所有引用的形式都是"refs/__hidden__/N"),只有一个分支:
show-ref
for_each_ref_in()
refs/__hidden__/N
git commit --allow-empty -m "base" && seq 1 500000 | sed 's,\(.*\),create refs/__hidden__/\1 HEAD,' | git update-ref --stdin && git pack-refs --all
在我的机器上,输出单个分支的存在性目前需要大约50ms。这些时间的绝大部分都浪费在迭代那些我们知道要丢弃的引用上。相反,教导show-ref,当分别给定--heads和/或--tags时,它只能迭代"refs/heads"和/或"refs/tags"。一些有趣的小事情要注意:
refs/heads
refs/tags
for_each_ref()
for_each_fullref_in()
for_each_fullref_in_prefixes()
for_each_branch_ref()
for_each_tag_ref()
当heads_only或tags_only被置位时,我们可以完全消除builtin/show-ref.c::show_ref()中的strcmp()调用,因为我们知道show_ref()永远不会看到非分支或标记引用。不幸的是,我们不能使用for_each_fullref_in_prefixes()来增强show-ref的模式匹配,因为show-ref模式在 * 后缀 * 上匹配(例如,模式"foo"显示"refs/heads/foo"、"refs/tags/foo"等,而不是"foo/*")。尽管如此,在我们上面的合成示例中,这提供了显著的加速("git"大约是v2.36,"git.compile"是这个补丁):
heads_only
tags_only
builtin/show-ref.c::show_ref()
strcmp()
show_ref()
refs/heads/foo
refs/tags/foo
foo/*
git.compile
$ hyperfine -N 'git show-ref --heads' 'git.compile show-ref --heads' Benchmark 1: git show-ref --heads Time (mean ± σ): 49.9 ms ± 6.2 ms [User: 45.6 ms, System: 4.1 ms] Range (min … max): 46.1 ms … 73.6 ms 43 runs Benchmark 2: git.compile show-ref --heads Time (mean ± σ): 2.8 ms ± 0.4 ms [User: 1.4 ms, System: 1.2 ms] Range (min … max): 1.3 ms … 5.6 ms 957 runs Summary 'git.compile show-ref --heads' ran 18.03 ± 3.38 times faster than 'git show-ref --heads'
2条答案
按热度按时间mefy6pfw1#
您应该能够使用
git show-ref
命令。git-show-ref documentation00jrzges2#
如果你在一个大型仓库上使用
git show-ref --heads -s
,一个有分支或标签以外的引用的仓库(比如gerrit repository),请确保使用Git 2.37(Q3 2022)。"
git show-ref --heads
"(man)(和"--tags
")仍然在 * 所有 * 引用上迭代,只是为了丢弃指定区域之外的引用,Git 2.37(Q3 2022)对此进行了修正。参见Taylor Blau (
ttaylorr
)的commit c0c9d35(2022年6月3日)。(由Junio C Hamano --
gitster
--合并到commit 2246937,2022年6月13日)builtin/show-ref.c
:避免使用--heads
、--tags
进行过度迭代签署人:泰勒·布劳
当
show-ref
与--heads
或--tags
选项结合使用时,它可以避免迭代它不关心的存储库引用部分。但是它没有利用这种潜在的优化。
当这个命令被重新引入358ddb6(添加,2006年9月15日,Git v1.4.4-rc1--merge)(添加"
git show-ref
"(man)内置命令,2006年9月15日)时,for_each_ref_in()
确实存在。但是,由于大多数存储库没有太多(任何?)不是分支或标记的引用,这在实践中几乎没有什么区别。
尽管对于分支和标签(或者,更可能是服务器操作员,许多隐藏引用)的存储库来说,这会造成很大的不同。
例如,一个仓库有500,000个"隐藏"引用(所有引用的形式都是"
refs/__hidden__/N
"),只有一个分支:在我的机器上,输出单个分支的存在性目前需要大约50ms。
这些时间的绝大部分都浪费在迭代那些我们知道要丢弃的引用上。
相反,教导
show-ref
,当分别给定--heads
和/或--tags
时,它只能迭代"refs/heads
"和/或"refs/tags
"。一些有趣的小事情要注意:
for_each_ref()
调用,因为我们知道它不会给我们任何我们已经过滤掉的引用。for_each_fullref_in()
进行两次单独的调用(并且避免,比方说,更专门化的for_each_fullref_in_prefixes()
,因为我们知道每一次调用所枚举的引用集是不相交的,所以我们永远不会在两次调用中看到相同的引用。for_each_branch_ref()
和for_each_tag_ref()
),因为我们希望在show-ref
的输出中出现完全限定的引用名称。当
heads_only
或tags_only
被置位时,我们可以完全消除builtin/show-ref.c::show_ref()
中的strcmp()
调用,因为我们知道show_ref()
永远不会看到非分支或标记引用。不幸的是,我们不能使用
for_each_fullref_in_prefixes()
来增强show-ref
的模式匹配,因为show-ref
模式在 * 后缀 * 上匹配(例如,模式"foo"显示"refs/heads/foo
"、"refs/tags/foo
"等,而不是"foo/*
")。尽管如此,在我们上面的合成示例中,这提供了显著的加速("git"大约是v2.36,"
git.compile
"是这个补丁):