Display all first-level descendant branches using Git

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:

  • Centralized GIT workflow/deployment - Release Branch
  • Reusing a merged development branch / Remerging into an unchanged stable branch with git
  • Linking SVN repository trunk as branch for Git repository subfolder
  • Subversion branch reintegration
  • Vendor Branching, Mercurial Style?
  • Create SVN branch from specific Tag and merge to trunk
  • 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?

  • How to use git for file synchronization?
  • How to exclude a commit from git pull request?
  • How do you get full url of branch to clone from command line? Bitbucket
  • For every commit, create an equivalent compiled commit in a separate repo or branch
  • What is this branch tracking (if anything) in git?
  • What is the equivalent of git commit -a for git add
  • One Solution collect form web for “Display all first-level descendant branches using Git”

    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 Baby is a git and github fan, let's start git clone.