2010-02-05 14 views
8

Come posso ottenere un elenco di rami che sono discendenti di primo livello dell'attuale HEAD?Visualizzare tutte le diramazioni discendenti di primo livello utilizzando Git

posso ottenere un elenco di tutto l'albero con:

git log --graph --abbrev-commit --pretty=decorate --branches 

che dà

* 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 

ma mi piacerebbe ottenere solo un elenco piana del primo livello bambini della ramo corrente, come in questo esempio per master:

dev 
issue-7559 
issue-8354 
issue-8351 

e se ero sul ramo issue-7559 Vedrei solo:

experimental 

Come posso andare su questo?

+0

Cosa intendete esattamente per i discendenti di primo livello? Quale ramo e criteri darebbe l'elenco di 4 rami che tu dai? –

+0

Siamo spiacenti, quell'esempio era per 'master'. Sto cercando di ottenere un elenco di rami che non hanno altra testa tra loro e il genitore. – mskfisher

+0

Sembra un po 'complicato. Si potrebbe provare a utilizzare i cicli nidificati di 'git-for-each' per verificare se la base di unione per qualsiasi altro ramo e il ramo sottoposto a test non è altro che il ramo corrente. Però sembra piuttosto una cosa arbitraria. C'è un problema più grande che stai cercando di risolvere? –

risposta

3

Si potrebbe fare come segue.

Prima il solito preambolo:

#! /usr/bin/perl 

use warnings; 
use strict; 

Usa git for-each-ref per raccogliere l'SHA-1 e un nome per ogni 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; 
} 

Se un commit è un bambino di HEAD, l'insieme di commit raggiungibile da HEAD escludendo tutto ciò che è raggiungibile dal commit in questione è il set vuoto. Possiamo verificare questa relazione con 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/; 
} 

Per ogni arbitro che è un discendente di HEAD ma non equivalente HEAD, esaminiamo il percorso da HEAD a quello di riferimento utilizzando git log. Se il percorso contiene la punta di un altro ramo, l'arbitro non può essere un bambino di primo livello.

Tutti i sopravvissuti di questo guanto di sfida sono bambini di primo livello.

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.\[email protected]" if $?; 
    for (@log) { 
    chomp; 
    next if $_ eq $refsha; 
    next REF if exists $headsha{$_}; 
    } 

    print $ref, "\n"; 
} 
+0

Speravo di evitare di scrivere codice per realizzare questo, e tu mi hai aiutato a farlo. :) – mskfisher

+0

@mskfisher Sono contento che sia di beneficio. Godere! –

Problemi correlati