Skip to content

Instantly share code, notes, and snippets.

@duub
Forked from bill-auger/git-branch-status
Last active May 28, 2016 00:00
Show Gist options
  • Select an option

  • Save duub/2014d207d0b8086427df to your computer and use it in GitHub Desktop.

Select an option

Save duub/2014d207d0b8086427df to your computer and use it in GitHub Desktop.

Revisions

  1. @bill-auger bill-auger revised this gist Mar 6, 2015. 1 changed file with 56 additions and 44 deletions.
    100 changes: 56 additions & 44 deletions git-branch-status
    Original file line number Diff line number Diff line change
    @@ -10,47 +10,57 @@


    read -r -d '' USAGE <<-'USAGE'
    usage: git-branch-status
    git-branch-status [-a | --all]
    git-branch-status [-b | --branch] [branch-name]
    git-branch-status [-d | --dates]
    git-branch-status [-h | --help]
    usage:
    git-branch-status
    git-branch-status [-a | --all]
    git-branch-status [-b | --branch] [branch-name]
    git-branch-status [-d | --dates]
    git-branch-status [-h | --help]
    git-branch-status [-v | --verbose]
    examples:
    # show only branches for which upstream HEAD differs from local
    $ git-branch-status
    | collab-branch | (behind 1) | (ahead 2) | origin/collab-branch |
    | feature-branch | (behind 0) | (ahead 2) | origin/feature-branch |
    | master | (behind 1) | (ahead 0) | origin/master |
    # show all branches - even those with no upstream and those up-to-date
    $ git-branch-status -a
    $ git-branch-status --all
    | local-branch | n/a | n/a | (no upstream) |
    | master | (behind 1) | (ahead 0) | origin/master |
    | tracked-branch | (even) | (even) | origin/tracked-branch |
    # show the current branch
    $ git-branch-status -b
    $ git-branch-status --branch
    | current-branch | (behind 0) | (ahead 2) | origin/current-branch |
    # show a specific branch
    $ git-branch-status specific-branch
    $ git-branch-status -b specific-branch
    $ git-branch-status --branch specific-branch
    | specific-branch | (behind 0) | (ahead 2) | origin/specific-branch |
    # show the timestamp of each HEAD
    $ git-branch-status -d
    $ git-branch-status --dates
    | 1999-12-31:master | (behind 2) | (ahead 0) | 2000-01-01:origin/master |
    # print this usage message
    $ git-branch-status -h
    $ git-branch-status --help
    "prints this usage message"
    # show only branches for which upstream HEAD differs from local
    $ git-branch-status
    | collab-branch | (behind 1) | (ahead 2) | origin/collab-branch |
    | feature-branch | (behind 0) | (ahead 2) | origin/feature-branch |
    | master | (behind 1) | (ahead 0) | origin/master |
    # show all branches - even those with no upstream and those up-to-date
    $ git-branch-status -a
    $ git-branch-status --all
    | local-branch | n/a | n/a | (no upstream) |
    | master | (behind 1) | (ahead 0) | origin/master |
    | tracked-branch | (even) | (even) | origin/tracked-branch |
    # show the current branch
    $ git-branch-status -b
    $ git-branch-status --branch
    | current-branch | (behind 0) | (ahead 2) | origin/current-branch |
    # show a specific branch
    $ git-branch-status specific-branch
    $ git-branch-status -b specific-branch
    $ git-branch-status --branch specific-branch
    | specific-branch | (behind 0) | (ahead 2) | origin/specific-branch |
    # show the timestamp of each HEAD
    $ git-branch-status -d
    $ git-branch-status --dates
    | 1999-12-31 master | (behind 2) | (ahead 0) | 2000-01-01 origin/master |
    # print this usage message
    $ git-branch-status -h
    $ git-branch-status --help
    "prints this usage message"
    # show all branches with timestamps (like -a -d)
    $ git-branch-status -v
    $ git-branch-status --verbose
    | 1999-12-31 local | n/a | n/a | (no upstream) |
    | 1999-12-31 master | (behind 1) | (ahead 0) | 2000-01-01 origin/master |
    | 1999-12-31 tracked | (even) | (even) | 2000-01-01 origin/tracked |
    USAGE


    @@ -99,7 +109,7 @@ function set_filter_or_die # (a_branch_name)
    function get_head_date # (a_commit_ref)
    {
    author_date=$(git log -n 1 --format=format:"%ai" $1 2> /dev/null)
    (($SHOW_DATES)) && [ "$author_date" ] && echo "${author_date:0:10}:"
    (($SHOW_DATES)) && [ "$author_date" ] && echo "${author_date:0:10}$JOIN_CHAR"
    }

    function get_commit_msg # (a_commit_ref)
    @@ -111,11 +121,13 @@ function get_commit_msg # (a_commit_ref)
    ### switches ###

    if [ $1 ] ; then
    if [ "$1" == "-a" -o "$1" == "--all" ] ; then readonly SHOW_ALL=1 ;
    elif [ "$1" == "-b" -o "$1" == "--branch" ] ; then
    if [ "$1" == "-a" -o "$1" == "--all" ] ; then readonly SHOW_ALL=1 ;
    elif [ "$1" == "-b" -o "$1" == "--branch" ] ; then
    if [ $2 ] ; then set_filter_or_die $2 ; else branch=$(current_branch) ; fi ;
    elif [ "$1" == "-d" -o "$1" == "--dates" ] ; then readonly SHOW_DATES=1 ;
    elif [ "$1" == "-h" -o "$1" == "--help" ] ; then echo "$USAGE" ; exit ;
    elif [ "$1" == "-d" -o "$1" == "--dates" ] ; then readonly SHOW_DATES=1 ;
    elif [ "$1" == "-h" -o "$1" == "--help" ] ; then echo "$USAGE" ; exit ;
    elif [ "$1" == "-v" -o "$1" == "--verbose" ]
    then readonly SHOW_ALL=1 ; readonly SHOW_DATES=1 ;
    else set_filter_or_die $1
    fi
    fi
    @@ -222,7 +234,7 @@ done < <(get_refs)
    for (( result_n = 0 ; result_n < ${#local_msgs[@]} ; result_n++ ))
    do
    # fetch data
    local_msg=${local_msgs[$result_n]}
    local_msg=$( echo ${local_msgs[$result_n]} | sed "$JOIN_REGEX" )
    behind_msg=$( echo ${behind_msgs[$result_n]} | sed "$JOIN_REGEX" )
    ahead_msg=$( echo ${ahead_msgs[$result_n]} | sed "$JOIN_REGEX" )
    remote_msg=$( echo ${remote_msgs[$result_n]} | sed "$JOIN_REGEX" )
  2. @bill-auger bill-auger revised this gist Mar 6, 2015. 1 changed file with 10 additions and 8 deletions.
    18 changes: 10 additions & 8 deletions git-branch-status
    Original file line number Diff line number Diff line change
    @@ -136,9 +136,11 @@ readonly CAHEAD=$CYELLOW
    readonly CBEHIND=$CRED
    readonly CEVEN=$CGREEN
    readonly CNOUPSTREAM=$CRED
    readonly JOIN_CHAR='_'
    readonly JOIN_REGEX="s/$JOIN_CHAR/ /"
    readonly STAR="*"
    readonly DELIM="|"
    readonly NO_UPSTREAM="(no-upstream)"
    readonly NO_UPSTREAM="(no${JOIN_CHAR}upstream)"
    readonly NO_RESULTS_MSG="Everything is synchronized"


    @@ -180,12 +182,12 @@ do
    # set data for branches with upstream
    local_color=$CDEFAULT
    if (($n_behind))
    then behind_msg="(behind $n_behind)" ; behind_color=$CBEHIND
    else behind_msg="(even)" ; behind_color=$CEVEN ;
    then behind_msg="(behind$JOIN_CHAR$n_behind)" ; behind_color=$CBEHIND
    else behind_msg="(even)" ; behind_color=$CEVEN ;
    fi
    if (($n_ahead))
    then ahead_msg="(ahead $n_ahead)" ; ahead_color=$CAHEAD ;
    else ahead_msg="(even)" ; ahead_color=$CEVEN ;
    then ahead_msg="(ahead$JOIN_CHAR$n_ahead)" ; ahead_color=$CAHEAD ;
    else ahead_msg="(even)" ; ahead_color=$CEVEN ;
    fi
    remote_color=$CDEFAULT
    elif (($SHOW_ALL_LOCAL)) ; then
    @@ -221,9 +223,9 @@ for (( result_n = 0 ; result_n < ${#local_msgs[@]} ; result_n++ ))
    do
    # fetch data
    local_msg=${local_msgs[$result_n]}
    behind_msg=${behind_msgs[$result_n]}
    ahead_msg=${ahead_msgs[$result_n]}
    remote_msg=${remote_msgs[$result_n]}
    behind_msg=$( echo ${behind_msgs[$result_n]} | sed "$JOIN_REGEX" )
    ahead_msg=$( echo ${ahead_msgs[$result_n]} | sed "$JOIN_REGEX" )
    remote_msg=$( echo ${remote_msgs[$result_n]} | sed "$JOIN_REGEX" )
    local_color="${local_colors[$result_n]}"
    behind_color="${behind_colors[$result_n]}"
    ahead_color="${ahead_colors[$result_n]}"
  3. @bill-auger bill-auger revised this gist Mar 6, 2015. 1 changed file with 5 additions and 4 deletions.
    9 changes: 5 additions & 4 deletions git-branch-status
    Original file line number Diff line number Diff line change
    @@ -12,10 +12,11 @@
    read -r -d '' USAGE <<-'USAGE'
    usage: git-branch-status
    git-branch-status [-a | --all]
    git-branch-status [-b | --branch [branch-name]] [branch-name]
    git-branch-status [-b | --branch] [branch-name]
    git-branch-status [-d | --dates]
    git-branch-status [-h | --help]
    examples:
    examples:
    # show only branches for which upstream HEAD differs from local
    $ git-branch-status
    @@ -84,12 +85,12 @@ function is_current_branch # (a_branch_name)
    function does_branch_exist # (a_branch_name)
    {
    is_known_branch=$(git branch | grep -G "^ $1$") # all but current
    [ $(is_current_branch $1) -o $is_known_branch ] && echo 1 || echo 0
    [ $(is_current_branch $1) -o "$is_known_branch" ] && echo 1 || echo 0
    }

    function set_filter_or_die # (a_branch_name)
    {
    if [ $(does_branch_exist $1) ]
    if (($(does_branch_exist $1)))
    then branch=$1
    else echo "no such branch: '$1'" ; exit ;
    fi
  4. @bill-auger bill-auger revised this gist Mar 6, 2015. 1 changed file with 28 additions and 37 deletions.
    65 changes: 28 additions & 37 deletions git-branch-status
    Original file line number Diff line number Diff line change
    @@ -72,7 +72,13 @@ function current_branch

    function is_current_branch # (a_branch_name)
    {
    if [ "$1" == "$(current_branch)" ] ; then echo 1 ; else echo 0 ; fi ;
    current=$(current_branch)
    if (($SHOW_DATES))
    then this_branch=$(get_head_date $1)$1 ; current=$(get_head_date $current)$current ;
    else this_branch=$1
    fi

    if [ "$this_branch" == "$current" ] ; then echo 1 ; else echo 0 ; fi ;
    }

    function does_branch_exist # (a_branch_name)
    @@ -118,7 +124,7 @@ fi

    readonly SHOW_ALL_LOCAL=$(($SHOW_ALL + 0)) # also show branches that have no upstream
    readonly SHOW_ALL_REMOTE=$(($SHOW_ALL + 0)) # also show branches that are up to date
    readonly MAX_COL_W=27
    readonly MAX_COL_W=27 # should be => 12
    readonly CWHITE='\033[0;37m'
    readonly CGREEN='\033[0;32m'
    readonly CYELLOW='\033[1;33m'
    @@ -160,35 +166,38 @@ do

    # parse local<->remote sync status
    if [ $remote ] ; then
    status=$(get_status)
    [ $(($?)) -eq 0 ] || continue
    status=$(get_status) ; (($?)) && continue ;

    n_behind=$(echo $status | tr " " "\n" | grep -c '^>')
    n_ahead=$( echo $status | tr " " "\n" | grep -c '^<')
    n_differences=$(($n_behind + $n_ahead))
    n_total_differences=$(($n_total_differences + $n_differences))

    # filter branches by status
    [ "$SHOW_ALL_REMOTE" -eq 0 -a "$n_differences" -eq 0 ] && continue
    (($SHOW_ALL_REMOTE)) || (($n_differences)) || continue

    # color output
    # set data for branches with upstream
    local_color=$CDEFAULT
    if [ "$n_behind" -ne 0 ] ; then behind_color=$CBEHIND ; else behind_color=$CEVEN ; fi ;
    if [ "$n_ahead" -ne 0 ] ; then ahead_color=$CAHEAD ; else ahead_color=$CEVEN ; fi ;
    if (($n_behind))
    then behind_msg="(behind $n_behind)" ; behind_color=$CBEHIND
    else behind_msg="(even)" ; behind_color=$CEVEN ;
    fi
    if (($n_ahead))
    then ahead_msg="(ahead $n_ahead)" ; ahead_color=$CAHEAD ;
    else ahead_msg="(even)" ; ahead_color=$CEVEN ;
    fi
    remote_color=$CDEFAULT
    elif [ "$SHOW_ALL_LOCAL" -eq 1 ] ; then
    elif (($SHOW_ALL_LOCAL)) ; then
    # dummy data for branches with no upstream
    local_color=$CDEFAULT
    n_behind="X" ; behind_color="$CDEFAULT" ;
    n_ahead="X" ; ahead_color="$CDEFAULT" ;
    remote="$NO_UPSTREAM" ; remote_color=$CNOUPSTREAM
    behind_msg="n/a" ; behind_color="$CDEFAULT" ;
    ahead_msg="n/a" ; ahead_color="$CDEFAULT" ;
    remote="$NO_UPSTREAM" ; remote_color=$CNOUPSTREAM ;
    else continue
    fi

    # populate lists
    local_msg="$(get_head_date $local)$local" ; local_msg="${local_msg:0:$MAX_COL_W}" ;
    behind_msg="$n_behind"
    ahead_msg="$n_ahead"
    remote_msg="$(get_head_date $remote)$remote" ; remote_msg="${remote_msg:0:$MAX_COL_W}" ;
    local_msgs=( ${local_msgs[@]} "$local_msg" )
    behind_msgs=( ${behind_msgs[@]} "$behind_msg" )
    @@ -204,40 +213,21 @@ do
    if [ ${#behind_msg} -gt $behind_w ] ; then behind_w=${#behind_msg} ; fi ;
    if [ ${#ahead_msg} -gt $ahead_w ] ; then ahead_w=${#ahead_msg} ; fi ;
    if [ ${#remote_msg} -gt $remote_w ] ; then remote_w=${#remote_msg} ; fi ;

    done < <(get_refs)

    # compensate width for dates and "(ahead )" and "(behind )" to be appended
    # local_w=$(( $local_w + 11 ))
    ahead_w=$(( $ahead_w + 8 ))
    behind_w=$(( $behind_w + 9 ))
    # remote_w=$(( $remote_w + 11 ))

    # pretty print results
    for (( result_n = 0 ; result_n < ${#local_msgs[@]} ; result_n++ ))
    do
    # fetch data
    this_branch=${local_msgs[$result_n]}
    n_behind=${behind_msgs[$result_n]}
    n_ahead=${ahead_msgs[$result_n]}
    remote_branch=${remote_msgs[$result_n]}
    local_msg=${local_msgs[$result_n]}
    behind_msg=${behind_msgs[$result_n]}
    ahead_msg=${ahead_msgs[$result_n]}
    remote_msg=${remote_msgs[$result_n]}
    local_color="${local_colors[$result_n]}"
    behind_color="${behind_colors[$result_n]}"
    ahead_color="${ahead_colors[$result_n]}"
    remote_color="${remote_colors[$result_n]}"

    # format data representation
    # echo "this_branch=$this_branch current_branch=$(current_branch)" not_current_branch
    if (($(is_current_branch $this_branch))) ; then star=$STAR ; else star=" " ; fi ;
    local_msg="$this_branch"
    behind_msg="(behind $n_behind)"
    ahead_msg="(ahead $n_ahead)"
    remote_msg="$remote_branch"
    if [ "$behind_msg" == "(behind 0)" ] ; then behind_msg="(even)" ; fi ;
    if [ "$ahead_msg" == "(ahead 0)" ] ; then ahead_msg="(even)" ; fi ;
    if [ "$remote_msg" == "$NO_UPSTREAM" ] ; then behind_msg="n/a" ; fi ;
    if [ "$remote_msg" == "$NO_UPSTREAM" ] ; then ahead_msg="n/a" ; fi ;

    # calculate column offsets
    local_offset=1
    behind_offset=$(( $local_w - ${#local_msg} ))
    @@ -246,6 +236,7 @@ do
    end_offset=$(( $remote_w - ${#remote_msg} ))

    # build output messages and display
    if (($(is_current_branch $local_msg))) ; then star=$STAR ; else star=" " ; fi ;
    local_msg="%$(( $local_offset ))s$star$(echo -e $DELIM $local_color$local_msg$CEND)"
    behind_msg="%$(( $behind_offset ))s $( echo -e $DELIM $behind_color$behind_msg$CEND)"
    ahead_msg="%$(( $ahead_offset ))s $( echo -e $DELIM $ahead_color$ahead_msg$CEND)"
  5. @bill-auger bill-auger revised this gist Mar 4, 2015. 1 changed file with 37 additions and 17 deletions.
    54 changes: 37 additions & 17 deletions git-branch-status
    Original file line number Diff line number Diff line change
    @@ -8,9 +8,6 @@

    # this script prints out pretty git branch sync status reports

    # TODO: add HEAD dates
    # TODO: data header


    read -r -d '' USAGE <<-'USAGE'
    usage: git-branch-status
    @@ -36,13 +33,18 @@ usage: git-branch-status
    # show the current branch
    $ git-branch-status -b
    $ git-branch-status --branch
    | current-branch | (behind 0) | (ahead 2) | origin/current-branch |
    | current-branch | (behind 0) | (ahead 2) | origin/current-branch |
    # show a specific branch
    $ git-branch-status specific-branch
    $ git-branch-status -b specific-branch
    $ git-branch-status --branch specific-branch
    | specific-branch | (behind 0) | (ahead 2) | origin/specific-branch |
    | specific-branch | (behind 0) | (ahead 2) | origin/specific-branch |
    # show the timestamp of each HEAD
    $ git-branch-status -d
    $ git-branch-status --dates
    | 1999-12-31:master | (behind 2) | (ahead 0) | 2000-01-01:origin/master |
    # print this usage message
    $ git-branch-status -h
    @@ -55,42 +57,57 @@ USAGE

    function get_refs
    {
    echo "`git for-each-ref --format="%(refname:short) %(upstream:short)" refs/heads 2> /dev/null`"
    git for-each-ref --format="%(refname:short) %(upstream:short)" refs/heads 2> /dev/null
    }

    function get_status
    {
    git rev-list --left-right ${local}...${remote} -- 2>/dev/null
    }

    function current_branch() { echo $(git rev-parse --abbrev-ref HEAD) ; }
    function current_branch
    {
    git rev-parse --abbrev-ref HEAD
    }

    function is_current_branch()
    function is_current_branch # (a_branch_name)
    {
    if [ "$1" == "$(current_branch)" ] ; then echo 1 ; else echo 0 ; fi ;
    }

    function does_branch_exist()
    function does_branch_exist # (a_branch_name)
    {
    is_known_branch=$(git branch | grep -G "^ $1$")
    is_known_branch=$(git branch | grep -G "^ $1$") # all but current
    [ $(is_current_branch $1) -o $is_known_branch ] && echo 1 || echo 0
    }

    function set_filter_or_die
    function set_filter_or_die # (a_branch_name)
    {
    if [ $(does_branch_exist $1) ]
    then branch=$1
    else echo "no such branch: '$1'" ; exit ;
    fi
    }

    function get_head_date # (a_commit_ref)
    {
    author_date=$(git log -n 1 --format=format:"%ai" $1 2> /dev/null)
    (($SHOW_DATES)) && [ "$author_date" ] && echo "${author_date:0:10}:"
    }

    function get_commit_msg # (a_commit_ref)
    {
    git log -n 1 --format=format:"%s" $1
    }


    ### switches ###

    if [ $1 ] ; then
    if [ "$1" == "-a" -o "$1" == "--all" ] ; then readonly SHOW_ALL=1 ;
    elif [ "$1" == "-b" -o "$1" == "--branch" ] ; then
    if [ $2 ] ; then set_filter_or_die $2 ; else branch=$(current_branch) ; fi ;
    elif [ "$1" == "-d" -o "$1" == "--dates" ] ; then readonly SHOW_DATES=1 ;
    elif [ "$1" == "-h" -o "$1" == "--help" ] ; then echo "$USAGE" ; exit ;
    else set_filter_or_die $1
    fi
    @@ -101,7 +118,7 @@ fi

    readonly SHOW_ALL_LOCAL=$(($SHOW_ALL + 0)) # also show branches that have no upstream
    readonly SHOW_ALL_REMOTE=$(($SHOW_ALL + 0)) # also show branches that are up to date
    readonly MAX_COL_W=25
    readonly MAX_COL_W=27
    readonly CWHITE='\033[0;37m'
    readonly CGREEN='\033[0;32m'
    readonly CYELLOW='\033[1;33m'
    @@ -169,10 +186,10 @@ do
    fi

    # populate lists
    local_msg="${local:0:$MAX_COL_W}"
    local_msg="$(get_head_date $local)$local" ; local_msg="${local_msg:0:$MAX_COL_W}" ;
    behind_msg="$n_behind"
    ahead_msg="$n_ahead"
    remote_msg="${remote:0:$MAX_COL_W}"
    remote_msg="$(get_head_date $remote)$remote" ; remote_msg="${remote_msg:0:$MAX_COL_W}" ;
    local_msgs=( ${local_msgs[@]} "$local_msg" )
    behind_msgs=( ${behind_msgs[@]} "$behind_msg" )
    ahead_msgs=( ${ahead_msgs[@]} "$ahead_msg" )
    @@ -190,9 +207,11 @@ do

    done < <(get_refs)

    # compensate width for "(ahead )" and "(behind )" to be appended
    ahead_w=$(( $ahead_w + 8 ))
    behind_w=$(( $behind_w + 9 ))
    # compensate width for dates and "(ahead )" and "(behind )" to be appended
    # local_w=$(( $local_w + 11 ))
    ahead_w=$(( $ahead_w + 8 ))
    behind_w=$(( $behind_w + 9 ))
    # remote_w=$(( $remote_w + 11 ))

    # pretty print results
    for (( result_n = 0 ; result_n < ${#local_msgs[@]} ; result_n++ ))
    @@ -208,6 +227,7 @@ do
    remote_color="${remote_colors[$result_n]}"

    # format data representation
    # echo "this_branch=$this_branch current_branch=$(current_branch)" not_current_branch
    if (($(is_current_branch $this_branch))) ; then star=$STAR ; else star=" " ; fi ;
    local_msg="$this_branch"
    behind_msg="(behind $n_behind)"
  6. @bill-auger bill-auger revised this gist Mar 4, 2015. 1 changed file with 85 additions and 49 deletions.
    134 changes: 85 additions & 49 deletions git-branch-status
    Original file line number Diff line number Diff line change
    @@ -9,7 +9,7 @@
    # this script prints out pretty git branch sync status reports

    # TODO: add HEAD dates
    # TODO: add * to current branch
    # TODO: data header


    read -r -d '' USAGE <<-'USAGE'
    @@ -29,7 +29,7 @@ usage: git-branch-status
    # show all branches - even those with no upstream and those up-to-date
    $ git-branch-status -a
    $ git-branch-status --all
    | local-branch | n/a | n/a | n/a |
    | local-branch | n/a | n/a | (no upstream) |
    | master | (behind 1) | (ahead 0) | origin/master |
    | tracked-branch | (even) | (even) | origin/tracked-branch |
    @@ -47,7 +47,7 @@ usage: git-branch-status
    # print this usage message
    $ git-branch-status -h
    $ git-branch-status --help
    prints this usage message
    "prints this usage message"
    USAGE


    @@ -65,10 +65,21 @@ function get_status

    function current_branch() { echo $(git rev-parse --abbrev-ref HEAD) ; }

    function is_current_branch()
    {
    if [ "$1" == "$(current_branch)" ] ; then echo 1 ; else echo 0 ; fi ;
    }

    function does_branch_exist()
    {
    is_known_branch=$(git branch | grep -G "^ $1$")
    [ $(is_current_branch $1) -o $is_known_branch ] && echo 1 || echo 0
    }

    function set_filter_or_die
    {
    if [ "$(current_branch)" == "$1" ] || [ $(git branch | grep -G "^ $1$") ] ; then
    branch=$1
    if [ $(does_branch_exist $1) ]
    then branch=$1
    else echo "no such branch: '$1'" ; exit ;
    fi
    }
    @@ -91,30 +102,37 @@ fi
    readonly SHOW_ALL_LOCAL=$(($SHOW_ALL + 0)) # also show branches that have no upstream
    readonly SHOW_ALL_REMOTE=$(($SHOW_ALL + 0)) # also show branches that are up to date
    readonly MAX_COL_W=25
    readonly CWHITE='\033[0;37m'
    readonly CGREEN='\033[0;32m'
    readonly CYELLOW='\033[1;33m'
    readonly CRED='\033[0;31m'
    readonly CEND='\033[0m'
    readonly SPACER="|"
    readonly CDEFAULT=$CWHITE
    readonly CAHEAD=$CYELLOW
    readonly CBEHIND=$CRED
    readonly CEVEN=$CGREEN
    readonly NO_RESULTS_MSG="${CEVEN}Everything is synchronized.$CEND"
    readonly CNOUPSTREAM=$CRED
    readonly STAR="*"
    readonly DELIM="|"
    readonly NO_UPSTREAM="(no-upstream)"
    readonly NO_RESULTS_MSG="Everything is synchronized"


    ### variables ###

    n_total_differences=0
    local_col_w=0
    behind_col_w=0
    ahead_col_w=0
    remote_col_w=0
    local_w=0
    behind_w=0
    ahead_w=0
    remote_w=0
    declare -a local_msgs=()
    declare -a behind_msgs=()
    declare -a ahead_msgs=()
    declare -a remote_msgs=()
    declare -a local_colors=()
    declare -a behind_colors=()
    declare -a ahead_colors=()
    declare -a remote_colors=()


    # loop over all branches
    @@ -137,68 +155,86 @@ do
    [ "$SHOW_ALL_REMOTE" -eq 0 -a "$n_differences" -eq 0 ] && continue

    # color output
    local_color=$CDEFAULT
    if [ "$n_behind" -ne 0 ] ; then behind_color=$CBEHIND ; else behind_color=$CEVEN ; fi ;
    if [ "$n_ahead" -ne 0 ] ; then ahead_color=$CAHEAD ; else ahead_color=$CEVEN ; fi ;
    remote_color=$CDEFAULT
    elif [ "$SHOW_ALL_LOCAL" -eq 1 ] ; then
    # dummy data for locals
    n_behind="X" ; n_ahead="X" ; remote="n/a" ; behind_color="$CEVEN" ; ahead_color="$CEVEN"
    # dummy data for branches with no upstream
    local_color=$CDEFAULT
    n_behind="X" ; behind_color="$CDEFAULT" ;
    n_ahead="X" ; ahead_color="$CDEFAULT" ;
    remote="$NO_UPSTREAM" ; remote_color=$CNOUPSTREAM
    else continue
    fi

    # populate lists
    local=${local:0:$MAX_COL_W} ; remote=${remote:0:$MAX_COL_W} ;
    local_msgs=( ${local_msgs[@]} "$local" )
    behind_msgs=( ${behind_msgs[@]} "$n_behind" )
    ahead_msgs=( ${ahead_msgs[@]} "$n_ahead" )
    remote_msgs=( ${remote_msgs[@]} "$remote" )
    local_msg="${local:0:$MAX_COL_W}"
    behind_msg="$n_behind"
    ahead_msg="$n_ahead"
    remote_msg="${remote:0:$MAX_COL_W}"
    local_msgs=( ${local_msgs[@]} "$local_msg" )
    behind_msgs=( ${behind_msgs[@]} "$behind_msg" )
    ahead_msgs=( ${ahead_msgs[@]} "$ahead_msg" )
    remote_msgs=( ${remote_msgs[@]} "$remote_msg" )
    local_colors=( ${local_colors[@]} "$local_color" )
    behind_colors=( ${behind_colors[@]} "$behind_color" )
    ahead_colors=( ${ahead_colors[@]} "$ahead_color" )
    remote_colors=( ${remote_colors[@]} "$remote_color" )

    # determine max column widths
    if [ ${#local} -gt $local_col_w ] ; then local_col_w=${#local} ; fi ;
    if [ ${#n_behind} -gt $behind_col_w ] ; then behind_col_w=${#n_behind} ; fi ;
    if [ ${#n_ahead} -gt $ahead_col_w ] ; then ahead_col_w=${#n_ahead} ; fi ;
    if [ ${#remote} -gt $remote_col_w ] ; then remote_col_w=${#remote} ; fi ;
    if [ ${#local_msg} -gt $local_w ] ; then local_w=${#local_msg} ; fi ;
    if [ ${#behind_msg} -gt $behind_w ] ; then behind_w=${#behind_msg} ; fi ;
    if [ ${#ahead_msg} -gt $ahead_w ] ; then ahead_w=${#ahead_msg} ; fi ;
    if [ ${#remote_msg} -gt $remote_w ] ; then remote_w=${#remote_msg} ; fi ;

    done < <(get_refs)

    # compensate width for "(behind )" and "(ahead )" to be appended
    behind_col_w=$(( $behind_col_w + 9 ))
    ahead_col_w=$(( $ahead_col_w + 8 ))
    # compensate width for "(ahead )" and "(behind )" to be appended
    ahead_w=$(( $ahead_w + 8 ))
    behind_w=$(( $behind_w + 9 ))

    # pretty print results
    for (( result_n = 0 ; result_n < ${#local_msgs[@]} ; result_n++ ))
    do
    # fetch and filter data
    local_msg="${local_msgs[$result_n]}"
    behind_msg="(behind ${behind_msgs[$result_n]})"
    ahead_msg="(ahead ${ahead_msgs[$result_n]})"
    remote_msg="${remote_msgs[$result_n]}"
    # fetch data
    this_branch=${local_msgs[$result_n]}
    n_behind=${behind_msgs[$result_n]}
    n_ahead=${ahead_msgs[$result_n]}
    remote_branch=${remote_msgs[$result_n]}
    local_color="${local_colors[$result_n]}"
    behind_color="${behind_colors[$result_n]}"
    ahead_color="${ahead_colors[$result_n]}"
    if [ "$remote_msg" == "n/a" ] ; then ahead_msg="n/a" ; ahead_color="" ; fi ;
    if [ "$remote_msg" == "n/a" ] ; then behind_msg="n/a" ; behind_color="" ; fi ;
    if [ "$behind_msg" == "(0 behind)" ] ; then behind_msg="(even)" ; fi ;
    if [ "$ahead_msg" == "(0 ahead)" ] ; then ahead_msg="(even)" ; fi ;
    remote_color="${remote_colors[$result_n]}"

    # format data representation
    if (($(is_current_branch $this_branch))) ; then star=$STAR ; else star=" " ; fi ;
    local_msg="$this_branch"
    behind_msg="(behind $n_behind)"
    ahead_msg="(ahead $n_ahead)"
    remote_msg="$remote_branch"
    if [ "$behind_msg" == "(behind 0)" ] ; then behind_msg="(even)" ; fi ;
    if [ "$ahead_msg" == "(ahead 0)" ] ; then ahead_msg="(even)" ; fi ;
    if [ "$remote_msg" == "$NO_UPSTREAM" ] ; then behind_msg="n/a" ; fi ;
    if [ "$remote_msg" == "$NO_UPSTREAM" ] ; then ahead_msg="n/a" ; fi ;

    # calculate column offsets
    local_col_offset=1
    behind_col_offset=$(( $local_col_w - ${#local_msg} ))
    ahead_col_offset=$(( $behind_col_w - ${#behind_msg} ))
    remote_col_offset=$(( $ahead_col_w - ${#ahead_msg} ))
    end_col_offset=$(( $remote_col_w - ${#remote_msg} ))

    # build output messages and print
    local_msg="%$(($local_col_offset))s $( echo -e $SPACER $local_msg)"
    behind_msg="%$(($behind_col_offset))s $(echo -e $SPACER $behind_color$behind_msg$CEND)"
    ahead_msg="%$(($ahead_col_offset))s $( echo -e $SPACER $ahead_color$ahead_msg$CEND)"
    remote_msg="%$(($remote_col_offset))s $(echo -e $SPACER $remote_msg)"
    end_msg="%$(($end_col_offset))s $SPACER"

    local_offset=1
    behind_offset=$(( $local_w - ${#local_msg} ))
    ahead_offset=$(( $behind_w - ${#behind_msg} ))
    remote_offset=$(( $ahead_w - ${#ahead_msg} ))
    end_offset=$(( $remote_w - ${#remote_msg} ))

    # build output messages and display
    local_msg="%$(( $local_offset ))s$star$(echo -e $DELIM $local_color$local_msg$CEND)"
    behind_msg="%$(( $behind_offset ))s $( echo -e $DELIM $behind_color$behind_msg$CEND)"
    ahead_msg="%$(( $ahead_offset ))s $( echo -e $DELIM $ahead_color$ahead_msg$CEND)"
    remote_msg="%$(( $remote_offset ))s $( echo -e $DELIM $remote_color$remote_msg$CEND)"
    end_msg="%$(( $end_offset ))s $DELIM"
    printf "$local_msg$behind_msg$ahead_msg$remote_msg$end_msg\n"
    done

    # print something if no diffs (and some branches exist in this dir)
    if [ "$n_total_differences" == 0 -a "$(get_refs)" ]
    then echo -e $NO_RESULTS_MSG
    if [ "$n_total_differences" == "0" -a "$(get_refs)" ]
    then echo -e "$CEVEN$NO_RESULTS_MSG$CEND"
    fi
  7. @bill-auger bill-auger revised this gist Mar 4, 2015. 1 changed file with 50 additions and 41 deletions.
    91 changes: 50 additions & 41 deletions git-branch-status
    100644 → 100755
    Original file line number Diff line number Diff line change
    @@ -1,43 +1,53 @@
    #!/bin/bash

    # git-branch-status
    # * originally by http://github.com/jehiah
    # * "s'all good!" message by http://github.com/kd35a
    # * ANSI colors by http://github.com/knovoselic
    # * column formatting and filters by http://github.com/bill-auger
    # * originally by http://github.com/jehiah
    # * "s'all good!" message by http://github.com/kd35a
    # * ANSI colors by http://github.com/knovoselic
    # * column formatting, filters, and usage by http://github.com/bill-auger

    # this script prints out pretty git branch sync status reports

    # TODO: add HEAD dates
    # TODO: add * to current branch


    read -r -d '' USAGE <<-'USAGE'
    usage: git-branch-status
    git-branch-status [-a | --all]
    git-branch-status [-h | --help]
    git-branch-status [-b | --branch [branch-name]] [branch-name]
    git-branch-status [-h | --help]
    examples:
    # show only branches for which upstream HEAD differs from local
    $ git-branch-status
    | dns_check | (ahead 1) | (behind 112) | origin/dns_check |
    | master | (ahead 2) | (behind 0) | origin/master |
    | collab-branch | (behind 1) | (ahead 2) | origin/collab-branch |
    | feature-branch | (behind 0) | (ahead 2) | origin/feature-branch |
    | master | (behind 1) | (ahead 0) | origin/master |
    # show all branches - even those with no upstream and those up-to-date
    $ git-branch-status -a
    $ git-branch-status --all
    | a-local-branch | n/a | n/a | n/a |
    | a-remote-branch | (even) | (even) | origin/a-remote-branch |
    | dns_check | (ahead 1) | (behind 112) | origin/dns_check |
    | master | (ahead 2) | (behind 0) | origin/master |
    | local-branch | n/a | n/a | n/a |
    | master | (behind 1) | (ahead 0) | origin/master |
    | tracked-branch | (even) | (even) | origin/tracked-branch |
    # show the current branch
    $ git-branch-status -b
    $ git-branch-status --branch
    | current-branch | (ahead 2) | (behind 0) | origin/even-branch |
    $ git-branch-status -h
    $ git-branch-status --help
    prints this message
    | current-branch | (behind 0) | (ahead 2) | origin/current-branch |
    # show a specific branch
    $ git-branch-status specific-branch
    $ git-branch-status -b specific-branch
    $ git-branch-status --branch specific-branch
    | specific-branch | (ahead 2) | (behind 0) | origin/even-branch |
    | specific-branch | (behind 0) | (ahead 2) | origin/specific-branch |
    # print this usage message
    $ git-branch-status -h
    $ git-branch-status --help
    prints this usage message
    USAGE


    @@ -67,20 +77,19 @@ function set_filter_or_die
    ### switches ###

    if [ $1 ] ; then
    if [ "$1" == "-h" -o "$1" == "--help" ] ; then echo "$USAGE" ; exit ;
    elif [ "$1" == "-a" -o "$1" == "--all" ] ; then
    readonly SHOW_ALL=1
    if [ "$1" == "-a" -o "$1" == "--all" ] ; then readonly SHOW_ALL=1 ;
    elif [ "$1" == "-b" -o "$1" == "--branch" ] ; then
    if [ $2 ] ; then set_filter_or_die $2 ; else branch=$(current_branch) ; fi ;
    elif [ "$1" == "-h" -o "$1" == "--help" ] ; then echo "$USAGE" ; exit ;
    else set_filter_or_die $1
    fi
    fi


    ### constants ###

    readonly SHOW_ALL_LOCAL=$(($SHOW_ALL + 0)) # also show branches that have no upstream
    readonly SHOW_ALL_REMOTE=$(($SHOW_ALL + 0)) # also show branches that are up to date
    readonly SHOW_ALL_LOCAL=$(($SHOW_ALL + 0)) # also show branches that have no remote counterpart
    readonly MAX_COL_W=25
    readonly CGREEN='\033[0;32m'
    readonly CYELLOW='\033[1;33m'
    @@ -97,15 +106,15 @@ readonly NO_RESULTS_MSG="${CEVEN}Everything is synchronized.$CEND"

    n_total_differences=0
    local_col_w=0
    ahead_col_w=0
    behind_col_w=0
    ahead_col_w=0
    remote_col_w=0
    declare -a local_msgs=()
    declare -a ahead_msgs=()
    declare -a behind_msgs=()
    declare -a ahead_msgs=()
    declare -a remote_msgs=()
    declare -a ahead_colors=()
    declare -a behind_colors=()
    declare -a ahead_colors=()


    # loop over all branches
    @@ -119,74 +128,74 @@ do
    status=$(get_status)
    [ $(($?)) -eq 0 ] || continue

    n_ahead=$( echo $status | tr " " "\n" | grep -c '^<')
    n_behind=$(echo $status | tr " " "\n" | grep -c '^>')
    n_differences=$(($n_ahead + $n_behind))
    n_ahead=$( echo $status | tr " " "\n" | grep -c '^<')
    n_differences=$(($n_behind + $n_ahead))
    n_total_differences=$(($n_total_differences + $n_differences))

    # filter branches by status
    [ "$SHOW_ALL_REMOTE" -eq 0 -a "$n_differences" -eq 0 ] && continue

    # color output
    if [ "$n_ahead" -ne 0 ] ; then ahead_color=$CAHEAD ; else ahead_color=$CEVEN ; fi ;
    if [ "$n_behind" -ne 0 ] ; then behind_color=$CBEHIND ; else behind_color=$CEVEN ; fi ;
    if [ "$n_ahead" -ne 0 ] ; then ahead_color=$CAHEAD ; else ahead_color=$CEVEN ; fi ;
    elif [ "$SHOW_ALL_LOCAL" -eq 1 ] ; then
    # dummy data for locals
    n_ahead="X" ; n_behind="X" ; remote="n/a" ; ahead_color="$CEVEN" ; behind_color="$CEVEN"
    n_behind="X" ; n_ahead="X" ; remote="n/a" ; behind_color="$CEVEN" ; ahead_color="$CEVEN"
    else continue
    fi

    # populate lists
    local=${local:0:$MAX_COL_W} ; remote=${remote:0:$MAX_COL_W} ;
    local_msgs=( ${local_msgs[@]} "$local" )
    ahead_msgs=( ${ahead_msgs[@]} "$n_ahead" )
    behind_msgs=( ${behind_msgs[@]} "$n_behind" )
    ahead_msgs=( ${ahead_msgs[@]} "$n_ahead" )
    remote_msgs=( ${remote_msgs[@]} "$remote" )
    ahead_colors=( ${ahead_colors[@]} "$ahead_color" )
    behind_colors=( ${behind_colors[@]} "$behind_color" )
    ahead_colors=( ${ahead_colors[@]} "$ahead_color" )

    # determine max column widths
    if [ ${#local} -gt $local_col_w ] ; then local_col_w=${#local} ; fi ;
    if [ ${#n_ahead} -gt $ahead_col_w ] ; then ahead_col_w=${#n_ahead} ; fi ;
    if [ ${#n_behind} -gt $behind_col_w ] ; then behind_col_w=${#n_behind} ; fi ;
    if [ ${#n_ahead} -gt $ahead_col_w ] ; then ahead_col_w=${#n_ahead} ; fi ;
    if [ ${#remote} -gt $remote_col_w ] ; then remote_col_w=${#remote} ; fi ;

    done < <(get_refs)

    # compensate for "(ahead )" and "(behind )" to be appended
    ahead_col_w=$(( $ahead_col_w + 8 ))
    # compensate width for "(behind )" and "(ahead )" to be appended
    behind_col_w=$(( $behind_col_w + 9 ))
    ahead_col_w=$(( $ahead_col_w + 8 ))

    # pretty print results
    for (( result_n = 0 ; result_n < ${#local_msgs[@]} ; result_n++ ))
    do
    # fetch and filter data
    local_msg="${local_msgs[$result_n]}"
    ahead_msg="(ahead ${ahead_msgs[$result_n]})"
    behind_msg="(behind ${behind_msgs[$result_n]})"
    ahead_msg="(ahead ${ahead_msgs[$result_n]})"
    remote_msg="${remote_msgs[$result_n]}"
    ahead_color="${ahead_colors[$result_n]}"
    behind_color="${behind_colors[$result_n]}"
    ahead_color="${ahead_colors[$result_n]}"
    if [ "$remote_msg" == "n/a" ] ; then ahead_msg="n/a" ; ahead_color="" ; fi ;
    if [ "$remote_msg" == "n/a" ] ; then behind_msg="n/a" ; behind_color="" ; fi ;
    if [ "$ahead_msg" == "(0 ahead)" ] ; then ahead_msg="(even)" ; fi ;
    if [ "$behind_msg" == "(0 behind)" ] ; then behind_msg="(even)" ; fi ;
    if [ "$ahead_msg" == "(0 ahead)" ] ; then ahead_msg="(even)" ; fi ;

    # calculate column offsets
    local_col_offset=1
    ahead_col_offset=$(( $local_col_w - ${#local_msg} ))
    behind_col_offset=$(( $ahead_col_w - ${#ahead_msg} ))
    remote_col_offset=$(( $behind_col_w - ${#behind_msg} ))
    behind_col_offset=$(( $local_col_w - ${#local_msg} ))
    ahead_col_offset=$(( $behind_col_w - ${#behind_msg} ))
    remote_col_offset=$(( $ahead_col_w - ${#ahead_msg} ))
    end_col_offset=$(( $remote_col_w - ${#remote_msg} ))

    # build output messages and print
    local_msg="%$(($local_col_offset))s $( echo -e $SPACER $local_msg)"
    ahead_msg="%$(($ahead_col_offset))s $( echo -e $SPACER $ahead_color$ahead_msg$CEND)"
    behind_msg="%$(($behind_col_offset))s $(echo -e $SPACER $behind_color$behind_msg$CEND)"
    ahead_msg="%$(($ahead_col_offset))s $( echo -e $SPACER $ahead_color$ahead_msg$CEND)"
    remote_msg="%$(($remote_col_offset))s $(echo -e $SPACER $remote_msg)"
    end_msg="%$(($end_col_offset))s $SPACER"

    printf "$local_msg$ahead_msg$behind_msg$remote_msg$end_msg\n"
    printf "$local_msg$behind_msg$ahead_msg$remote_msg$end_msg\n"
    done

    # print something if no diffs (and some branches exist in this dir)
  8. @bill-auger bill-auger revised this gist Nov 4, 2014. 1 changed file with 17 additions and 5 deletions.
    22 changes: 17 additions & 5 deletions git-branch-status
    Original file line number Diff line number Diff line change
    @@ -43,7 +43,17 @@ USAGE

    ### helpers ###

    function current_branch() { echo $(git rev-parse --abbrev-ref HEAD) ; }
    function get_refs
    {
    echo "`git for-each-ref --format="%(refname:short) %(upstream:short)" refs/heads 2> /dev/null`"
    }

    function get_status
    {
    git rev-list --left-right ${local}...${remote} -- 2>/dev/null
    }

    function current_branch() { echo $(git rev-parse --abbrev-ref HEAD) ; }

    function set_filter_or_die
    {
    @@ -106,7 +116,7 @@ do

    # parse local<->remote sync status
    if [ $remote ] ; then
    status=$(git rev-list --left-right ${local}...${remote} -- 2>/dev/null)
    status=$(get_status)
    [ $(($?)) -eq 0 ] || continue

    n_ahead=$( echo $status | tr " " "\n" | grep -c '^<')
    @@ -141,7 +151,7 @@ do
    if [ ${#n_behind} -gt $behind_col_w ] ; then behind_col_w=${#n_behind} ; fi ;
    if [ ${#remote} -gt $remote_col_w ] ; then remote_col_w=${#remote} ; fi ;

    done < <(git for-each-ref --format="%(refname:short) %(upstream:short)" refs/heads)
    done < <(get_refs)

    # compensate for "(ahead )" and "(behind )" to be appended
    ahead_col_w=$(( $ahead_col_w + 8 ))
    @@ -179,5 +189,7 @@ do
    printf "$local_msg$ahead_msg$behind_msg$remote_msg$end_msg\n"
    done

    # print something if no diffs
    if [ "$n_total_differences" == 0 ] ; then echo -e $NO_RESULTS_MSG ; fi ;
    # print something if no diffs (and some branches exist in this dir)
    if [ "$n_total_differences" == 0 -a "$(get_refs)" ]
    then echo -e $NO_RESULTS_MSG
    fi
  9. @bill-auger bill-auger revised this gist Nov 3, 2014. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion git-branch-status
    Original file line number Diff line number Diff line change
    @@ -14,6 +14,8 @@ usage: git-branch-status
    git-branch-status [-h | --help]
    git-branch-status [-b | --branch [branch-name]] [branch-name]
    examples:
    $ git-branch-status
    | dns_check | (ahead 1) | (behind 112) | origin/dns_check |
    | master | (ahead 2) | (behind 0) | origin/master |
    @@ -55,7 +57,7 @@ function set_filter_or_die
    ### switches ###

    if [ $1 ] ; then
    if [ "$1" == "-h" -o "$1" == "--help" ] ; then echo $USAGE ; exit ;
    if [ "$1" == "-h" -o "$1" == "--help" ] ; then echo "$USAGE" ; exit ;
    elif [ "$1" == "-a" -o "$1" == "--all" ] ; then
    readonly SHOW_ALL=1
    elif [ "$1" == "-b" -o "$1" == "--branch" ] ; then
  10. @bill-auger bill-auger revised this gist Nov 3, 2014. 1 changed file with 18 additions and 18 deletions.
    36 changes: 18 additions & 18 deletions git-branch-status
    Original file line number Diff line number Diff line change
    @@ -8,9 +8,7 @@
    # this script prints out pretty git branch sync status reports


    ### constants ###

    readonly USAGE=<<USAGE
    read -r -d '' USAGE <<-'USAGE'
    usage: git-branch-status
    git-branch-status [-a | --all]
    git-branch-status [-h | --help]
    @@ -41,6 +39,19 @@ usage: git-branch-status
    USAGE


    ### helpers ###

    function current_branch() { echo $(git rev-parse --abbrev-ref HEAD) ; }

    function set_filter_or_die
    {
    if [ "$(current_branch)" == "$1" ] || [ $(git branch | grep -G "^ $1$") ] ; then
    branch=$1
    else echo "no such branch: '$1'" ; exit ;
    fi
    }


    ### switches ###

    if [ $1 ] ; then
    @@ -54,6 +65,8 @@ if [ $1 ] ; then
    fi


    ### constants ###

    readonly SHOW_ALL_REMOTE=$(($SHOW_ALL + 0)) # also show branches that are up to date
    readonly SHOW_ALL_LOCAL=$(($SHOW_ALL + 0)) # also show branches that have no remote counterpart
    readonly MAX_COL_W=25
    @@ -83,19 +96,6 @@ declare -a ahead_colors=()
    declare -a behind_colors=()


    ### helpers ###

    function current_branch() { echo $(git rev-parse --abbrev-ref HEAD) ; }

    function set_filter_or_die
    {
    if [ "$(current_branch)" == "$1" ] || [ $(git branch | grep -G "^ $1$") ] ; then
    branch=$1
    else echo "no such branch: '$1'" ; exit ;
    fi
    }


    # loop over all branches
    while read local remote
    do
    @@ -142,8 +142,8 @@ do
    done < <(git for-each-ref --format="%(refname:short) %(upstream:short)" refs/heads)

    # compensate for "(ahead )" and "(behind )" to be appended
    ahead_col_w=$(( $ahead_col_w + 8 ))
    behind_col_w=$(( $behind_col_w + 10 ))
    ahead_col_w=$(( $ahead_col_w + 8 ))
    behind_col_w=$(( $behind_col_w + 9 ))

    # pretty print results
    for (( result_n = 0 ; result_n < ${#local_msgs[@]} ; result_n++ ))
  11. @bill-auger bill-auger revised this gist Nov 2, 2014. 1 changed file with 26 additions and 17 deletions.
    43 changes: 26 additions & 17 deletions git-branch-status
    Original file line number Diff line number Diff line change
    @@ -8,7 +8,9 @@
    # this script prints out pretty git branch sync status reports


    USAGE=<<USAGE
    ### constants ###

    readonly USAGE=<<USAGE
    usage: git-branch-status
    git-branch-status [-a | --all]
    git-branch-status [-h | --help]
    @@ -39,16 +41,7 @@ usage: git-branch-status
    USAGE


    # switches
    function current_branch() { echo $(git rev-parse --abbrev-ref HEAD) ; }

    function set_filter_or_die
    {
    if [ "$(current_branch)" == "$1" ] || [ $(git branch | grep -G "^ $1$") ] ; then
    branch=$1
    else echo "no such branch: '$1'" ; exit ;
    fi
    }
    ### switches ###

    if [ $1 ] ; then
    if [ "$1" == "-h" -o "$1" == "--help" ] ; then echo $USAGE ; exit ;
    @@ -61,9 +54,9 @@ if [ $1 ] ; then
    fi


    # constants
    readonly SHOW_ALL_REMOTE=$(($SHOW_ALL + 0)) # also show branches that are up to date
    readonly SHOW_ALL_LOCAL=$(($SHOW_ALL + 0)) # also show branches that have no remote counterpart
    readonly MAX_COL_W=25
    readonly CGREEN='\033[0;32m'
    readonly CYELLOW='\033[1;33m'
    readonly CRED='\033[0;31m'
    @@ -75,7 +68,8 @@ readonly CEVEN=$CGREEN
    readonly NO_RESULTS_MSG="${CEVEN}Everything is synchronized.$CEND"


    # variables
    ### variables ###

    n_total_differences=0
    local_col_w=0
    ahead_col_w=0
    @@ -89,16 +83,30 @@ declare -a ahead_colors=()
    declare -a behind_colors=()


    ### helpers ###

    function current_branch() { echo $(git rev-parse --abbrev-ref HEAD) ; }

    function set_filter_or_die
    {
    if [ "$(current_branch)" == "$1" ] || [ $(git branch | grep -G "^ $1$") ] ; then
    branch=$1
    else echo "no such branch: '$1'" ; exit ;
    fi
    }


    # loop over all branches
    while read local remote
    do
    # filter branches by name
    [ $branch ] && [ "$branch" != "$local" ] && continue

    # parse local<->remote sync status
    if [ ! -z "$remote" ] ; then
    if [ $remote ] ; then
    status=$(git rev-list --left-right ${local}...${remote} -- 2>/dev/null)
    [ $(($?)) -eq 0 ] || continue

    n_ahead=$( echo $status | tr " " "\n" | grep -c '^<')
    n_behind=$(echo $status | tr " " "\n" | grep -c '^>')
    n_differences=$(($n_ahead + $n_behind))
    @@ -111,11 +119,13 @@ do
    if [ "$n_ahead" -ne 0 ] ; then ahead_color=$CAHEAD ; else ahead_color=$CEVEN ; fi ;
    if [ "$n_behind" -ne 0 ] ; then behind_color=$CBEHIND ; else behind_color=$CEVEN ; fi ;
    elif [ "$SHOW_ALL_LOCAL" -eq 1 ] ; then
    # dummy data for locals
    n_ahead="X" ; n_behind="X" ; remote="n/a" ; ahead_color="$CEVEN" ; behind_color="$CEVEN"
    else continue
    fi

    # populate lists
    local=${local:0:$MAX_COL_W} ; remote=${remote:0:$MAX_COL_W} ;
    local_msgs=( ${local_msgs[@]} "$local" )
    ahead_msgs=( ${ahead_msgs[@]} "$n_ahead" )
    behind_msgs=( ${behind_msgs[@]} "$n_behind" )
    @@ -131,7 +141,6 @@ do

    done < <(git for-each-ref --format="%(refname:short) %(upstream:short)" refs/heads)


    # compensate for "(ahead )" and "(behind )" to be appended
    ahead_col_w=$(( $ahead_col_w + 8 ))
    behind_col_w=$(( $behind_col_w + 10 ))
    @@ -159,8 +168,8 @@ do
    end_col_offset=$(( $remote_col_w - ${#remote_msg} ))

    # build output messages and print
    local_msg="%$(($local_col_offset))s $(echo -e $SPACER $local_msg)"
    ahead_msg="%$(($ahead_col_offset))s $(echo -e $SPACER $ahead_color$ahead_msg$CEND)"
    local_msg="%$(($local_col_offset))s $( echo -e $SPACER $local_msg)"
    ahead_msg="%$(($ahead_col_offset))s $( echo -e $SPACER $ahead_color$ahead_msg$CEND)"
    behind_msg="%$(($behind_col_offset))s $(echo -e $SPACER $behind_color$behind_msg$CEND)"
    remote_msg="%$(($remote_col_offset))s $(echo -e $SPACER $remote_msg)"
    end_msg="%$(($end_col_offset))s $SPACER"
  12. @bill-auger bill-auger revised this gist Oct 31, 2014. 1 changed file with 13 additions and 74 deletions.
    87 changes: 13 additions & 74 deletions git-branch-status
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,5 @@
    #!/bin/bash
    # git-branch-status DEBUG
    # git-branch-status
    # * originally by http://github.com/jehiah
    # * "s'all good!" message by http://github.com/kd35a
    # * ANSI colors by http://github.com/knovoselic
    @@ -51,8 +51,8 @@ function set_filter_or_die
    }

    if [ $1 ] ; then
    if [ "$1" == "-h" -o "$1" == "--help" ] ; then echo $USAGE ; exit ;
    elif [ "$1" == "-a" -o "$1" == "--all" ] ; then
    if [ "$1" == "-h" -o "$1" == "--help" ] ; then echo $USAGE ; exit ;
    elif [ "$1" == "-a" -o "$1" == "--all" ] ; then
    readonly SHOW_ALL=1
    elif [ "$1" == "-b" -o "$1" == "--branch" ] ; then
    if [ $2 ] ; then set_filter_or_die $2 ; else branch=$(current_branch) ; fi ;
    @@ -89,31 +89,21 @@ declare -a ahead_colors=()
    declare -a behind_colors=()


    # if [ $SHOW_ALL_REMOTE -eq 1 ] ; then echo "show diffs" ; else echo "no diffs" ; fi ;
    # if [ $SHOW_ALL_LOCAL -eq 1 ] ; then echo "show locals" ; else echo "no locals" ; fi ;


    # loop over all branches
    while read local remote
    do
    # echo ; echo "$local <-> $remote IN"
    # if [ $branch ] && [ "$branch" != "$local" ] ; then echo "skipping branch '$local'" ; fi ;
    # if [ ! -z "$remote" ] ; then echo "has remote" ; else echo "no remote - bailing" ; fi ;

    # filter branches by name
    [ $branch ] && [ "$branch" != "$local" ] && continue

    # parse local<->remote sync status
    if [ ! -z "$remote" ] ; then
    status=$(git rev-list --left-right ${local}...${remote} -- 2>/dev/null)
    [ $(($?)) -eq 0 ] || continue
    n_ahead=$(echo $status | tr " " "\n" | grep -c '^<')
    n_ahead=$( echo $status | tr " " "\n" | grep -c '^<')
    n_behind=$(echo $status | tr " " "\n" | grep -c '^>')
    n_differences=$(($n_ahead + $n_behind))
    n_total_differences=$(($n_total_differences + $n_differences))

    # echo "SHOW_ALL_REMOTE=$SHOW_ALL_REMOTE n_ahead=$n_ahead n_behind=$n_behind n_total_differences =$n_total_differences"

    # filter branches by status
    [ "$SHOW_ALL_REMOTE" -eq 0 -a "$n_differences" -eq 0 ] && continue

    @@ -133,10 +123,6 @@ do
    ahead_colors=( ${ahead_colors[@]} "$ahead_color" )
    behind_colors=( ${behind_colors[@]} "$behind_color" )

    # echo "$local <-> $remote OUT"
    # echo "col_ws IN=[ ${#local} ${#n_ahead} ${#n_behind} ${#remote} ]"
    # echo "msg=*$local*$n_ahead*$n_behind*$remote*"

    # determine max column widths
    if [ ${#local} -gt $local_col_w ] ; then local_col_w=${#local} ; fi ;
    if [ ${#n_ahead} -gt $ahead_col_w ] ; then ahead_col_w=${#n_ahead} ; fi ;
    @@ -145,34 +131,14 @@ do

    done < <(git for-each-ref --format="%(refname:short) %(upstream:short)" refs/heads)

    # echo "n_results=${#local_msgs[@]}"

    # compensate for "(ahead )" and "(behind )" to be appended
    ahead_col_w=$(($ahead_col_w + 8))
    behind_col_w=$(($behind_col_w + 10))
    ahead_col_w=$(( $ahead_col_w + 8 ))
    behind_col_w=$(( $behind_col_w + 10 ))

    # pretty print results
    for (( result_n = 0 ; result_n < ${#local_msgs[@]} ; result_n++ ))
    do
    # echo

    # pad "( 9 ahead)" like "( 99 ahead)" like "(999 ahead)"
    # ahead_pad_w=$(($ahead_col_w - ${#ahead_msgs[$result_n]} - 8))
    # behind_pad_w=$(($behind_col_w - ${#behind_msgs[$result_n]} - 9))
    # ahead_pad="'%"$ahead_pad_w"s'"
    # behind_pad="'%"$behind_pad_w"s'"
    # # echo "ahead_pad=$ahead_pad ahead_pad_w=$ahead_pad_w"
    # # echo "behind_pad_w=$behind_pad_w"

    # ahead_msg=$(printf "(${ahead_msgs[$result_n]} "$ahead_pad"ahead)")
    # behind_msg=$(printf "(${behind_msgs[$result_n]} "$behind_pad"behind)")
    # echo "'$head_msg' head_msg_len=${#head_msg}"
    # echo "'${ahead_msg}' ahead_msg_len=${#ahead_msg}"

    # behind_col_offset=$(($ahead_col_w - ${#ahead_msg} - 8 - $ahead_pad_w))
    # remote_col_offset=$(($behind_col_w - ${#behind_msg} - 9 - $behind_pad_w))
    # ahead_msg="("$ahead_pad" $ahead_msg ahead)"
    # behind_msg="("$behind_pad"$behind_msg behind)"

    # fetch and filter data
    local_msg="${local_msgs[$result_n]}"
    ahead_msg="(ahead ${ahead_msgs[$result_n]})"
    @@ -185,47 +151,20 @@ do
    if [ "$ahead_msg" == "(0 ahead)" ] ; then ahead_msg="(even)" ; fi ;
    if [ "$behind_msg" == "(0 behind)" ] ; then behind_msg="(even)" ; fi ;

    # echo "local_msg='${local_msgs[$result_n]}'"
    # echo "ahead_msg='${ahead_msgs[$result_n]}'"
    # echo "behind_msg='${behind_msgs[$result_n]}'"
    # echo "remote_msgs='${remote_msgs[$result_n]}'"

    # echo "local_msg IN='$local_msg' (${#local_msg})"
    # echo "ahead_msg IN='$ahead_msg' (${#ahead_msg})"
    # echo "behind_msg IN='$behind_msg' (${#behind_msg})"
    # echo "remote_msgs IN='$remote_msg' (${#remote_msg})"

    # echo "ahead_color=$ahead_color"
    # echo "behind_color=$behind_color"

    # calculate column offsets
    local_col_offset=1
    ahead_col_offset=$(($local_col_w - ${#local_msg}))
    behind_col_offset=$(($ahead_col_w - ${#ahead_msg}))
    remote_col_offset=$(($behind_col_w - ${#behind_msg}))
    end_col_offset=$(($remote_col_w - ${#remote_msg}))

    # echo "local_col_offset =$local_col_w - ${#local_msg} = $ahead_col_offset"
    # echo "ahead_col_offset =$ahead_col_w - ${#ahead_msg} = $behind_col_offset"
    # echo "remote_col_offset=$behind_col_w - ${#behind_msg} = $remote_col_offset"
    # echo "end_col_offset =$remote_col_w - ${#remote_msg} = $end_col_offset"
    # echo "col_ws OUT=[ $local_col_w $ahead_col_w $behind_col_w $remote_col_w ]"
    # echo "this_w OUT=[ ${#local_msg} ${#ahead_msg} ${#behind_msg} ${#remote_msg} ]"
    # echo "offsets =[ $ahead_col_offset $behind_col_offset $remote_col_offset $end_col_offset ]"
    ahead_col_offset=$(( $local_col_w - ${#local_msg} ))
    behind_col_offset=$(( $ahead_col_w - ${#ahead_msg} ))
    remote_col_offset=$(( $behind_col_w - ${#behind_msg} ))
    end_col_offset=$(( $remote_col_w - ${#remote_msg} ))

    # build output messages and print
    local_msg="%$(($local_col_offset))s $(echo -e $SPACER $local_msg)"
    ahead_msg="%$(($ahead_col_offset))s $(echo -e $SPACER $ahead_color$ahead_msg$CEND)"
    local_msg="%$(($local_col_offset))s $(echo -e $SPACER $local_msg)"
    ahead_msg="%$(($ahead_col_offset))s $(echo -e $SPACER $ahead_color$ahead_msg$CEND)"
    behind_msg="%$(($behind_col_offset))s $(echo -e $SPACER $behind_color$behind_msg$CEND)"
    remote_msg="%$(($remote_col_offset))s $(echo -e $SPACER $remote_msg)"
    end_msg="%$(($end_col_offset))s $SPACER"

    # echo "local_msg OUT='$local_msg'"
    # echo "ahead_msg OUT='$ahead_msg'"
    # echo "behind_msg OUT='$behind_msg'"
    # echo "remote_msgs OUT='$remote_msg'"
    # echo "msg=*$local_msg}*$ahead_msg}*$behind_msg}*$remote_msg}*"

    printf "$local_msg$ahead_msg$behind_msg$remote_msg$end_msg\n"
    done

  13. @bill-auger bill-auger revised this gist Oct 31, 2014. 1 changed file with 228 additions and 13 deletions.
    241 changes: 228 additions & 13 deletions git-branch-status
    Original file line number Diff line number Diff line change
    @@ -1,18 +1,233 @@
    #!/bin/bash
    # by http://github.com/jehiah
    # this prints out some branch status (similar to the '... ahead' info you get from git status)
    # git-branch-status DEBUG
    # * originally by http://github.com/jehiah
    # * "s'all good!" message by http://github.com/kd35a
    # * ANSI colors by http://github.com/knovoselic
    # * column formatting and filters by http://github.com/bill-auger

    # example:
    # $ git branch-status
    # dns_check (ahead 1) | (behind 112) origin/master
    # master (ahead 2) | (behind 0) origin/master
    # this script prints out pretty git branch sync status reports

    git for-each-ref --format="%(refname:short) %(upstream:short)" refs/heads | \

    USAGE=<<USAGE
    usage: git-branch-status
    git-branch-status [-a | --all]
    git-branch-status [-h | --help]
    git-branch-status [-b | --branch [branch-name]] [branch-name]
    $ git-branch-status
    | dns_check | (ahead 1) | (behind 112) | origin/dns_check |
    | master | (ahead 2) | (behind 0) | origin/master |
    $ git-branch-status --all
    | a-local-branch | n/a | n/a | n/a |
    | a-remote-branch | (even) | (even) | origin/a-remote-branch |
    | dns_check | (ahead 1) | (behind 112) | origin/dns_check |
    | master | (ahead 2) | (behind 0) | origin/master |
    $ git-branch-status -b
    $ git-branch-status --branch
    | current-branch | (ahead 2) | (behind 0) | origin/even-branch |
    $ git-branch-status -h
    $ git-branch-status --help
    prints this message
    $ git-branch-status specific-branch
    $ git-branch-status -b specific-branch
    $ git-branch-status --branch specific-branch
    | specific-branch | (ahead 2) | (behind 0) | origin/even-branch |
    USAGE


    # switches
    function current_branch() { echo $(git rev-parse --abbrev-ref HEAD) ; }

    function set_filter_or_die
    {
    if [ "$(current_branch)" == "$1" ] || [ $(git branch | grep -G "^ $1$") ] ; then
    branch=$1
    else echo "no such branch: '$1'" ; exit ;
    fi
    }

    if [ $1 ] ; then
    if [ "$1" == "-h" -o "$1" == "--help" ] ; then echo $USAGE ; exit ;
    elif [ "$1" == "-a" -o "$1" == "--all" ] ; then
    readonly SHOW_ALL=1
    elif [ "$1" == "-b" -o "$1" == "--branch" ] ; then
    if [ $2 ] ; then set_filter_or_die $2 ; else branch=$(current_branch) ; fi ;
    else set_filter_or_die $1
    fi
    fi


    # constants
    readonly SHOW_ALL_REMOTE=$(($SHOW_ALL + 0)) # also show branches that are up to date
    readonly SHOW_ALL_LOCAL=$(($SHOW_ALL + 0)) # also show branches that have no remote counterpart
    readonly CGREEN='\033[0;32m'
    readonly CYELLOW='\033[1;33m'
    readonly CRED='\033[0;31m'
    readonly CEND='\033[0m'
    readonly SPACER="|"
    readonly CAHEAD=$CYELLOW
    readonly CBEHIND=$CRED
    readonly CEVEN=$CGREEN
    readonly NO_RESULTS_MSG="${CEVEN}Everything is synchronized.$CEND"


    # variables
    n_total_differences=0
    local_col_w=0
    ahead_col_w=0
    behind_col_w=0
    remote_col_w=0
    declare -a local_msgs=()
    declare -a ahead_msgs=()
    declare -a behind_msgs=()
    declare -a remote_msgs=()
    declare -a ahead_colors=()
    declare -a behind_colors=()


    # if [ $SHOW_ALL_REMOTE -eq 1 ] ; then echo "show diffs" ; else echo "no diffs" ; fi ;
    # if [ $SHOW_ALL_LOCAL -eq 1 ] ; then echo "show locals" ; else echo "no locals" ; fi ;


    # loop over all branches
    while read local remote
    do
    [ -z "$remote" ] && continue
    git rev-list --left-right ${local}...${remote} -- 2>/dev/null >/tmp/git_upstream_status_delta || continue
    LEFT_AHEAD=$(grep -c '^<' /tmp/git_upstream_status_delta)
    RIGHT_AHEAD=$(grep -c '^>' /tmp/git_upstream_status_delta)
    echo "$local (ahead $LEFT_AHEAD) | (behind $RIGHT_AHEAD) $remote"
    done
    # echo ; echo "$local <-> $remote IN"
    # if [ $branch ] && [ "$branch" != "$local" ] ; then echo "skipping branch '$local'" ; fi ;
    # if [ ! -z "$remote" ] ; then echo "has remote" ; else echo "no remote - bailing" ; fi ;

    # filter branches by name
    [ $branch ] && [ "$branch" != "$local" ] && continue

    # parse local<->remote sync status
    if [ ! -z "$remote" ] ; then
    status=$(git rev-list --left-right ${local}...${remote} -- 2>/dev/null)
    [ $(($?)) -eq 0 ] || continue
    n_ahead=$(echo $status | tr " " "\n" | grep -c '^<')
    n_behind=$(echo $status | tr " " "\n" | grep -c '^>')
    n_differences=$(($n_ahead + $n_behind))
    n_total_differences=$(($n_total_differences + $n_differences))

    # echo "SHOW_ALL_REMOTE=$SHOW_ALL_REMOTE n_ahead=$n_ahead n_behind=$n_behind n_total_differences =$n_total_differences"

    # filter branches by status
    [ "$SHOW_ALL_REMOTE" -eq 0 -a "$n_differences" -eq 0 ] && continue

    # color output
    if [ "$n_ahead" -ne 0 ] ; then ahead_color=$CAHEAD ; else ahead_color=$CEVEN ; fi ;
    if [ "$n_behind" -ne 0 ] ; then behind_color=$CBEHIND ; else behind_color=$CEVEN ; fi ;
    elif [ "$SHOW_ALL_LOCAL" -eq 1 ] ; then
    n_ahead="X" ; n_behind="X" ; remote="n/a" ; ahead_color="$CEVEN" ; behind_color="$CEVEN"
    else continue
    fi

    # populate lists
    local_msgs=( ${local_msgs[@]} "$local" )
    ahead_msgs=( ${ahead_msgs[@]} "$n_ahead" )
    behind_msgs=( ${behind_msgs[@]} "$n_behind" )
    remote_msgs=( ${remote_msgs[@]} "$remote" )
    ahead_colors=( ${ahead_colors[@]} "$ahead_color" )
    behind_colors=( ${behind_colors[@]} "$behind_color" )

    # echo "$local <-> $remote OUT"
    # echo "col_ws IN=[ ${#local} ${#n_ahead} ${#n_behind} ${#remote} ]"
    # echo "msg=*$local*$n_ahead*$n_behind*$remote*"

    # determine max column widths
    if [ ${#local} -gt $local_col_w ] ; then local_col_w=${#local} ; fi ;
    if [ ${#n_ahead} -gt $ahead_col_w ] ; then ahead_col_w=${#n_ahead} ; fi ;
    if [ ${#n_behind} -gt $behind_col_w ] ; then behind_col_w=${#n_behind} ; fi ;
    if [ ${#remote} -gt $remote_col_w ] ; then remote_col_w=${#remote} ; fi ;

    done < <(git for-each-ref --format="%(refname:short) %(upstream:short)" refs/heads)

    # echo "n_results=${#local_msgs[@]}"
    # compensate for "(ahead )" and "(behind )" to be appended
    ahead_col_w=$(($ahead_col_w + 8))
    behind_col_w=$(($behind_col_w + 10))

    # pretty print results
    for (( result_n = 0 ; result_n < ${#local_msgs[@]} ; result_n++ ))
    do
    # echo

    # pad "( 9 ahead)" like "( 99 ahead)" like "(999 ahead)"
    # ahead_pad_w=$(($ahead_col_w - ${#ahead_msgs[$result_n]} - 8))
    # behind_pad_w=$(($behind_col_w - ${#behind_msgs[$result_n]} - 9))
    # ahead_pad="'%"$ahead_pad_w"s'"
    # behind_pad="'%"$behind_pad_w"s'"
    # # echo "ahead_pad=$ahead_pad ahead_pad_w=$ahead_pad_w"
    # # echo "behind_pad_w=$behind_pad_w"

    # ahead_msg=$(printf "(${ahead_msgs[$result_n]} "$ahead_pad"ahead)")
    # behind_msg=$(printf "(${behind_msgs[$result_n]} "$behind_pad"behind)")
    # echo "'$head_msg' head_msg_len=${#head_msg}"
    # echo "'${ahead_msg}' ahead_msg_len=${#ahead_msg}"

    # behind_col_offset=$(($ahead_col_w - ${#ahead_msg} - 8 - $ahead_pad_w))
    # remote_col_offset=$(($behind_col_w - ${#behind_msg} - 9 - $behind_pad_w))
    # ahead_msg="("$ahead_pad" $ahead_msg ahead)"
    # behind_msg="("$behind_pad"$behind_msg behind)"

    # fetch and filter data
    local_msg="${local_msgs[$result_n]}"
    ahead_msg="(ahead ${ahead_msgs[$result_n]})"
    behind_msg="(behind ${behind_msgs[$result_n]})"
    remote_msg="${remote_msgs[$result_n]}"
    ahead_color="${ahead_colors[$result_n]}"
    behind_color="${behind_colors[$result_n]}"
    if [ "$remote_msg" == "n/a" ] ; then ahead_msg="n/a" ; ahead_color="" ; fi ;
    if [ "$remote_msg" == "n/a" ] ; then behind_msg="n/a" ; behind_color="" ; fi ;
    if [ "$ahead_msg" == "(0 ahead)" ] ; then ahead_msg="(even)" ; fi ;
    if [ "$behind_msg" == "(0 behind)" ] ; then behind_msg="(even)" ; fi ;

    # echo "local_msg='${local_msgs[$result_n]}'"
    # echo "ahead_msg='${ahead_msgs[$result_n]}'"
    # echo "behind_msg='${behind_msgs[$result_n]}'"
    # echo "remote_msgs='${remote_msgs[$result_n]}'"

    # echo "local_msg IN='$local_msg' (${#local_msg})"
    # echo "ahead_msg IN='$ahead_msg' (${#ahead_msg})"
    # echo "behind_msg IN='$behind_msg' (${#behind_msg})"
    # echo "remote_msgs IN='$remote_msg' (${#remote_msg})"

    # echo "ahead_color=$ahead_color"
    # echo "behind_color=$behind_color"

    # calculate column offsets
    local_col_offset=1
    ahead_col_offset=$(($local_col_w - ${#local_msg}))
    behind_col_offset=$(($ahead_col_w - ${#ahead_msg}))
    remote_col_offset=$(($behind_col_w - ${#behind_msg}))
    end_col_offset=$(($remote_col_w - ${#remote_msg}))

    # echo "local_col_offset =$local_col_w - ${#local_msg} = $ahead_col_offset"
    # echo "ahead_col_offset =$ahead_col_w - ${#ahead_msg} = $behind_col_offset"
    # echo "remote_col_offset=$behind_col_w - ${#behind_msg} = $remote_col_offset"
    # echo "end_col_offset =$remote_col_w - ${#remote_msg} = $end_col_offset"
    # echo "col_ws OUT=[ $local_col_w $ahead_col_w $behind_col_w $remote_col_w ]"
    # echo "this_w OUT=[ ${#local_msg} ${#ahead_msg} ${#behind_msg} ${#remote_msg} ]"
    # echo "offsets =[ $ahead_col_offset $behind_col_offset $remote_col_offset $end_col_offset ]"

    # build output messages and print
    local_msg="%$(($local_col_offset))s $(echo -e $SPACER $local_msg)"
    ahead_msg="%$(($ahead_col_offset))s $(echo -e $SPACER $ahead_color$ahead_msg$CEND)"
    behind_msg="%$(($behind_col_offset))s $(echo -e $SPACER $behind_color$behind_msg$CEND)"
    remote_msg="%$(($remote_col_offset))s $(echo -e $SPACER $remote_msg)"
    end_msg="%$(($end_col_offset))s $SPACER"

    # echo "local_msg OUT='$local_msg'"
    # echo "ahead_msg OUT='$ahead_msg'"
    # echo "behind_msg OUT='$behind_msg'"
    # echo "remote_msgs OUT='$remote_msg'"
    # echo "msg=*$local_msg}*$ahead_msg}*$behind_msg}*$remote_msg}*"

    printf "$local_msg$ahead_msg$behind_msg$remote_msg$end_msg\n"
    done

    # print something if no diffs
    if [ "$n_total_differences" == 0 ] ; then echo -e $NO_RESULTS_MSG ; fi ;
  14. @jehiah jehiah created this gist Oct 14, 2011.
    18 changes: 18 additions & 0 deletions git-branch-status
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,18 @@
    #!/bin/bash
    # by http://github.com/jehiah
    # this prints out some branch status (similar to the '... ahead' info you get from git status)

    # example:
    # $ git branch-status
    # dns_check (ahead 1) | (behind 112) origin/master
    # master (ahead 2) | (behind 0) origin/master

    git for-each-ref --format="%(refname:short) %(upstream:short)" refs/heads | \
    while read local remote
    do
    [ -z "$remote" ] && continue
    git rev-list --left-right ${local}...${remote} -- 2>/dev/null >/tmp/git_upstream_status_delta || continue
    LEFT_AHEAD=$(grep -c '^<' /tmp/git_upstream_status_delta)
    RIGHT_AHEAD=$(grep -c '^>' /tmp/git_upstream_status_delta)
    echo "$local (ahead $LEFT_AHEAD) | (behind $RIGHT_AHEAD) $remote"
    done