bin/git-cut-branch
#!/usr/bin/env bash
#
# https://github.com/rtomayko/dotfiles
#
#/ Usage: git-cut-branch <name>
#/ Create a new branch named <name> pointed at HEAD and reset the current branch
#/ to the head of its tracking branch. This is useful when working on master and
#/ you realize you should be on a topic branch.
set -e
# bail out with message to stderr and exit status 1
die() {
# shellcheck disable=SC2086
echo "$(basename $0):" "$@" 1>&2
exit 1
}
# write a short sha for the given sha
shortsha() {
echo "$1" |cut -c1-7
}
# show usage
# shellcheck disable=SC2166
[ -z "$1" -o "$1" = "--help" ] && {
grep '^#/' "$0" |cut -c4-
exit 2
}
# first argument is the new branch name
branch="$1"
# get the current branch for HEAD in refs/heads/<branch> form
ref=$(git symbolic-ref -q HEAD)
sha=$(git rev-parse HEAD)
[ -n "$ref" ] ||
die "you're not on a branch"
# just the branch name please
current=$(echo "$ref" | sed 's@^refs/heads/@@')
[ -n "$current" ] ||
die "you're in a weird place; get on a local branch"
# figure out what branch we're currently tracking
remote=$(git config --get "branch.$current.remote" || true)
merge=$(git config --get "branch.$current.merge" | sed 's@refs/heads/@@')
# build up a sane <remote>/<branch> name
# shellcheck disable=SC2166
if [ -n "$remote" -a -n "$merge" ]; then
tracking="$remote/$merge"
elif [ -n "$merge" ]; then
tracking="$merge"
else
die "$current is not tracking anything"
fi
# make sure there's no changes before we reset hard
if ! git diff-index --quiet --cached HEAD || ! git diff-files --quiet
then die "cannot cut branch with changes to index or working directory"
fi
# reset the current branch to its tracking branch, create the new branch also
# tracking the original branch, and switch to it.
git branch "$branch"
git reset -q --hard "$tracking"
git checkout -q "$branch"
git branch --set-upstream-to "$branch" "$tracking"
git reset -q --hard "$sha"
# shellcheck disable=SC2086,SC2046
echo "[$(shortsha "$sha")...$(shortsha $(git rev-parse $tracking))] $current"
# shellcheck disable=SC2046
echo "[0000000...$(shortsha $(git rev-parse HEAD))] $branch"