使用Git显示所有第一级后代分支 [英] Display all first-level descendant branches using Git
问题描述
如何获得当前HEAD的第一级后代的分支列表?
我可以通过以下方式获取整棵树的列表:
p> git log --graph --abbrev-commit --pretty = decorate --branches
给出的是
* 2eff4a7 ... (refs / heads / issue-8351)增加了工厂工厂。
* 2e387aa ...重构所有工厂工厂。
| * b3fad52 ...(refs / heads / issue-8354)将baz移出构造函数。
| /
| * f4cf3fe ...(参考/头/实验)quuz看起来不错
| * 1d276b9 ...危险的修复以quuz替换quux。
| * d6b0222 ...(refs / heads / issue-7559)修复了foo中的quux。
| /
| * 3f4cfff ...(refs / heads / dev)wip
| /
* 76f493f ...(refs / heads / master)SVN 30192
但我只想获得当前分支的第一级孩子的简单列表,如 master
:
dev
发行-7559
发行-8354
issue-8351
如果我在分支 issue-7559
我只会看到:
实验性
我该怎么办?
您可以做到这一点如下。
首先是通常的序言:
#! / usr / bin / perl
使用警告;
使用strict;
使用 git for-each-ref
来收集SHA- 1和名字为每个ref:
sub refs {
打开我的$ fh, - |,git ,for-each-ref,
--format =%(objectname)\t%(refname:short)
或死$ 0:无法运行git for-each- REF;
my%ref2sha;
while(< $ fh>){
chomp;
my($ sha,$ ref)= split / \t /;
$ ref2sha {$ ref} = $ sha;
}
\%ref2sha;
$ b $ p
$ b 如果一个提交是 HEAD ,从 HEAD
可达到的提交集合中排除了所提交的所有内容都是空集合。我们可以通过 git rev-list
。
sub is_child {
my ($ ref)= @_;
#git rev-list ^ dev master
my $ refs =`git rev-list ^ $ ref HEAD - 2>& 1`;
die$ 0:git rev-list-failed.\\\
$ refsif $ ?;
$ refs!〜/ \S /;
$ / code>
对于每个属于 HEAD
但它不等于 HEAD
,我们检查从 HEAD
到该引用的路径, a href =http://git-scm.com/docs/git-log =nofollow noreferrer> git log
。如果路径包含另一个分支的提示,那么裁判不能是第一级的孩子。
这个手套的所有幸存者都是一级孩子。
chomp(my $ head =`git rev-parse HEAD 2>& 1`);
die$ 0:git rev-parse failed.\\\
$ headif $ ?;
my $ ref2sha = refs;
my%headsha = reverse%$ ref2sha;
REF:
foreach my $ ref(keys%$ ref2sha){
my $ refsha = $ ref2sha-> {$ ref};
next,如果$ refsha eq $ head || !is_child $ ref;
my @log =`git log --pretty = format:%H .. $ ref 2>& 1`;
死$ 0:git log failed.\\\
@logif $ ?; (@log){
chomp;
;
next,如果$ _ eq $ refsha;
next如果存在$ headsha {$ _};
}
print $ ref,\\\
;
}
How can I get a list of branches that are first-level descendants of the current HEAD?
I can get a list of the whole tree with:
git log --graph --abbrev-commit --pretty=decorate --branches
which gives
* 2eff4a7... (refs/heads/issue-8351) Added a factory factory factory.
* 2e387aa... Refactored all of the factory factories.
| * b3fad52... (refs/heads/issue-8354) Moved the baz out of the constructor.
|/
| * f4cf3fe... (refs/heads/experimental) quuz looking good
| * 1d276b9... Risky fix to replace the quux with the quuz.
| * d6b0222... (refs/heads/issue-7559) Fixed the quux in the foo.
|/
| * 3f4cfff... (refs/heads/dev) wip
|/
* 76f493f... (refs/heads/master) SVN 30192
but I'd like to just get a plain list of the first-level children of the current branch, like this example for master
:
dev
issue-7559
issue-8354
issue-8351
and if I was on branch issue-7559
I'd only see:
experimental
How might I go about this?
解决方案 You could do it as follows.
First the usual preamble:
#! /usr/bin/perl
use warnings;
use strict;
Use git for-each-ref
to gather the SHA-1 and name for each ref:
sub refs {
open my $fh, "-|", "git", "for-each-ref",
"--format=%(objectname)\t%(refname:short)"
or die "$0: failed to run git for-each-ref";
my %ref2sha;
while (<$fh>) {
chomp;
my($sha,$ref) = split /\t/;
$ref2sha{$ref} = $sha;
}
\%ref2sha;
}
If a commit is a child of HEAD
, the set of commits reachable from HEAD
excluding everything reachable from the commit in question is the empty set. We can check this relationship with git rev-list
.
sub is_child {
my($ref) = @_;
# git rev-list ^dev master
my $refs = `git rev-list ^$ref HEAD -- 2>&1`;
die "$0: git rev-list-failed.\n$refs" if $?;
$refs !~ /\S/;
}
For each ref that is a descendant of HEAD
but it not equivalent to HEAD
, we examine the path from HEAD
to that reference using git log
. If the path contains the tip of another branch, the ref cannot be a first-level child.
All survivors of this gauntlet are first-level children.
chomp(my $head = `git rev-parse HEAD 2>&1`);
die "$0: git rev-parse failed.\n$head" if $?;
my $ref2sha = refs;
my %headsha = reverse %$ref2sha;
REF:
foreach my $ref (keys %$ref2sha) {
my $refsha = $ref2sha->{$ref};
next if $refsha eq $head || !is_child $ref;
my @log = `git log --pretty=format:%H ..$ref 2>&1`;
die "$0: git log failed.\n@log" if $?;
for (@log) {
chomp;
next if $_ eq $refsha;
next REF if exists $headsha{$_};
}
print $ref, "\n";
}
这篇关于使用Git显示所有第一级后代分支的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!