-
-
Save vivek-bala/9862bb3c412ede083ee4a26b13ce89f7 to your computer and use it in GitHub Desktop.
git bs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# edited by andre@merzky.net | |
# original at https://gist.github.com/Mark-Booth/5058384 | |
# forked from https://gist.github.com/lth2h/4177524 @ ae184f1 by mark.booth | |
# forked from https://gist.github.com/jehiah/1288596 @ e357c1e by lth2h | |
# ideas from https://github.com/kortina/bakpak/blob/master/bin/git-branches-vs-origin-master | |
# this prints out some branch status | |
# (similar to the '... ahead' info you get from git status) | |
# example: | |
# $ git branch-status -a | |
# dns_check (ahead 1) | (behind 112) origin/master | |
# master (ahead 2) | (behind 0) origin/master | |
# $ git branch-status | |
# master (ahead 2) | (behind 0) origin/master | |
OPTIONS='hcdemnqb:s:lru:' | |
usage=" | |
$(basename "$0") ["$OPTIONS"] -- Summarise status of branch(es) | |
Where: | |
-h shows this help text | |
-c shows the current branch only | |
-m shows branch(es) with respect to origin/master | |
-d shows branch(es) with respect to origin/devel | |
-e shows all branches, including remote-only ones | |
-n shows numbers instead of graphs | |
-q quiet, show output only if counts are non-zero | |
-b BRANCH shows branch(es) with respect to a given branch | |
-s FROM/TO shows branch(es) with respect to a branch substitution | |
Note: Any branches which don't match FROM will be ignored | |
-l shows only when the left/local side is ahead (push needed) | |
-r shows only when the right/remote side is ahead (pull needed) | |
-u UPSTREAM selects an upstream other than origin for -b and -m options | |
For example | |
$(basename "$0") -m # Show all branches which are ahead | |
# of or behind their origin/master. | |
$(basename "$0") -b 8.38-hotfix # Show each repo whose checked out | |
# branch is behind the hotfix branch. | |
$(basename "$0") -s 8.34/8.36 # Show all 8.34 branches which are | |
# ahead of or behind their 8.38 remote. | |
" | |
verbose=true | |
filter=refs/heads | |
upstreambranch= | |
while getopts $OPTIONS option; do | |
case "$option" in | |
h) echo "$usage" | |
exit | |
;; | |
c) filter= | |
;; | |
d) upstreambranch=devel | |
;; | |
e) empty=true | |
;; | |
m) upstreambranch=master | |
;; | |
n) numbers=true | |
;; | |
q) verbose= | |
;; | |
b) upstreambranch=$OPTARG | |
;; | |
s) remotesubstitute=$OPTARG | |
;; | |
l) aheadonly=true | |
;; | |
r) behindonly=true | |
;; | |
u) upstream=$OPTARG | |
;; | |
:) echo "Option -$OPTARG requires an argument." >&2 | |
echo "$usage" >&2 | |
exit 1 | |
;; | |
?) printf "Invalid option: -$OPTARG" >&2 | |
echo "$usage" >&2 | |
exit 1 | |
;; | |
esac | |
done | |
shift $((OPTIND - 1)) | |
test -z "$filter" && filter=$(git symbolic-ref -q HEAD) | |
test -z "$upstream" && upstream=origin | |
BM=0 | |
RM=0 | |
LM=0 | |
LIM=40 | |
test -z $aheadonly || LIM=80 | |
test -z $behindonly || LIM=80 | |
P="/tmp/git_pipe.$$" | |
mkfifo $P | |
if test -z "$empty" | |
then | |
gc=$(git for-each-ref --format="%(refname:short) %(upstream:short)" $filter) | |
(printf "$gc" | grep '^master\b' | |
printf "$gc" | grep '^devel\b' | |
printf "$gc" | grep -v -e '^master\b' -e '^devel\b') > $P & | |
else | |
( | |
git branch -a | sed -e 's/^\*/ /' \ | |
| grep -ve '^[ \*]*remotes/'"$upstream" \ | |
| grep -v -e HEAD \ | |
; \ | |
git branch -a | sed -e 's/^\*/ /' \ | |
| grep -e '^[ \*]*remotes/'"$upstream" \ | |
| grep -v -e HEAD -e "$upstream/pr/" \ | |
| cut -f 3- -d '/' \ | |
) | xargs -n 1 echo | sort -u > $P & | |
fi | |
while read local remote | |
do | |
if ! test -z "$remotesubstitute" | |
then | |
remote=$(echo $remote | sed "s/${remotesubstitute}/") | |
elif ! test -z "$upstreambranch" | |
then | |
remote=$upstream/$upstreambranch | |
fi | |
if test -z "$(git ls-remote . $remote)" | |
then | |
remote="" | |
else | |
DELTAS=$(git rev-list --left-right ${local}...${remote} -- 2>/dev/null) | |
OK=$? | |
LEFT_AHEAD=$( echo "$DELTAS" | grep -c '^<') | |
RIGHT_AHEAD=$(echo "$DELTAS" | grep -c '^>') | |
fi | |
# new longest name? | |
test ${#local} -gt $BM && BM=${#local} | |
if test "$OK" = 0 | |
then | |
R='#' | |
L='#' | |
else | |
R='#' | |
L='?' | |
fi | |
if ! test -z "$numbers" | |
then | |
R=$RIGHT_AHEAD | |
RM=5 | |
L=$LEFT_AHEAD | |
LM=5 | |
else | |
i=0 | |
while test $i -lt $RIGHT_AHEAD | |
do | |
i=$((i+1)) | |
R="$R-" | |
test ${#R} -gt $LIM && R="$R<<<" | |
test ${#R} -gt $RM && RM="${#R}" | |
test ${#R} -gt $LIM && break | |
done | |
i=0 | |
while test $i -lt $LEFT_AHEAD | |
do | |
i=$((i+1)) | |
L="-$L" | |
test ${#L} -gt $LIM && L=">>>$L" | |
test ${#L} -gt $LM && LM=${#L} | |
test ${#L} -gt $LIM && break | |
done | |
fi | |
# skip this one if this is the compare target and L,R are empty | |
if test "$upstreambranch" && test "$remote" = "$upstream/$local" | |
then | |
if test "$L" = "#" && test "$R" = "#" | |
then | |
continue | |
fi | |
fi | |
if [ -z $aheadonly ] && [ -z $behindonly ] ; then | |
if [ $LEFT_AHEAD -gt 0 ] || [ $RIGHT_AHEAD -gt 0 ] || [ $verbose ] ; then | |
INFO="$INFO$local $L $R $remote\\n" | |
fi | |
elif [ $aheadonly ] ; then | |
if [ $LEFT_AHEAD -gt 0 ] || [ $verbose ] ; then | |
RM=0 | |
INFO="$INFO$local $L # $remote\\n" | |
fi | |
elif [ $behindonly ] ; then | |
if [ $RIGHT_AHEAD -gt 0 ] || [ $verbose ] ; then | |
LM=0 | |
INFO="$INFO$local # $R $remote\\n" | |
fi | |
else | |
printf "Specifying both -l and -r makes no sense" >&2 | |
echo "$usage" >&2 | |
exit 1 | |
fi | |
done < $P | |
rm -f $P | |
test -z "$numbers" && RM="-$RM" | |
s="%-${BM}s %${LM}s | %${RM}s %-20s\n" | |
echo | |
printf "$INFO" | \ | |
while read local L R remote | |
do | |
L=$(echo "$L" | sed -e 's/#//g') | |
R=$(echo "$R" | sed -e 's/#//g') | |
printf "$s" "$local" "$L" "$R" "$remote" | |
# printf "$s" $local $L $R $remote | |
done | |
echo |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment