2017-01-20 15:12:32 -08:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
|
|
|
#
|
|
|
|
# --------------------------------------------------------
|
|
|
|
# Usage
|
|
|
|
# --------------------------------------------------------
|
|
|
|
#
|
|
|
|
# git top [branch-name]
|
|
|
|
#
|
|
|
|
# --------------------------------------------------------
|
|
|
|
# Summary
|
|
|
|
# --------------------------------------------------------
|
|
|
|
#
|
2020-11-04 09:45:58 -08:00
|
|
|
# Performs a pull from origin onto the default branch before rebasing the
|
|
|
|
# current branch on to the default branch.
|
2017-01-20 15:12:32 -08:00
|
|
|
#
|
|
|
|
# Author: Tony Grosinger
|
|
|
|
#
|
|
|
|
# --------------------------------------------------------
|
|
|
|
# Installation
|
|
|
|
# --------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Place the following in your .bashrc then place this file on your path.
|
|
|
|
#
|
|
|
|
# _git_top() {
|
|
|
|
# if [[ "${COMP_LINE}" =~ ^git\ top.*$ ]]; then
|
|
|
|
# __gitcomp_nl "$(__git_heads)"
|
|
|
|
# else
|
|
|
|
# __git_main
|
|
|
|
# fi
|
|
|
|
# }
|
|
|
|
#
|
2020-11-04 09:45:58 -08:00
|
|
|
# Ensure the following is in your .gitconfig alias section:
|
|
|
|
#
|
|
|
|
# default-branch = "!git symbolic-ref refs/remotes/origin/HEAD | cut -f4 -d/"
|
|
|
|
#
|
2017-01-20 15:12:32 -08:00
|
|
|
|
|
|
|
VERSION="v0.0.2"
|
|
|
|
|
|
|
|
GREEN="\e[32m"
|
|
|
|
BLUE="\e[34m"
|
|
|
|
RED="\e[91m"
|
|
|
|
CLEAR="\e[0m"
|
|
|
|
|
2020-11-04 09:45:58 -08:00
|
|
|
DEFAULT_BRANCH=$(git default-branch)
|
|
|
|
|
2017-01-20 15:12:32 -08:00
|
|
|
version() {
|
|
|
|
echo "git top ${VERSION}"
|
|
|
|
echo ""
|
|
|
|
}
|
|
|
|
|
|
|
|
usage() {
|
|
|
|
echo "usage: git top [branch-name]"
|
|
|
|
echo ""
|
|
|
|
echo "If branch name is omitted, current branch will be updated"
|
|
|
|
}
|
|
|
|
|
|
|
|
print_cmd() {
|
|
|
|
echo -e "${GREEN}>> ${CLEAR}${@}"
|
|
|
|
}
|
|
|
|
|
|
|
|
print_status() {
|
|
|
|
echo -e "${BLUE}${@}${CLEAR}"
|
|
|
|
}
|
|
|
|
|
|
|
|
print_fatal() {
|
|
|
|
echo -e >&2 "${RED}Fatal: ${CLEAR}${@}"
|
|
|
|
}
|
|
|
|
|
|
|
|
exec_cmd() {
|
|
|
|
print_cmd ${1}
|
|
|
|
${1}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
require_git_repo() {
|
|
|
|
git rev-parse --is-inside-work-tree > /dev/null 2>&1
|
|
|
|
|
|
|
|
if [ $? != 0 ]; then
|
|
|
|
print_fatal "Not a git repository"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
require_clean_work_tree() {
|
|
|
|
# Outputs an error to stderr if working tree is not clean, then exits
|
|
|
|
# Function retrieved from http://www.spinics.net/lists/git/msg142043.html
|
|
|
|
# http://stackoverflow.com/questions/3878624/how-do-i-programmatically-determine-if-there-are-uncommited-changes
|
|
|
|
|
|
|
|
# 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 "cannot $1: you have unstaged changes."
|
|
|
|
git diff-files --name-status -r --ignore-submodules -- >&2
|
|
|
|
err=1
|
|
|
|
fi
|
|
|
|
|
|
|
|
# Disallow uncommitted changes in the index
|
|
|
|
if ! git diff-index --cached --quiet HEAD --ignore-submodules --
|
|
|
|
then
|
|
|
|
echo >&2 "cannot $1: your index contains uncommitted changes."
|
|
|
|
git diff-index --cached --name-status -r --ignore-submodules HEAD -- >&2
|
|
|
|
err=1
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ $err = 1 ]
|
|
|
|
then
|
|
|
|
echo >&2 "Please commit or stash them."
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
checkout() {
|
|
|
|
exec_cmd "git checkout -q ${1}"
|
|
|
|
}
|
|
|
|
|
|
|
|
pull_remote() {
|
2020-11-04 09:45:58 -08:00
|
|
|
checkout "${DEFAULT_BRANCH}"
|
2017-01-20 15:12:32 -08:00
|
|
|
exec_cmd "git pull -r -q"
|
|
|
|
|
|
|
|
if [ $? != 0 ]; then
|
2020-11-04 09:45:58 -08:00
|
|
|
echo >&2 "Could not pull on ${DEFAULT_BRANCH}, please check that upstream is set and try again."
|
2017-01-20 15:12:32 -08:00
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
rebase() {
|
|
|
|
local startbranch=${1}
|
2020-11-04 09:45:58 -08:00
|
|
|
exec_cmd "git rebase -q ${DEFAULT_BRANCH} ${startbranch}"
|
2017-01-20 15:12:32 -08:00
|
|
|
|
|
|
|
if [ $? != 0 ]; then
|
2020-11-04 09:45:58 -08:00
|
|
|
echo >&2 "Could not rebase ${startbranch} on ${DEFAULT_BRANCH}, rolling back changes."
|
2017-01-20 15:12:32 -08:00
|
|
|
echo >&2 "Please manually resolve conflicts."
|
|
|
|
|
|
|
|
git rebase --abort
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
main() {
|
|
|
|
require_git_repo
|
|
|
|
local startbranch=`git rev-parse --abbrev-ref HEAD`
|
|
|
|
|
|
|
|
if [ $# = 1 ]; then
|
|
|
|
case "$1" in
|
|
|
|
"-h"|"--help")
|
|
|
|
usage
|
|
|
|
exit 0
|
|
|
|
;;
|
|
|
|
"-v"|"--version")
|
|
|
|
version
|
|
|
|
exit 0
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
startbranch=$1
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
elif [ $# != 0 ]; then
|
|
|
|
print_fatal "Invalid number of arguments provided"
|
|
|
|
echo ""
|
|
|
|
usage
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
git show-ref --verify -q refs/heads/${startbranch}
|
|
|
|
if [ $? != 0 ]; then
|
|
|
|
print_fatal "Branch \"${startbranch}\" does not exist"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
require_clean_work_tree
|
|
|
|
|
2020-11-04 09:45:58 -08:00
|
|
|
git fetch -p
|
|
|
|
|
|
|
|
if [ ${startbranch} = "${DEFAULT_BRANCH}" ]; then
|
|
|
|
print_status "Already on ${DEFAULT_BRANCH}, only performing git pull"
|
2017-01-20 15:12:32 -08:00
|
|
|
pull_remote
|
|
|
|
else
|
|
|
|
pull_remote
|
|
|
|
rebase $startbranch
|
|
|
|
fi
|
|
|
|
|
|
|
|
checkout $startbranch
|
|
|
|
|
|
|
|
print_status "Branch update complete."
|
|
|
|
}
|
|
|
|
|
|
|
|
main "$@"
|
|
|
|
|