From 88e88ba88a10466da2968934ba058275936bd363 Mon Sep 17 00:00:00 2001 From: David O'Trakoun Date: Tue, 31 Mar 2015 23:53:42 -0400 Subject: [PATCH 1/9] update 0.3.0 with decorated merged/local info --- README.md | 37 +++++++---- git-my | 191 +++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 179 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 5f2345d..6d91f21 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,18 @@ -# git-my v0.1 +# git-my v0.3.0 -> Lists (stale) (branches|tags) in the remote named (origin) (where you were -> the last committer) +> Lists a user's remote branches and shows if it was merged and/or available +> locally [Homepage](https://github.com/davidosomething/git-my) ## About -Unlike `git branch -r` this shows only YOUR branches. +Unlike `git branch -r` and `git remote show origin` this shows only branches +where YOU were the last committer and it will tell you if you have a copy of +that branch locally. + +Here's a screenshot: +![Example output](https://raw.githubusercontent.com/davidosomething/git-my/docs/git-my/screenshot.png) ## Installation @@ -16,19 +21,27 @@ Unlike `git branch -r` this shows only YOUR branches. ## Usage From command line execute: + ``` git my ``` -## TODO -- Add options: +## To do + +- Colorize output +- Options support + ``` --U|--username="gitconfig user.name" --R|--remote=origin --T|--tags --B|--branches --F|--filter=mine,stale + -v|--version + -h|--help + -d|--decorate LOCAL,MERGED + -r|--remote-ref origin/master + -U|--username + --no-color + --no-header + --no-decorate ``` -Copyright (c) 2015 David O'Trakoun + +Copyright (c) 2015 David O'Trakoun diff --git a/git-my b/git-my index d680093..56ea6d1 100755 --- a/git-my +++ b/git-my @@ -1,72 +1,189 @@ #!/usr/bin/env bash -# git-my v0.1 +# git-my v0.3.0 # -# Lists (stale) (branches|tags) in the remote named (origin) (where you were -# the last committer) +# Lists a user's remote branches and shows if it was merged +# and/or available locally # # Copyright (c) 2015 David O'Trakoun # # Usage: # git my # -# Options: -# @todo NOT IMPLEMENTED -# -U|--username="gitconfig user.name" -# -R|--remote=origin -# -T|--tags -# -B|--branches -# -F|--filter=mine,stale -# set -eu +# _check_in_repository +# +# Exits with error if not a git repository +# _check_in_repository() { git rev-parse --git-dir > /dev/null 2>&1 } -_filter_mine() { - local git_user - git_user=$(git config --get user.name) +# _get_local_branches +# +# Proper way to get a porcelain list of local branches for shell script use +# +_get_local_branches() { + local fmt + local cmd_get_local_branches - # use eval to not parse the fmt string - local my_remotes - my_remotes=$(echo "$1" | grep -i "^$git_user") - echo "$my_remotes" | awk -F'\t' '{ print $2 }' + # shellcheck disable=SC2016 + fmt=' + r=%(refname) + refname_without_prefix=${r#refs/heads/} + printf "%s\t%s\n" "$refname_without_prefix" + ' + + cmd_get_local_branches=$( + git for-each-ref --shell --format="$fmt" refs/heads + ) + + eval "$cmd_get_local_branches" } -# @TODO -_filter_stales() { - local raw_stales - raw_stales=$(git remote prune --dry-run origin) - echo "$raw_stales" -} - -_main() { - if ! _check_in_repository ; then - echo "This is not a git repository." - exit 1 - fi +# _get_everyones_remotes +# +# Get porcelain list of all remote branches +# +# @TODO support remote_name (currently origin) +# +_get_everyones_remotes() { + local fmt + local cmd_everyones_remotes # user.namebranch.name # the TAB is used as a delimiter to awk with # shellcheck disable=SC2016 - local fmt=' + fmt=' a=%(authorname) r=%(refname) - b=${r#refs/remotes/origin/} - printf "%s\t%s\n" "$a" "$b" + refname_without_prefix=${r#refs/remotes/origin/} + printf "%s\t%s\n" "$a" "$refname_without_prefix" ' - local cmd_everyones_remotes cmd_everyones_remotes=$( git for-each-ref --shell --format="$fmt" refs/remotes/origin ) - local everyones_remotes - everyones_remotes=$(eval "$cmd_everyones_remotes") - _filter_mine "$everyones_remotes" + eval "$cmd_everyones_remotes" } +# _get_merged_remote_branches +# +# @TODO support param remote_branche (currently origin/master) +# +# @output names of remote branches that are merged into origin/master +_get_merged_remote_branches() { + local remote_name + local remote_refname + local merged_remote_branches + local stripped_branchnames + + remote_name="origin" + remote_refname="master" + + merged_remote_branches=$( \ + git branch --no-color \ + --remotes \ + --merged $remote_name/$remote_refname \ + ) + + # remove "origin/" + # shellcheck disable=SC2001 + stripped_branchnames=$( \ + echo "$merged_remote_branches" | sed "s/^\s*$remote_name\///g" \ + ) + + echo "$stripped_branchnames" +} + +# _filter_mine +# +# @param git_user +# @param branchnames +# @output branchnames owned by current git user +_filter_mine() { + local git_user + local branchnames + git_user=$1 + branchnames=$2 + + # use eval to not parse the fmt string + local my_remotes + my_remotes=$(echo "$branchnames" | grep -i "^$git_user") + + # output only the branchname + echo "$my_remotes" | awk -F'\t' '{ print $2 }' +} + +# _decorate_merged +# +# @TODO support param branch to check against +# +# @param branchnames to check if merged into against +# @output branchnames with [merged] +_decorate_merged() { + local merged_remote_branches + local decorated + + merged_remote_branches=$(_get_merged_remote_branches) + local_branches=$(_get_local_branches) + + # heading + decorated=$( printf '%12s %12s %s' \ + "local copy?" "in master? " "branch name" + ) + decorated+=$'\n' + + # body + for branchname in $1 + do + local local_text="..........." + local merged_text='............' + + echo "$local_branches" | grep -q "$branchname" && \ + local_text="..[local].." + + echo "$merged_remote_branches" | grep -q "$branchname" && \ + merged_text="..[merged].." + + decorated+=$(printf "%12s.%12s %s" \ + "$local_text" "$merged_text" "$branchname" + ) + decorated+=$'\n' + done + + echo "$decorated" +} + +_main() { + local everyones_remotes + local my_remotes + local output + local git_user + local git_remote + local heading + + git_user=$(git config --get user.name) + git_remote=$(git config --get remote.origin.url) + heading="$git_user's remote branches in $git_remote" + + everyones_remotes=$(_get_everyones_remotes) + my_remotes=$(_filter_mine "$git_user" "$everyones_remotes") + output=$(_decorate_merged "$my_remotes") + + printf '+%78s+\n' | tr ' ' - + printf '| %-76s |\n' "$heading" + printf '+%78s+\n' | tr ' ' - + echo "$output" +} + +if ! _check_in_repository ; then + echo "This is not a git repository." + exit 1 +fi + _main From d41d98675e439600c1caabe7df79e690cef6f8a4 Mon Sep 17 00:00:00 2001 From: David O'Trakoun Date: Tue, 31 Mar 2015 23:54:17 -0400 Subject: [PATCH 2/9] screenshot path --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6d91f21..9266482 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ where YOU were the last committer and it will tell you if you have a copy of that branch locally. Here's a screenshot: -![Example output](https://raw.githubusercontent.com/davidosomething/git-my/docs/git-my/screenshot.png) +![Example output](https://raw.githubusercontent.com/davidosomething/git-my/docs/screenshot.png) ## Installation From 29620b3b86d80566fb4a9f75acecbea33f6fc1b8 Mon Sep 17 00:00:00 2001 From: David O'Trakoun Date: Tue, 31 Mar 2015 23:55:59 -0400 Subject: [PATCH 3/9] readme fmt --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9266482..d028075 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,9 @@ > Lists a user's remote branches and shows if it was merged and/or available > locally -[Homepage](https://github.com/davidosomething/git-my) +| Name | Link | +| ---- | ---- | +| Project Home: | [https://github.com/davidosomething/git-my](https://github.com/davidosomething/git-my) ## About From 302401bf7c6472720c9d2a0acb18b7b54b78286e Mon Sep 17 00:00:00 2001 From: David O'Trakoun Date: Wed, 1 Apr 2015 14:30:13 -0400 Subject: [PATCH 4/9] support argument for remote branch --- README.md | 14 ++++++- git-my | 114 +++++++++++++++++++++++++++++++++--------------------- 2 files changed, 83 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index d028075..c3c7feb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# git-my v0.3.0 +# git-my v0.4.0 > Lists a user's remote branches and shows if it was merged and/or available > locally @@ -28,6 +28,18 @@ From command line execute: git my ``` +### Options + +Currently git-my supports one argument, the remote branch to test against. E.g. +running: + +``` +git my origin/qa +``` + +will give you a list of your remote branches and tell you which ones have been +merged into `origin/qa`. + ## To do - Colorize output diff --git a/git-my b/git-my index 56ea6d1..cd4ee22 100755 --- a/git-my +++ b/git-my @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# git-my v0.3.0 +# git-my v0.4.0 # # Lists a user's remote branches and shows if it was merged # and/or available locally @@ -53,18 +53,21 @@ _get_everyones_remotes() { local fmt local cmd_everyones_remotes + local remote_name + remote_name=${1:-"origin"} + # user.namebranch.name # the TAB is used as a delimiter to awk with # shellcheck disable=SC2016 fmt=' a=%(authorname) r=%(refname) - refname_without_prefix=${r#refs/remotes/origin/} + refname_without_prefix=${r#refs/remotes/$remote_name/} printf "%s\t%s\n" "$a" "$refname_without_prefix" ' cmd_everyones_remotes=$( - git for-each-ref --shell --format="$fmt" refs/remotes/origin + git for-each-ref --shell --format="$fmt" "refs/remotes/$remote_name" ) eval "$cmd_everyones_remotes" @@ -72,22 +75,26 @@ _get_everyones_remotes() { # _get_merged_remote_branches # -# @TODO support param remote_branche (currently origin/master) -# -# @output names of remote branches that are merged into origin/master +# @param string optional remote to list merged branches of. Defaults to +# "origin/master" +# @output names of remote branches that are merged into given branch _get_merged_remote_branches() { + local remote local remote_name - local remote_refname + #local remote_refname local merged_remote_branches local stripped_branchnames - remote_name="origin" - remote_refname="master" + remote=${1:-"origin/master"} + # trim from end of string until / for the remote name + remote_name=${remote%/*} + # trim from beginning of string until / for the remote refname + #remote_refname=${remote#*/} merged_remote_branches=$( \ git branch --no-color \ --remotes \ - --merged $remote_name/$remote_refname \ + --merged "$remote" \ ) # remove "origin/" @@ -120,36 +127,30 @@ _filter_mine() { # _decorate_merged # -# @TODO support param branch to check against -# -# @param branchnames to check if merged into against -# @output branchnames with [merged] +# @param string my_branches list of remote branch names owned by me +# @param string local_branches list of local branch names +# @param string merged_remote_branches list of all remote branch names merged +# into another branch +# @output table of branch names and status _decorate_merged() { - local merged_remote_branches + local my_branches=$1 + local local_branches=$2 + local merged_remote_branches=$3 local decorated - merged_remote_branches=$(_get_merged_remote_branches) - local_branches=$(_get_local_branches) - - # heading - decorated=$( printf '%12s %12s %s' \ - "local copy?" "in master? " "branch name" - ) - decorated+=$'\n' - # body - for branchname in $1 + for branchname in $my_branches do - local local_text="..........." - local merged_text='............' + local local_text='............' + local merged_text='..........' echo "$local_branches" | grep -q "$branchname" && \ - local_text="..[local].." + local_text='.....[local]' echo "$merged_remote_branches" | grep -q "$branchname" && \ - merged_text="..[merged].." + merged_text='..[merged]' - decorated+=$(printf "%12s.%12s %s" \ + decorated+=$(printf " %12s..%10s. %s" \ "$local_text" "$merged_text" "$branchname" ) decorated+=$'\n' @@ -158,26 +159,51 @@ _decorate_merged() { echo "$decorated" } -_main() { - local everyones_remotes - local my_remotes - local output - local git_user - local git_remote +_heading() { + local git_user=$1 + local git_remote=$2 + local remote_ref=$3 local heading + local table_heading - git_user=$(git config --get user.name) - git_remote=$(git config --get remote.origin.url) + table_heading=$( printf '%12s %10s %s' \ + "local copy?" "in $remote_ref?" "branch name" + ) heading="$git_user's remote branches in $git_remote" - everyones_remotes=$(_get_everyones_remotes) - my_remotes=$(_filter_mine "$git_user" "$everyones_remotes") - output=$(_decorate_merged "$my_remotes") - printf '+%78s+\n' | tr ' ' - printf '| %-76s |\n' "$heading" printf '+%78s+\n' | tr ' ' - - echo "$output" + echo + printf ' %-76s \n' "$table_heading" +} + + +_main() { + local decorated + local everyones_remotes + local git_remote + local git_user + local local_branches + local merged_remote_branches + local my_remotes + + local remote=${1:-"origin/master"} + + # trim from end of string until / for the remote name + local remote_name=${remote%/*} + # trim from beginning of string until / for the remote refname + local remote_ref=${remote#*/} + + git_user=$(git config --get user.name) + git_remote=$(git config --get "remote.${remote_name}.url") + everyones_remotes=$(_get_everyones_remotes "$remote_name") + my_remotes=$(_filter_mine "$git_user" "$everyones_remotes") + merged_remote_branches=$(_get_merged_remote_branches "$remote_name/$remote_ref") + local_branches=$(_get_local_branches) + + _heading "$git_user" "$git_remote" "$remote_ref" + _decorate_merged "$my_remotes" "$local_branches" "$merged_remote_branches" } if ! _check_in_repository ; then @@ -185,5 +211,5 @@ if ! _check_in_repository ; then exit 1 fi -_main +_main "$@" From 505c1eb4e7d3bd891c78ea555179306b0dbfa657 Mon Sep 17 00:00:00 2001 From: David O'Trakoun Date: Thu, 3 Dec 2015 15:56:38 -0500 Subject: [PATCH 5/9] cleanup output with color, check if branch is tracked too --- git-my | 73 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/git-my b/git-my index cd4ee22..968b859 100755 --- a/git-my +++ b/git-my @@ -18,7 +18,7 @@ set -eu # Exits with error if not a git repository # _check_in_repository() { - git rev-parse --git-dir > /dev/null 2>&1 + git rev-parse --git-dir >/dev/null 2>&1 } # _get_local_branches @@ -122,7 +122,12 @@ _filter_mine() { my_remotes=$(echo "$branchnames" | grep -i "^$git_user") # output only the branchname - echo "$my_remotes" | awk -F'\t' '{ print $2 }' + echo "$my_remotes" | grep -v "HEAD" | awk -F'\t' '{ print $2 }' +} + +_merge_lists() { + # shellcheck disable=SC2086 + echo $1 $2 | tr ' ' '\n' | sort -u } # _decorate_merged @@ -136,53 +141,51 @@ _decorate_merged() { local my_branches=$1 local local_branches=$2 local merged_remote_branches=$3 - local decorated + local zebra=0 + local is_first='' + + # heading + echo ' local | remote | tracked | branch' # body for branchname in $my_branches do - local local_text='............' - local merged_text='..........' + local decorated='' + local is_local=' ' + local is_tracked=' ' + local is_merged=' ' echo "$local_branches" | grep -q "$branchname" && \ - local_text='.....[local]' + is_local='✓' + + if git rev-parse --symbolic-full-name "$branchname"@{u} >/dev/null 2>&1; then + is_tracked='✓' + fi echo "$merged_remote_branches" | grep -q "$branchname" && \ - merged_text='..[merged]' + is_merged='✓' - decorated+=$(printf " %12s..%10s. %s" \ - "$local_text" "$merged_text" "$branchname" + decorated=$(printf "%s %s | %s | %s | %s" \ + "$is_first" "$is_local" "$is_merged" "$is_tracked" "$branchname" ) - decorated+=$'\n' + + if [ $zebra = 0 ]; then + echo -en "\e[48;5;0m${decorated}" + zebra=1 + else + echo -en "\e[48;5;236m${decorated}" + zebra=0 + fi + + is_first='\n' done - - echo "$decorated" -} - -_heading() { - local git_user=$1 - local git_remote=$2 - local remote_ref=$3 - local heading - local table_heading - - table_heading=$( printf '%12s %10s %s' \ - "local copy?" "in $remote_ref?" "branch name" - ) - heading="$git_user's remote branches in $git_remote" - - printf '+%78s+\n' | tr ' ' - - printf '| %-76s |\n' "$heading" - printf '+%78s+\n' | tr ' ' - echo - printf ' %-76s \n' "$table_heading" } - _main() { local decorated local everyones_remotes - local git_remote + #local git_remote local git_user local local_branches local merged_remote_branches @@ -196,14 +199,14 @@ _main() { local remote_ref=${remote#*/} git_user=$(git config --get user.name) - git_remote=$(git config --get "remote.${remote_name}.url") + #git_remote=$(git config --get "remote.${remote_name}.url") everyones_remotes=$(_get_everyones_remotes "$remote_name") my_remotes=$(_filter_mine "$git_user" "$everyones_remotes") merged_remote_branches=$(_get_merged_remote_branches "$remote_name/$remote_ref") local_branches=$(_get_local_branches) + my_branches=$(_merge_lists "$my_remotes" "$local_branches") - _heading "$git_user" "$git_remote" "$remote_ref" - _decorate_merged "$my_remotes" "$local_branches" "$merged_remote_branches" + _decorate_merged "$my_branches" "$my_remotes" "$local_branches" "$merged_remote_branches" } if ! _check_in_repository ; then From 850cd44aac82bb94d3e1ede14a7d8d7c2c5f5875 Mon Sep 17 00:00:00 2001 From: David O'Trakoun Date: Thu, 3 Dec 2015 16:50:56 -0500 Subject: [PATCH 6/9] formatting and meta --- git-my | 54 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/git-my b/git-my index 968b859..cc10224 100755 --- a/git-my +++ b/git-my @@ -141,13 +141,21 @@ _decorate_merged() { local my_branches=$1 local local_branches=$2 local merged_remote_branches=$3 - local zebra=0 - local is_first='' + + local normal + local magenta + normal=$(tput sgr0) + magenta=$(tput setaf 5) + + local clreol + clreol=$'\x1B[K' # heading - echo ' local | remote | tracked | branch' + echo 'local | tracked | merged' + echo '----- + ------- + ------' # body + local zebra=0 for branchname in $my_branches do local decorated='' @@ -165,27 +173,31 @@ _decorate_merged() { echo "$merged_remote_branches" | grep -q "$branchname" && \ is_merged='✓' - decorated=$(printf "%s %s | %s | %s | %s" \ - "$is_first" "$is_local" "$is_merged" "$is_tracked" "$branchname" - ) - - if [ $zebra = 0 ]; then - echo -en "\e[48;5;0m${decorated}" - zebra=1 + if [ "$branchname" == "$(git symbolic-ref --short HEAD)" ]; then + branchname="${magenta}${branchname}${normal}" else - echo -en "\e[48;5;236m${decorated}" - zebra=0 + branchname="${branchname}" fi - is_first='\n' + decorated=$(printf " %s | %s | %s %s" \ + "$is_local" "$is_tracked" "$is_merged" "$branchname") + + if [ $zebra = 0 ]; then + printf "\e[48;5;0m%s %s\n" "$decorated" "$clreol" + zebra=1 + else + printf "\e[48;5;236m%s %s\n" "$decorated" "$clreol" + zebra=0 + fi done - echo + + printf "\e[48;5;0m" } _main() { local decorated local everyones_remotes - #local git_remote + local git_remote local git_user local local_branches local merged_remote_branches @@ -199,14 +211,22 @@ _main() { local remote_ref=${remote#*/} git_user=$(git config --get user.name) - #git_remote=$(git config --get "remote.${remote_name}.url") + git_remote=$(git config --get "remote.${remote_name}.url") everyones_remotes=$(_get_everyones_remotes "$remote_name") my_remotes=$(_filter_mine "$git_user" "$everyones_remotes") merged_remote_branches=$(_get_merged_remote_branches "$remote_name/$remote_ref") local_branches=$(_get_local_branches) my_branches=$(_merge_lists "$my_remotes" "$local_branches") - _decorate_merged "$my_branches" "$my_remotes" "$local_branches" "$merged_remote_branches" + echo + echo "branches owned by user: $git_user" + echo "compare local/merge to: $remote" + echo "in remote repository: $git_remote" + echo + + _decorate_merged "$my_branches" "$local_branches" "$merged_remote_branches" + + echo } if ! _check_in_repository ; then From 7adccffbb4814fd6355ab9753ce23074e7c29778 Mon Sep 17 00:00:00 2001 From: David O'Trakoun Date: Thu, 3 Dec 2015 16:56:15 -0500 Subject: [PATCH 7/9] update readme --- README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c3c7feb..94dc14c 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,10 @@ -# git-my v0.4.0 +# git-my v1.0.0 -> Lists a user's remote branches and shows if it was merged and/or available -> locally +Lists all of a user's branches, including local and remote, and shows: + +- if a remote branch is checked out locally +- if a local branch is tracked remotely +- if a local branch is up-to-date with a specified branch | Name | Link | | ---- | ---- | @@ -42,7 +45,6 @@ merged into `origin/qa`. ## To do -- Colorize output - Options support ``` @@ -56,6 +58,7 @@ merged into `origin/qa`. --no-decorate ``` +---- Copyright (c) 2015 David O'Trakoun From 383142fdb4c618cd4380c016eacda4a1358eba71 Mon Sep 17 00:00:00 2001 From: David O'Trakoun Date: Thu, 3 Dec 2015 16:56:43 -0500 Subject: [PATCH 8/9] spacing --- git-my | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/git-my b/git-my index cc10224..95c1c36 100755 --- a/git-my +++ b/git-my @@ -219,9 +219,9 @@ _main() { my_branches=$(_merge_lists "$my_remotes" "$local_branches") echo - echo "branches owned by user: $git_user" + echo "branches owned by user: $git_user" echo "compare local/merge to: $remote" - echo "in remote repository: $git_remote" + echo "in remote repository: $git_remote" echo _decorate_merged "$my_branches" "$local_branches" "$merged_remote_branches" From 320ab19f95ec09c603c8f301858473281232fb31 Mon Sep 17 00:00:00 2001 From: David O'Trakoun Date: Thu, 3 Dec 2015 17:01:06 -0500 Subject: [PATCH 9/9] update readme --- README.md | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 94dc14c..7b99727 100644 --- a/README.md +++ b/README.md @@ -27,36 +27,26 @@ Here's a screenshot: From command line execute: -``` -git my -``` + git my ### Options -Currently git-my supports one argument, the remote branch to test against. E.g. -running: +#### Remote comparison branch -``` -git my origin/qa -``` + git my origin/qa will give you a list of your remote branches and tell you which ones have been merged into `origin/qa`. ## To do -- Options support + -v|--version + -h|--help + -U|--username + --local + --merged + --tracked -``` - -v|--version - -h|--help - -d|--decorate LOCAL,MERGED - -r|--remote-ref origin/master - -U|--username - --no-color - --no-header - --no-decorate -``` ----