diff --git a/plugins/available/git.plugin.bash b/plugins/available/git.plugin.bash index b2c05b60..02d6d9d3 100644 --- a/plugins/available/git.plugin.bash +++ b/plugins/available/git.plugin.bash @@ -2,140 +2,140 @@ cite about-plugin about-plugin 'git helper functions' function git_remote { - about 'adds remote $GIT_HOSTING:$1 to current repo' - group 'git' - - echo "Running: git remote add origin ${GIT_HOSTING}:$1.git" - git remote add origin $GIT_HOSTING:$1.git + about 'adds remote $GIT_HOSTING:$1 to current repo' + group 'git' + + echo "Running: git remote add origin ${GIT_HOSTING}:$1.git" + git remote add origin $GIT_HOSTING:$1.git } function git_first_push { - about 'push into origin refs/heads/master' - group 'git' - - echo "Running: git push origin master:refs/heads/master" - git push origin master:refs/heads/master + about 'push into origin refs/heads/master' + group 'git' + + echo "Running: git push origin master:refs/heads/master" + git push origin master:refs/heads/master } function git_pub() { - about 'publishes current branch to remote origin' - group 'git' - BRANCH=$(git rev-parse --abbrev-ref HEAD) - - echo "Publishing ${BRANCH} to remote origin" - git push -u origin $BRANCH + about 'publishes current branch to remote origin' + group 'git' + BRANCH=$(git rev-parse --abbrev-ref HEAD) + + echo "Publishing ${BRANCH} to remote origin" + git push -u origin $BRANCH } function git_revert() { - about 'applies changes to HEAD that revert all changes after this commit' - group 'git' - - git reset $1 - git reset --soft HEAD@{1} - git commit -m "Revert to ${1}" - git reset --hard + about 'applies changes to HEAD that revert all changes after this commit' + group 'git' + + git reset $1 + git reset --soft HEAD@{1} + git commit -m "Revert to ${1}" + git reset --hard } function git_rollback() { - about 'resets the current HEAD to this commit' - group 'git' - - function is_clean() { - if [[ $(git diff --shortstat 2> /dev/null | tail -n1) != "" ]]; then - echo "Your branch is dirty, please commit your changes" - kill -INT $$ + about 'resets the current HEAD to this commit' + group 'git' + + function is_clean() { + if [[ $(git diff --shortstat 2> /dev/null | tail -n1) != "" ]]; then + echo "Your branch is dirty, please commit your changes" + kill -INT $$ + fi + } + + function commit_exists() { + git rev-list --quiet $1 + status=$? + if [ $status -ne 0 ]; then + echo "Commit ${1} does not exist" + kill -INT $$ + fi + } + + function keep_changes() { + while true + do + read -p "Do you want to keep all changes from rolled back revisions in your working tree? [Y/N]" RESP + case $RESP + in + [yY]) + echo "Rolling back to commit ${1} with unstaged changes" + git reset $1 + break + ;; + [nN]) + echo "Rolling back to commit ${1} with a clean working tree" + git reset --hard $1 + break + ;; + *) + echo "Please enter Y or N" + esac + done + } + + if [ -n "$(git symbolic-ref HEAD 2> /dev/null)" ]; then + is_clean + commit_exists $1 + + while true + do + read -p "WARNING: This will change your history and move the current HEAD back to commit ${1}, continue? [Y/N]" RESP + case $RESP + in + [yY]) + keep_changes $1 + break + ;; + [nN]) + break + ;; + *) + echo "Please enter Y or N" + esac + done + else + echo "you're currently not in a git repository" fi - } - - function commit_exists() { - git rev-list --quiet $1 - status=$? - if [ $status -ne 0 ]; then - echo "Commit ${1} does not exist" - kill -INT $$ - fi - } - - function keep_changes() { - while true - do - read -p "Do you want to keep all changes from rolled back revisions in your working tree? [Y/N]" RESP - case $RESP - in - [yY]) - echo "Rolling back to commit ${1} with unstaged changes" - git reset $1 - break - ;; - [nN]) - echo "Rolling back to commit ${1} with a clean working tree" - git reset --hard $1 - break - ;; - *) - echo "Please enter Y or N" - esac - done - } - - if [ -n "$(git symbolic-ref HEAD 2> /dev/null)" ]; then - is_clean - commit_exists $1 - - while true - do - read -p "WARNING: This will change your history and move the current HEAD back to commit ${1}, continue? [Y/N]" RESP - case $RESP - in - [yY]) - keep_changes $1 - break - ;; - [nN]) - break - ;; - *) - echo "Please enter Y or N" - esac - done - else - echo "you're currently not in a git repository" - fi } function git_remove_missing_files() { - about "git rm's missing files" - group 'git' - - git ls-files -d -z | xargs -0 git update-index --remove + about "git rm's missing files" + group 'git' + + git ls-files -d -z | xargs -0 git update-index --remove } # Adds files to git's exclude file (same as .gitignore) function local-ignore() { - about 'adds file or path to git exclude file' - param '1: file or path fragment to ignore' - group 'git' - echo "$1" >> .git/info/exclude + about 'adds file or path to git exclude file' + param '1: file or path fragment to ignore' + group 'git' + echo "$1" >> .git/info/exclude } # get a quick overview for your git repo function git_info() { about 'overview for your git repo' group 'git' - + if [ -n "$(git symbolic-ref HEAD 2> /dev/null)" ]; then # print informations echo "git repo overview" echo "-----------------" echo - + # print all remotes and thier details for remote in $(git remote show); do echo $remote: git remote show $remote echo done - + # print status of working repo echo "status:" if [ -n "$(git status -s 2> /dev/null)" ]; then @@ -143,133 +143,168 @@ function git_info() { else echo "working directory is clean" fi - + # print at least 5 last log entries echo echo "log:" git log -5 --oneline echo - + else echo "you're currently not in a git repository" - + fi } function git_stats { about 'display stats per author' group 'git' - -# awesome work from https://github.com/esc/git-stats -# including some modifications - -if [ -n "$(git symbolic-ref HEAD 2> /dev/null)" ]; then - echo "Number of commits per author:" - git --no-pager shortlog -sn --all - AUTHORS=$( git shortlog -sn --all | cut -f2 | cut -f1 -d' ') - LOGOPTS="" - if [ "$1" == '-w' ]; then - LOGOPTS="$LOGOPTS -w" - shift + + # awesome work from https://github.com/esc/git-stats + # including some modifications + + if [ -n "$(git symbolic-ref HEAD 2> /dev/null)" ]; then + echo "Number of commits per author:" + git --no-pager shortlog -sn --all + AUTHORS=$( git shortlog -sn --all | cut -f2 | cut -f1 -d' ') + LOGOPTS="" + if [ "$1" == '-w' ]; then + LOGOPTS="$LOGOPTS -w" + shift + fi + if [ "$1" == '-M' ]; then + LOGOPTS="$LOGOPTS -M" + shift + fi + if [ "$1" == '-C' ]; then + LOGOPTS="$LOGOPTS -C --find-copies-harder" + shift + fi + for a in $AUTHORS + do + echo '-------------------' + echo "Statistics for: $a" + echo -n "Number of files changed: " + git log $LOGOPTS --all --numstat --format="%n" --author=$a | cut -f3 | sort -iu | wc -l + echo -n "Number of lines added: " + git log $LOGOPTS --all --numstat --format="%n" --author=$a | cut -f1 | awk '{s+=$1} END {print s}' + echo -n "Number of lines deleted: " + git log $LOGOPTS --all --numstat --format="%n" --author=$a | cut -f2 | awk '{s+=$1} END {print s}' + echo -n "Number of merges: " + git log $LOGOPTS --all --merges --author=$a | grep -c '^commit' + done + else + echo "you're currently not in a git repository" fi - if [ "$1" == '-M' ]; then - LOGOPTS="$LOGOPTS -M" - shift - fi - if [ "$1" == '-C' ]; then - LOGOPTS="$LOGOPTS -C --find-copies-harder" - shift - fi - for a in $AUTHORS - do - echo '-------------------' - echo "Statistics for: $a" - echo -n "Number of files changed: " - git log $LOGOPTS --all --numstat --format="%n" --author=$a | cut -f3 | sort -iu | wc -l - echo -n "Number of lines added: " - git log $LOGOPTS --all --numstat --format="%n" --author=$a | cut -f1 | awk '{s+=$1} END {print s}' - echo -n "Number of lines deleted: " - git log $LOGOPTS --all --numstat --format="%n" --author=$a | cut -f2 | awk '{s+=$1} END {print s}' - echo -n "Number of merges: " - git log $LOGOPTS --all --merges --author=$a | grep -c '^commit' - done -else - echo "you're currently not in a git repository" -fi } function gittowork() { - about 'Places the latest .gitignore file for a given project type in the current directory, or concatenates onto an existing .gitignore' - group 'git' - param '1: the language/type of the project, used for determining the contents of the .gitignore file' - example '$ gittowork java' - - result=$(curl -L "https://www.gitignore.io/api/$1" 2>/dev/null) - - if [[ $result =~ ERROR ]]; then - echo "Query '$1' has no match. See a list of possible queries with 'gittowork list'" - elif [[ $1 = list ]]; then - echo "$result" - else - if [[ -f .gitignore ]]; then - result=`echo "$result" | grep -v "# Created by http://www.gitignore.io"` - echo ".gitignore already exists, appending..." - echo "$result" >> .gitignore + about 'Places the latest .gitignore file for a given project type in the current directory, or concatenates onto an existing .gitignore' + group 'git' + param '1: the language/type of the project, used for determining the contents of the .gitignore file' + example '$ gittowork java' + + result=$(curl -L "https://www.gitignore.io/api/$1" 2>/dev/null) + + if [[ $result =~ ERROR ]]; then + echo "Query '$1' has no match. See a list of possible queries with 'gittowork list'" + elif [[ $1 = list ]]; then + echo "$result" else - echo "$result" > .gitignore + if [[ -f .gitignore ]]; then + result=`echo "$result" | grep -v "# Created by http://www.gitignore.io"` + echo ".gitignore already exists, appending..." + echo "$result" >> .gitignore + else + echo "$result" > .gitignore + fi fi - fi } function gitignore-reload() { - about 'Empties the git cache, and readds all files not blacklisted by .gitignore' - group 'git' - example '$ gitignore-reload' - + about 'Empties the git cache, and readds all files not blacklisted by .gitignore' + group 'git' + example '$ gitignore-reload' + # The .gitignore file should not be reloaded if there are uncommited changes. - # Firstly, require a clean work tree. The function require_clean_work_tree() - # was stolen with love from https://www.spinics.net/lists/git/msg142043.html - - # Begin require_clean_work_tree() - - # Update the index - git update-index -q --ignore-submodules --refresh - err=0 - - # Disallow unstaged changes in the working tree - if ! git diff-files --quiet --ignore-submodules -- - then - echo >&2 "ERROR: Cannot reload .gitignore: Your index contains unstaged changes." - git diff-index --cached --name-status -r --ignore-submodules HEAD -- >&2 - err=1 - fi - - # Disallow uncommited changes in the index - if ! git diff-index --cached --quiet HEAD --ignore-submodules - then - echo >&2 "ERROR: Cannot reload .gitignore: Your index contains uncommited changes." - git diff-index --cached --name-status -r --ignore-submodules HEAD -- >&2 - err=1 - fi - - # Prompt user to commit or stash changes and exit - if [ $err = 1 ] - then - echo >&2 "Please commit or stash them." - fi - - # End require_clean_work_tree() - - # If we're here, then there are no uncommited or unstaged changes dangling around. - # Proceed to reload .gitignore - if [ $err = 0 ]; then - # Remove all cached files - git rm -r --cached . - - # Re-add everything. The changed .gitignore will be picked up here and will exclude the files - # now blacklisted by .gitignore - echo >&2 "Running git add ." - git add . - echo >&2 "Files readded. Commit your new changes now." - fi + # Firstly, require a clean work tree. The function require_clean_work_tree() + # was stolen with love from https://www.spinics.net/lists/git/msg142043.html + + # Begin require_clean_work_tree() + + # Update the index + git update-index -q --ignore-submodules --refresh + err=0 + + # Disallow unstaged changes in the working tree + if ! git diff-files --quiet --ignore-submodules -- + then + echo >&2 "ERROR: Cannot reload .gitignore: Your index contains unstaged changes." + git diff-index --cached --name-status -r --ignore-submodules HEAD -- >&2 + err=1 + fi + + # Disallow uncommited changes in the index + if ! git diff-index --cached --quiet HEAD --ignore-submodules + then + echo >&2 "ERROR: Cannot reload .gitignore: Your index contains uncommited changes." + git diff-index --cached --name-status -r --ignore-submodules HEAD -- >&2 + err=1 + fi + + # Prompt user to commit or stash changes and exit + if [ $err = 1 ] + then + echo >&2 "Please commit or stash them." + fi + + # End require_clean_work_tree() + + # If we're here, then there are no uncommited or unstaged changes dangling around. + # Proceed to reload .gitignore + if [ $err = 0 ]; then + # Remove all cached files + git rm -r --cached . + + # Re-add everything. The changed .gitignore will be picked up here and will exclude the files + # now blacklisted by .gitignore + echo >&2 "Running git add ." + git add . + echo >&2 "Files readded. Commit your new changes now." + fi } + +function git-changelog(){ + about 'Creates the git changelog from one point to another by date' + group 'git' + example '$ git-changelog origin/master...origin/release [md|txt]' + + if [[ "$1" != *"..."* ]] + then + echo "Please include the valid 'diff' to make changelog" + return 1 + fi + + local NEXT=$(date +%F) + + if [[ "$2" == "md" ]] + then + echo "# CHANGELOG $1" + + git log $1 --no-merges --format="%cd" --date=short | sort -u -r | while read DATE ; do + echo + echo "### $DATE" + GIT_PAGER=cat git log --no-merges --format=" * (%h) %s by [%an](mailto:%ae)" --since="$DATE 00:00:00" --until="$DATE 24:00:00" + NEXT=$DATE + done + else + echo "CHANGELOG $1" + echo ---------------------- + git log $1 --no-merges --format="%cd" --date=short | sort -u -r | while read DATE ; do + echo + echo [$DATE] + GIT_PAGER=cat git log --no-merges --format=" * (%h) %s by %an <%ae>" --since="$DATE 00:00:00" --until="$DATE 24:00:00" + NEXT=$DATE + done + fi +} \ No newline at end of file