Merge branch 'master' into docs

This commit is contained in:
David O'Trakoun 2015-12-03 17:01:19 -05:00
commit 74b741eb7e
2 changed files with 243 additions and 57 deletions

View file

@ -1,13 +1,23 @@
# git-my v0.1
# git-my v1.0.0
> Lists (stale) (branches|tags) in the remote named (origin) (where you were
> the last committer)
Lists all of a user's branches, including local and remote, and shows:
[Homepage](https://github.com/davidosomething/git-my)
- 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 |
| ---- | ---- |
| Project Home: | [https://github.com/davidosomething/git-my](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/screenshot.png)
## Installation
@ -16,19 +26,29 @@ Unlike `git branch -r` this shows only YOUR branches.
## Usage
From command line execute:
```
git my
```
## TODO
- Add options:
```
-U|--username="gitconfig user.name"
-R|--remote=origin
-T|--tags
-B|--branches
-F|--filter=mine,stale
```
git my
Copyright (c) 2015 David O'Trakoun
### Options
#### Remote comparison branch
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
-v|--version
-h|--help
-U|--username
--local
--merged
--tracked
----
Copyright (c) 2015 David O'Trakoun <me@davidosomething.com>

244
git-my
View file

@ -1,72 +1,238 @@
#!/usr/bin/env bash
# git-my v0.1
# git-my v0.4.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 <me@davidosomething.com>
#
# 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
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"
}
# _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
_main() {
if ! _check_in_repository ; then
echo "This is not a git repository."
exit 1
fi
local remote_name
remote_name=${1:-"origin"}
# user.name<TAB>branch.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/$remote_name/}
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
git for-each-ref --shell --format="$fmt" "refs/remotes/$remote_name"
)
local everyones_remotes
everyones_remotes=$(eval "$cmd_everyones_remotes")
_filter_mine "$everyones_remotes"
eval "$cmd_everyones_remotes"
}
_main
# _get_merged_remote_branches
#
# @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 merged_remote_branches
local stripped_branchnames
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" \
)
# 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" | grep -v "HEAD" | awk -F'\t' '{ print $2 }'
}
_merge_lists() {
# shellcheck disable=SC2086
echo $1 $2 | tr ' ' '\n' | sort -u
}
# _decorate_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 my_branches=$1
local local_branches=$2
local merged_remote_branches=$3
local normal
local magenta
normal=$(tput sgr0)
magenta=$(tput setaf 5)
local clreol
clreol=$'\x1B[K'
# heading
echo 'local | tracked | merged'
echo '----- + ------- + ------'
# body
local zebra=0
for branchname in $my_branches
do
local decorated=''
local is_local=' '
local is_tracked=' '
local is_merged=' '
echo "$local_branches" | grep -q "$branchname" && \
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" && \
is_merged='✓'
if [ "$branchname" == "$(git symbolic-ref --short HEAD)" ]; then
branchname="${magenta}${branchname}${normal}"
else
branchname="${branchname}"
fi
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
printf "\e[48;5;0m"
}
_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)
my_branches=$(_merge_lists "$my_remotes" "$local_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
echo "This is not a git repository."
exit 1
fi
_main "$@"