fixed git-changelog plugin

pull/1816/head
Gurkirat Singh 2021-01-24 18:01:51 +05:30 committed by Noah Gorny
parent 63f9f660a9
commit 77654875e5
2 changed files with 272 additions and 275 deletions

View File

@ -50,6 +50,7 @@ themes/modern
plugins/available/basher.plugin.bash plugins/available/basher.plugin.bash
plugins/available/cmd-returned-notify.plugin.bash plugins/available/cmd-returned-notify.plugin.bash
plugins/available/docker-machine.plugin.bash plugins/available/docker-machine.plugin.bash
plugins/available/git.plugin.bash
plugins/available/go.plugin.bash plugins/available/go.plugin.bash
plugins/available/goenv.plugin.bash plugins/available/goenv.plugin.bash
plugins/available/history.plugin.bash plugins/available/history.plugin.bash

View File

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