├── git-cherry-move ├── git-prompt ├── git-get-branch ├── git-l ├── git-pull-request ├── git-is-current ├── git-info ├── git-out ├── git-cherry-copy └── README.md /git-cherry-move: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | git-cherry-copy -m "$@" 6 | -------------------------------------------------------------------------------- /git-prompt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # gitl-prompt 4 | # 5 | # https://github.com/lennartcl/gitl 6 | # 7 | # License: MIT 8 | # Copyright (c) 2012 Lennart C. L. Kats 9 | 10 | set -e 11 | 12 | PROMPT=' PS1='\''\[\033[01;32m\]\u:\[\033[01;34m\]$(pwd | sed "s|$HOME|~|")\[\033[0;36m\]$(git-get-branch -p)\[\033[00m\]\$ '\' 13 | 14 | echo "Add this to the .bashrc or .profile in your home directory:" 15 | echo 16 | echo $PROMPT 17 | -------------------------------------------------------------------------------- /git-get-branch: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # git-get-branch 4 | # 5 | # License: MIT 6 | # Copyright (c) 2012 Lennart C. L. Kats 7 | 8 | set -e 9 | 10 | RESULT=`git branch --no-color 2>/dev/null | grep '\* ' | grep --color=never -Eo '(\(|\w).*'` 11 | 12 | if [ "$RESULT" == "(no branch)" ] || [ "$RESULT" == "" ]; then 13 | if [ "$1" == "-p" ]; then 14 | if [ "$RESULT" == "(no branch)" ]; then 15 | echo -n " * `git rev-parse HEAD | grep -oE '^.{7}'`" 16 | fi 17 | else 18 | echo "Error: not on a branch" >&2 19 | exit 1 20 | fi 21 | else 22 | if [ "$1" == "-p" ]; then 23 | echo -n ' * '$RESULT 24 | else 25 | echo $RESULT 26 | fi 27 | fi 28 | 29 | if [ "$1" == "-p" ] && [ "$2" != "--no-tag" ] && git describe --tag --exact-match &>/dev/null; then 30 | echo -n ' @ '`git describe --tag --exact-match` 31 | fi 32 | -------------------------------------------------------------------------------- /git-l: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # git-l 4 | # 5 | # License: MIT 6 | # Copyright (c) 2012 Lennart C. L. Kats 7 | 8 | set -e 9 | 10 | if [ "$1" == "" ]; then 11 | BRANCH=HEAD 12 | else 13 | BRANCH=$1 14 | shift 15 | fi 16 | 17 | if echo $BRANCH | grep '\.\.' >/dev/null; then 18 | LOG=`git log --oneline --first-parent $BRANCH "$@" | head -n 21` 19 | elif ! git remote | grep -iE '^origin$' >/dev/null; then 20 | LOG=`git log --oneline --first-parent $BRANCH "$@" | head -n 21` 21 | else 22 | LOG=`git log --oneline --first-parent origin/master..$BRANCH "$@" | head -n 21` 23 | fi 24 | 25 | if [ "$LOG" == "" ] && 26 | (echo $BRANCH | grep -iE '^(master|origin/master)$' >/dev/null || 27 | (echo $BRANCH | grep -iE '^HEAD$' >/dev/null && [ "`git-get-branch 2>/dev/null`" == "master" ])) 28 | then 29 | LOG=`git log --oneline --first-parent $BRANCH "$@" | head -n 21` 30 | fi 31 | 32 | if [ `echo "$LOG" | wc -l` -gt 20 ]; then 33 | echo "$LOG" | head -n 20 34 | echo ... 35 | else 36 | echo "$LOG" 37 | fi 38 | -------------------------------------------------------------------------------- /git-pull-request: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # git-pull-request 4 | # 5 | # License: MIT 6 | # Copyright (c) 2012 Lennart C. L. Kats 7 | 8 | set -e 9 | 10 | OLD= 11 | NO_FETCH= 12 | 13 | if [ "$1" == "-o" ]; then 14 | OLD=-o 15 | NO_FETCH=-f 16 | shift 17 | fi 18 | 19 | if [ "$1" == "-f" ]; then 20 | NO_FETCH=-f 21 | shift 22 | fi 23 | 24 | if [ "$1" == "-o" ]; then 25 | OLD=-o 26 | NO_FETCH=-f 27 | shift 28 | fi 29 | 30 | if [ "$1" == "" ]; then 31 | BRANCH=`git-get-branch` 32 | else 33 | BRANCH="$1" 34 | fi 35 | 36 | # URL encode is required when not using /new/ 37 | ENC_BRANCH=`echo -n $BRANCH | sed 's/\//%2F/g'` 38 | 39 | 40 | REMOTE=$( 41 | git remote -v | grep 'origin.*push' \ 42 | | grep -oE '(bitbucket.org|github.com)[:/][^/]+/[^ ]+' \ 43 | | sed -E 's/(.*)\.git/\1/' \ 44 | | sed -E 's/(bitbucket.org|github.com):/\1\//' \ 45 | ) || (echo 'No remote for current directory' >&2 && exit 1) 46 | 47 | 48 | if [ ! "$REMOTE" ]; then 49 | echo Repository not recognized: 50 | git remote -v 51 | exit 1 52 | fi 53 | 54 | if [ ! $NO_FETCH ]; then 55 | CURL_OUT=/tmp/git-pr-`date +'%H%M%S'` 56 | # curl --head -s -o $CURL_OUT $URL/$ENC_BRANCH?access_token=$GITHUB_TOKEN & 57 | CURL=$! 58 | fi 59 | 60 | if [ ! $OLD ] && ! [ $NO_FETCH ] && ! LOG=`git log origin/$BRANCH..$BRANCH 2>/dev/null` || [ "$LOG" != "" ]; then 61 | git-push-branch $BRANCH 62 | fi 63 | 64 | if [ ! $OLD ] && ! git-is-current -q $NO_FETCH $BRANCH; then 65 | echo -n "Branch conflicts with origin/master, continue? [no] " 66 | read CONSENT 67 | if [ "$CONSENT" != "y" ] && [ "$CONSENT" != "yes" ]; then 68 | exit 1 69 | fi 70 | fi 71 | 72 | open() { 73 | if which start &>/dev/null && ! [[ `uname -s` =~ Darwin|Linux ]]; then 74 | start "$1" 75 | elif which xdg-open &>/dev/null && ! [[ `uname -s` =~ Darwin ]]; then 76 | xdg-open "$1" 77 | elif which gnome-open &>/dev/null && ! [[ `uname -s` =~ Darwin ]]; then 78 | gnome-open "$1" 79 | elif which kde-open &>/dev/null && ! [[ `uname -s` =~ Darwin ]]; then 80 | kde-open "$1" 81 | else 82 | command open "$1" 83 | fi 84 | } 85 | 86 | if echo $REMOTE | grep -q bitbucket.org; then 87 | URL="https://$REMOTE" 88 | if [ $OLD ]; then 89 | open "$URL/src/$BRANCH" 90 | else 91 | open "$URL/pull-request/new?source=$BRANCH" 92 | fi 93 | else 94 | USER=`echo $REMOTE | perl -pe 's|github.com.([^/]+)/.*|$1|'` 95 | REPO=`echo $REMOTE | perl -pe 's|github.com.[^/]+/(.*)|$1|'` 96 | URL=https://github.com/$USER/$REPO 97 | 98 | #if [ ! $NO_FETCH ] && wait $CURL && grep '1 302' $CURL_OUT &>/dev/null; then 99 | if [ $OLD ]; then 100 | open $URL/pull/$ENC_BRANCH 101 | else 102 | open $URL/compare/$BRANCH?expand=1 103 | fi 104 | fi -------------------------------------------------------------------------------- /git-is-current: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # git-is-current 4 | # 5 | # License: MIT 6 | # Copyright (c) 2012 Lennart C. L. Kats 7 | 8 | set -e 9 | 10 | # Internal config 11 | USE_BETA=0 12 | 13 | # Defaults 14 | BRANCH=HEAD 15 | NO_FETCH= 16 | MASTER= 17 | 18 | if [ "$1" == "-q" ]; then 19 | QUIET=-q 20 | shift 21 | fi 22 | 23 | if [ "$1" == "-f" ]; then 24 | NO_FETCH=-f 25 | shift 26 | fi 27 | 28 | if [ "$1" == "-q" ]; then 29 | QUIET=-q 30 | shift 31 | fi 32 | 33 | if echo "$1" | grep origin/ >/dev/null; then 34 | MASTER=$1 35 | shift 36 | fi 37 | 38 | if [ "$1" != "" ]; then 39 | BRANCH="$1" 40 | fi 41 | 42 | 43 | if [ "$MASTER" == "" ]; then 44 | if [ "$USE_BETA" != "1" ]; then 45 | MASTER=origin/master 46 | else 47 | FAIL=0 48 | if [ ! $NO_FETCH ]; then 49 | echo -n 'Fetching... ' 50 | git fetch origin master beta &>/dev/null 51 | echo -ne '\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b' 52 | fi 53 | $0 -f origin/master $BRANCH || FAIL=1 54 | if git branch --list origin/beta >/dev/null; then 55 | $0 -f origin/beta $BRANCH || FAIL=1 56 | fi 57 | exit $FAIL 58 | fi 59 | fi 60 | 61 | if [ ! $NO_FETCH ]; then 62 | M=`echo $MASTER | perl -pe 's/^origin\/(.*)/$1/'` 63 | echo -n 'Fetching... ' 64 | git fetch origin $M &>/dev/null 65 | echo -ne '\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b' 66 | fi 67 | 68 | # Non-destructive version based on http://stackoverflow.com/a/6283843: doesn't detect "both added file" conflicts 69 | BASE=`git merge-base $MASTER $BRANCH` 70 | DIFF=`git merge-tree $BASE $MASTER $BRANCH || echo "added in -- git merge-tree failed"` 71 | if echo "$DIFF" | grep -E '^.<<<<<' &>/dev/null; then 72 | echo -e "$BRANCH \033[01;32mCONFLICTS\033[00m with $MASTER" 73 | exit 1 74 | elif echo "$DIFF" | grep -Ev '^added in' &>/dev/null; then 75 | if [ ! $QUIET ]; then 76 | echo "$BRANCH does not conflict with $MASTER" 77 | fi 78 | exit 0 79 | fi 80 | 81 | # Fallback: slow, in-repository check 82 | 83 | OLD_BRANCH=`git get-branch` 84 | STASH= 85 | 86 | if ! (git checkout $MASTER && git checkout `git rev-parse HEAD`) &>/dev/null; then 87 | STASH=1 88 | git stash save "changes stashed by git-is-current" &>/dev/null || 89 | (echo Could not stash current changes>&2; git stash; exit 1) 90 | fi 91 | 92 | git checkout $MASTER &>/dev/null 93 | git checkout `git rev-parse HEAD` &>/dev/null 94 | if git merge $BRANCH --no-ff --no-commit &>/dev/null; then 95 | if [ ! $QUIET ]; then 96 | echo "$BRANCH does not conflict with $MASTER" 97 | fi 98 | EXIT=0 99 | else 100 | echo -e "$BRANCH \033[01;31mCONFLICTS\033[00m with $MASTER" 101 | EXIT=1 102 | fi 103 | 104 | git checkout -f $OLD_BRANCH &>/dev/null 105 | if [ $STASH ]; then 106 | git stash pop &>/dev/null 107 | fi 108 | 109 | exit $EXIT 110 | -------------------------------------------------------------------------------- /git-info: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # git-info 4 | # 5 | # License: MIT 6 | # Copyright (c) 2012 Lennart C. L. Kats 7 | 8 | set -e 9 | 10 | WEB= 11 | if [ "$1" == "-w" ]; then 12 | WEB=-w 13 | shift 14 | fi 15 | 16 | REV= 17 | if [ "$1" != "" ] && git rev-parse --verify "$1" &>/dev/null && [ ! -e "$1" ]; then 18 | REV=`git rev-parse $1` 19 | shift 20 | elif [ "$1" == "-r" ]; then 21 | REV=`git rev-parse $2` 22 | shift; shift 23 | fi 24 | 25 | if [ "$1" == "-w" ]; then 26 | WEB=-w 27 | shift 28 | fi 29 | 30 | if [ "$1" == "" ]; then 31 | FILE= 32 | else 33 | FILE="$1" 34 | 35 | FILE=`cd -P -- "$(dirname -- "$FILE")" && echo "$(pwd -P)/$(basename -- "$FILE")"` 36 | while [ ! -e .git ] && [ "`pwd`" != "/" ]; do 37 | cd .. 38 | done 39 | BASEPATH=`ls -d $(pwd -P)` 40 | RELPATH=`echo "$FILE" | sed "s|$BASEPATH/||"` 41 | fi 42 | 43 | if ! git remote &>/dev/null; then 44 | cd `dirname "$FILE"` 45 | FILE="`basename "$FILE"`" 46 | fi 47 | 48 | REMOTE=$( 49 | git remote -v | grep 'origin.*push' \ 50 | | grep -oE '(bitbucket.org|github.com)[:/][^/]+/[^ ]+' \ 51 | | sed -E 's/(.*)\.git/\1/' \ 52 | | sed -E 's/(bitbucket.org|github.com):/\1\//' \ 53 | ) || (echo 'No remote for current directory' >&2 && exit 1) 54 | 55 | 56 | if [ ! "$REMOTE" ]; then 57 | echo Repository not recognized: 58 | git remote -v 59 | exit 1 60 | fi 61 | 62 | BRANCH=`git-get-branch 2>/dev/null || git rev-parse HEAD` 63 | BRANCH_IN_URL=`echo $BRANCH | sed 's!/!%2F!g'` 64 | 65 | if [ "$FILE" ] && [ ! -d "$FILE" ]; then 66 | git status "$FILE" 67 | fi 68 | 69 | if echo $REMOTE | grep -q bitbucket.org; then 70 | BASE_URL="https://$REMOTE" 71 | 72 | if [ $REV ] && [ ! "$FILE" ]; then 73 | URL="$BASE_URL/commits/$REV" 74 | DIFFURL= # not supported 75 | elif [ $REV ]; then 76 | URL="$BASE_URL/src/$REV/$RELPATH?at=$BRANCH" 77 | if [ ! -d "$FILE" ]; then 78 | DIFFURL="$BASE_URL/diff/$RELPATH?diff1=master&diff2=$REV&at=$BRANCH" 79 | fi 80 | else 81 | URL="$BASE_URL/src/$BRANCH_IN_URL/$RELPATH?at=$BRANCH" 82 | DIFFURL="$BASE_URL/diff?diff1=master&diff2=$BRANCH" 83 | fi 84 | else 85 | USER=`echo $REMOTE | perl -pe 's|github.com.([^/]+)/.*|$1|'` 86 | REPO=`echo $REMOTE | perl -pe 's|github.com.[^/]+/(.*)|$1|'` 87 | BASE_URL="https://github.com/$USER/$REPO" 88 | 89 | if [ $REV ] && [ ! "$FILE" ]; then 90 | URL="$BASE_URL/commit/$REV" 91 | DIFFURL="$BASE_URL/compare/master...$REV" 92 | elif [ $REV ]; then 93 | if [ -d "$FILE" ]; then 94 | URL="$BASE_URL/tree/$REV/$RELPATH" 95 | else 96 | URL="$BASE_URL/blob/$REV/$RELPATH" 97 | fi 98 | DIFFURL= # not supported 99 | else 100 | URL="$BASE_URL/tree/$BRANCH_IN_URL/$RELPATH" 101 | DIFFURL= # not supported 102 | fi 103 | fi 104 | 105 | open() { 106 | if which start &>/dev/null && ! [[ `uname -s` =~ Darwin|Linux ]]; then 107 | start "$1" 108 | elif which xdg-open &>/dev/null && ! [[ `uname -s` =~ Darwin ]]; then 109 | xdg-open "$1" 110 | elif which gnome-open &>/dev/null && ! [[ `uname -s` =~ Darwin ]]; then 111 | gnome-open "$1" 112 | elif which kde-open &>/dev/null && ! [[ `uname -s` =~ Darwin ]]; then 113 | kde-open "$1" 114 | else 115 | command open "$1" 116 | fi 117 | } 118 | 119 | echo "# URL:" 120 | echo $URL 121 | 122 | if [ $DIFFURL ] && [ "$BRANCH" != "master" ]; then 123 | echo "# Diff URL:" 124 | echo $DIFFURL 125 | fi 126 | 127 | if [ $WEB ]; then 128 | open $URL 129 | fi 130 | -------------------------------------------------------------------------------- /git-out: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # git-out 4 | # 5 | # License: MIT 6 | # Copyright (c) 2012 Lennart C. L. Kats 7 | 8 | set -e 9 | 10 | QUIET= 11 | NO_FETCH= 12 | FETCHED= 13 | FETCHERS= 14 | ALL= 15 | 16 | for P in "$@"; do 17 | case $P in 18 | -q) 19 | QUIET=-q 20 | shift ;; 21 | -f) 22 | NO_FETCH=-f 23 | shift ;; 24 | -a|--all) 25 | ALL=-a 26 | shift ;; 27 | esac 28 | done 29 | 30 | MYBRANCH= 31 | SELECTION="$@" 32 | 33 | if echo "$SELECTION" | grep -iE 'head|local' >/dev/null \ 34 | || ([ "$SELECTION" == "" ] && ! [ "$ALL" ]); then 35 | SELECTION=`git-get-branch` 36 | MYBRANCH=1 37 | fi 38 | 39 | BRANCHES=`git branch --list $SELECTION | sed 's/\* //'` 40 | 41 | BRANCH=`git-get-branch 2>/dev/null` && 42 | BRANCHES="`git-get-branch` `echo "$BRANCHES" | grep -Ev "^$BRANCH\$"`" || : 43 | 44 | clearLine() { 45 | echo -ne '\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b' 46 | echo -ne '\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b' 47 | echo -ne '\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b' 48 | echo -ne '\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b' 49 | echo -ne ' ' 50 | echo -ne ' ' 51 | echo -ne '\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b' 52 | echo -ne '\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b' 53 | echo -ne '\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b' 54 | echo -ne '\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b' 55 | } 56 | 57 | if [ ! $NO_FETCH ]; then 58 | git fetch -q origin & 59 | FETCHER=$! 60 | fi 61 | 62 | while [ ! -e .git ] && [ "`pwd`" != "/" ]; do 63 | cd .. 64 | done 65 | GIT_OUT_CACHE=`cat .git/git-out-cache 2>/dev/null || echo` 66 | 67 | PRINTED_FIRST= 68 | for BRANCH in $BRANCHES; do 69 | if echo $BRANCH | grep '^_' >/dev/null || [ "$BRANCH" == "(no" ] || 70 | [ "$BRANCH" == "branch)" ]; then 71 | continue 72 | fi 73 | REVISION=`git rev-parse $BRANCH` 74 | if [[ "$GIT_OUT_CACHE" =~ "$REVISION" ]]; then 75 | continue 76 | elif ! git log -1 --oneline origin/$BRANCH &> /dev/null; then 77 | LOG=`git log --oneline --first-parent $BRANCH --not --remotes=origin` 78 | [ $PRINTED_FIRST ] && echo || PRINTED_FIRST=1 79 | if [ "$LOG" == "" ]; then 80 | echo -e "\033[09;32m$BRANCH\033[00m (empty)" 81 | else 82 | if [ ! $MYBRANCH ]; then 83 | echo -e "\033[01;32m$BRANCH\033[00m" 84 | fi 85 | if [ $QUIET ]; then 86 | echo "`echo "$LOG" | wc -l` commit(s)" 87 | else 88 | echo "$LOG" 89 | fi 90 | fi 91 | elif [ "`git log origin/$BRANCH..$BRANCH 2>/dev/null`" != "" ]; then 92 | [ $PRINTED_FIRST ] && echo || PRINTED_FIRST=1 93 | LOG=`git log --oneline --first-parent $BRANCH --not --remotes=origin` 94 | if [ ! $MYBRANCH ]; then 95 | echo -e "\033[01;32m$BRANCH\033[00m" 96 | fi 97 | if [ $QUIET ]; then 98 | echo "`echo "$LOG" | wc -l` commit(s)" 99 | else 100 | echo "$LOG" 101 | fi 102 | elif [ "`git log origin/master..$BRANCH 2>/dev/null`" != "" ]; then 103 | FETCHERS="$FETCHERS $BRANCH" 104 | else 105 | echo $REVISION >> .git/git-out-cache 106 | fi 107 | done 108 | 109 | if [ "$FETCHERS" != "" ]; then 110 | if [ ! $NO_FETCH ]; then 111 | [ $PRINTED_FIRST ] && echo || PRINTED_FIRST=1 112 | if which git-list-pull-requests &>/dev/null && [ "$GITHUB_REPOS" ]; then 113 | git-list-pull-requests -a >/tmp/.git-out-requests & 114 | PULLS=$! 115 | else 116 | echo >/tmp/.git-out-requests & 117 | PULLS=$! 118 | fi 119 | echo -n "Fetching info for `echo "$FETCHERS" | wc -w | grep -oE '[0-9]+'` remote branch(es)... " 120 | SUCCESS= 121 | wait $FETCHER 122 | clearLine 123 | FETCHED=1 124 | fi 125 | PRINTED_FIRST= 126 | for BRANCH in $FETCHERS; do 127 | if [ "`git log origin/master..$BRANCH 2>/dev/null`" != "" ]; then 128 | if [ ! $NO_FETCH ]; then 129 | wait $PULLS 130 | PULL_REQUESTS=`cat /tmp/.git-out-requests` 131 | fi 132 | if [ "`git log origin/master..$BRANCH 2>/dev/null`" != "" ]; then 133 | [ $PRINTED_FIRST ] && echo || PRINTED_FIRST=1 134 | if [ ! $NO_FETCH ] && echo "$PULL_REQUESTS" | grep "^$BRANCH\$" > /dev/null; then 135 | echo -e "$BRANCH (in pull request)" 136 | git is-current -f -q $BRANCH 137 | else 138 | echo -e "\033[01;32m$BRANCH\033[00m (unmerged in origin/master)" 139 | fi 140 | fi 141 | fi 142 | done 143 | fi 144 | -------------------------------------------------------------------------------- /git-cherry-copy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # git-cherry-copy 4 | # 5 | # License: MIT 6 | # Copyright (c) 2012 Lennart C. L. Kats 7 | 8 | set -e 9 | 10 | STASH= 11 | CURRENTBRANCH=`git-get-branch` 12 | MASTER=origin/master 13 | MAKENEWBRANCH= 14 | MAKE_NEW= 15 | NO_FETCH= 16 | MOVE_BRANCH= 17 | PULL_REQUEST= 18 | ORIGINAL_COMMAND="`basename $0` $*" 19 | 20 | while echo "$1" | grep -E "-" >/dev/null; do 21 | case "$1" in 22 | -b) 23 | MAKE_NEW=-b ;; 24 | -f) 25 | NO_FETCH=-f ;; 26 | -m) 27 | MOVE_BRANCH=-m ;; 28 | -p) 29 | PULL_REQUEST=-p ;; 30 | *) 31 | break ;; 32 | esac 33 | shift 34 | done 35 | 36 | if echo "$1" | grep origin/ >/dev/null; then 37 | MASTER=$1 38 | shift 39 | fi 40 | 41 | BRANCH=$1 42 | shift 43 | 44 | if [ "`git branch --list $BRANCH 2>/dev/null`" == "" ]; then 45 | if [ ! $MAKE_NEW ]; then 46 | echo Branch $BRANCH does not exist and option -b not specified. Aborting. >&2 47 | exit 1 48 | fi 49 | elif [ $MAKE_NEW ]; then 50 | echo Branch $BRANCH already exists and option -b specified. Aborting. >&2 51 | exit 1 52 | fi 53 | if [ "$1" == "" ]; then 54 | echo "Error: no commits to cherry-pick specified" >&2 55 | if [ "`git status --porcelain | grep -Ev '\?+ '`" != "" ]; then 56 | echo "Tip: did you mean to move your uncommited changes? Try: $ORIGINAL_COMMAND LOCAL" >&2 57 | fi 58 | echo Aborting. >&2 59 | exit 1 60 | fi 61 | 62 | if [ "$BRANCH" == "" ] || [ "$BRANCH" == "--help" ]; then 63 | echo "Usage: `basename $0` [OPTIONS...] [] " 64 | echo ' -b create a new branch BRANCH, rather than use an existing one' 65 | echo ' -f disable fetch step' 66 | echo ' -p make a pull request for the created branch' 67 | # echo ' -m` move the commit(s), instead of copying it' 68 | echo ' origin/BRANCH name for base branch' 69 | echo ' BRANCH name for new branch' 70 | echo " CHERRY a commit, a branch to pick the head from, or a range of commits [default: $CURRENTBRANCH]" 71 | echo " LOCAL take uncommited changes instead of a range of commits" 72 | exit 73 | fi 74 | 75 | if [ "$1" == local ] || [ "$1" == LOCAL ]; then 76 | echo '$ git stash' 77 | RESULT=`git stash save "changes stashed by git-branch-from-cherry"` 78 | if echo "$RESULT" | grep -iE 'No local changes' >/dev/null; then 79 | echo -e "error: no local changes. Aborting.">&2 80 | exit 1 81 | fi 82 | echo 83 | fi 84 | 85 | # -m is very conservative and only supports a few cases 86 | if [ "$MOVE_BRANCH" ]; then 87 | if [ "$*" == "local" ] || [ "$*" == LOCAL ]; then 88 | MOVE_BRANCH= 89 | elif echo "$*" | grep -Ei '^ (HEAD\^\^|HEAD~2) (HEAD\^|HEAD~1) HEAD$' >/dev/null; then 90 | MOVE_BRANCH="git reset --hard HEAD^^^" 91 | elif echo "$*" | grep -Ei '^(HEAD\^|HEAD~1) HEAD$' >/dev/null; then 92 | MOVE_BRANCH="git reset --hard HEAD^^" 93 | elif echo "$*" | grep -Ei '^HEAD$' >/dev/null || [ "`git rev-parse $*`" == "`git rev-parse HEAD`" ] || 94 | [ "$*" == "" ]; then 95 | MOVE_BRANCH="git reset --hard HEAD^" 96 | else 97 | echo "error: cannot use -m with this cherry-pick pattern. Aborting." >&2 98 | exit 1 99 | fi 100 | fi 101 | 102 | if [ ! $NO_FETCH ] && [ $MAKE_NEW ]; then 103 | M=`echo $MASTER | perl -pe 's/^origin\/(.*)/$1/'` 104 | echo "$ git fetch origin $M" 105 | git fetch -q origin $M 106 | echo 107 | fi 108 | 109 | if [ "$1" == local ] || [ "$1" == LOCAL ]; then 110 | if [ $MAKE_NEW ]; then 111 | echo "$ git checkout $MASTER" 112 | git checkout -q $MASTER 113 | echo 114 | fi 115 | echo "$ git checkout $MAKE_NEW $BRANCH" 116 | git checkout -q $MAKE_NEW $BRANCH 117 | echo 118 | echo "$ git stash pop" 119 | git stash pop -q 120 | echo 121 | echo "$ git status -s" 122 | git status -s 123 | exit 124 | else 125 | CHERRY=`git rev-parse "$@"` 126 | if [ $# == 1 ]; then 127 | echo "$ git log --oneline --first-parent -1 $@" 128 | git --no-pager log --oneline --color=never --first-parent -1 `git rev-parse "$@"` 129 | echo 130 | #else 131 | # echo "(can't show revision log for multiple revisions)" 132 | fi 133 | fi 134 | 135 | RESULT=`git stash save "changes stashed by git-branch-from-cherry"` 136 | if ! echo "$RESULT" | grep -iE 'No local changes' >/dev/null; then 137 | echo '$ git stash' 138 | echo 139 | STASH=1 140 | fi 141 | 142 | if [ $MAKE_NEW ]; then 143 | echo "$ git checkout $MASTER" 144 | git checkout -q $MASTER 145 | echo 146 | fi 147 | 148 | if ! ls `pwd` &>/dev/null; then 149 | PREVPWD=`pwd` 150 | while [ ! -e .git ] && [ "`pwd`" != "/" ]; do 151 | cd .. 152 | done 153 | echo "$ git checkout $CURRENTBRANCH" 154 | git checkout -q $CURRENTBRANCH 155 | echo 156 | if [ $STASH ]; then 157 | echo '$ git stash pop' 158 | git stash pop -q 159 | echo 160 | fi 161 | echo "error: cannot execute this from directory `pwd` that only exists in the curent branch. Aborted." 162 | cd $PREVPWD 163 | exit 1 164 | fi 165 | 166 | echo "$ git checkout $BRANCH" 167 | git checkout -q $MAKE_NEW $BRANCH 168 | echo 169 | 170 | echo "$ git cherry-pick $CHERRY" 171 | git cherry-pick $CHERRY 172 | echo 173 | 174 | echo "$ git checkout $CURRENTBRANCH" 175 | git checkout -q $CURRENTBRANCH 176 | echo 177 | 178 | if [ "$MOVE_BRANCH" ]; then 179 | echo "$ $MOVE_BRANCH" 180 | $MOVE_BRANCH 181 | echo 182 | fi 183 | 184 | if [ $STASH ]; then 185 | echo '$ git stash pop' 186 | git stash pop -q 187 | echo 188 | fi 189 | 190 | echo "Successfully cherry-picked to $BRANCH." 191 | echo 192 | 193 | if [ "$PULL_REQUEST" ]; then 194 | if [ $MAKE_NEW ]; then # already fetched 195 | NO_FETCH=-f 196 | fi 197 | echo "$ git-pull-request $BRANCH" 198 | git-pull-request $BRANCH 199 | fi 200 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | gitl 2 | ==== 3 | 4 | `gitl` is a collection of command-line git & github scripts. 5 | Most of these scripts operate fully in the command-line, but some 6 | of them can interact with github/bitbucket to open a pull request, or 7 | display some information about an item in the repository. 8 | 9 | Examples 10 | -------- 11 | 12 | Get a quick list of recent non-master commits in the current branch: 13 | 14 | $ git l 15 | dac6cc8 Fix git-bc LOCAL 16 | 8b0e105 Document git-bc -m option 17 | 4681a29 Fix missing newline 18 | 4e47ab8 Make git out independent of GITHUB_REPOS setting 19 | 8b46445 cleanup 20 | 21 | Create a pull request for the current branch: 22 | 23 | $ git pull-request 24 | # (opens your browser with github.com or bitbucket.org) 25 | 26 | Open a web page about the current repository, file, or revision in your browser: 27 | 28 | $ git info -w 29 | $ git info -w README.md 30 | $ git info -w HEAD 31 | 32 | Get an overview of all outgoing branches: 33 | 34 | $ git out --all 35 | master 36 | 2a6261b Something directly committed to master :o 37 | 38 | feature-x 39 | 8a8ffa1 Done. Going to bed now. 40 | 644abff WIP 41 | 42 | feature-y 43 | a8ffaa0 Add mysterious new feature 44 | 45 | Move the last commit into a separate feature branch and 46 | file a pull request for it: 47 | 48 | $ git cherry-move -b my-new-feature HEAD 49 | $ git pull-request my-new-feature 50 | # (opens your browser) 51 | 52 | Installation 53 | ------------ 54 | 55 | Just put these scripts on your PATH and they'll work. 56 | Instead of invoking a script directly, like `git-info`, 57 | you can also type `git info`. 58 | 59 | If you like, you can get a fancy prompt with some extra 60 | info about the current branch using `git prompt`. 61 | 62 | Command Reference 63 | ----------------- 64 | 65 | ### git-l 66 | 67 | Usage: `git l [BRANCH]` 68 | 69 | Quick log of the current or given branch, compared to origin/master. 70 | 71 | ### git-cherry-copy 72 | 73 | Extends or creates a branch with a cherry picking range of commits or local changes. 74 | 75 | Usage: `git cherry-copy [-f] [-b] [] ` 76 | 77 | * `-f` disable fetch step 78 | * `-b` create a new branch BRANCH, rather than use an existing one 79 | * `-p` make a pull request for the new branch 80 | * `origin/BRANCH` name for base branch 81 | * `BRANCH` name for new branch 82 | * `CHERRY` a commit, a branch to pick the head from, or a range of commits [default: HEAD] 83 | * `LOCAL` take uncommited changes instead of a range of commits 84 | 85 | ### git-cherry-move 86 | 87 | Extends or creates a branch with a cherry picking range of commits or local changes, 88 | moving them away from the current branch. 89 | 90 | Usage: `git cherry-move [-f] [-b] [] ` 91 | 92 | * `-f` disable fetch step 93 | * `-b` create a new branch BRANCH, rather than use an existing one 94 | * `-p` make a pull request for the new branch 95 | * `origin/BRANCH` name for base branch 96 | * `BRANCH` name for new branch 97 | * `CHERRY` a commit, a branch to pick the head from, or a range of commits [default: HEAD] 98 | * `LOCAL` take uncommited changes instead of a range of commits 99 | 100 | ### git-info 101 | 102 | Show information about the current repository or a path within the repository. 103 | 104 | Usage: `git info [-w] [PATH | REVISION]` 105 | 106 | * `-w` Open a web page in your browser 107 | * `PATH` A path to show info for 108 | 109 | ### git-is-current 110 | 111 | Determine if the current or specified branch is up-to-date compared to the current branch, 112 | or if merging the two branches would cause a conflict. 113 | 114 | Arguments: 115 | 116 | * `-f` Don't fetch before comparison 117 | * `-q` Be quiet 118 | * `origin/BRANCH` Compare to branch origin/BRANCH instead of origin/master 119 | * `BRANCH` Use selected branch 120 | 121 | ### git-out 122 | 123 | Show an overview of all outgoing branches. Branches starting with `_` are not fully shown. 124 | 125 | Arguments: 126 | 127 | * `-a|--all` Show all branches 128 | * `-f` Don't fetch 129 | * `BRANCH` Only show branch BRANCH 130 | 131 | ### git-pull-request 132 | 133 | Submit a GitHub pull request of the current or specified branch. Checks if it is 134 | still up-to-date using `git-is-current`, then opens your browser. 135 | 136 | Arguments: 137 | 138 | * `-f` Don't fetch before doing a pull request (faster, can't guarantee it won't conflict) 139 | * `-o` Open the page for an existing pull request 140 | * `BRANCH` Request branch BRANCH 141 | 142 | License (MIT) 143 | ------------- 144 | 145 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 146 | software and associated documentation files (the "Software"), to deal in the Software 147 | without restriction, including without limitation the rights to use, copy, modify, 148 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 149 | permit persons to whom the Software is furnished to do so, subject to the following 150 | conditions: 151 | 152 | The above copyright notice and this permission notice shall be included in all copies 153 | or substantial portions of the Software. 154 | 155 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 156 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 157 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 158 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 159 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 160 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 161 | 162 | --------------------------------------------------------------------------------