mirror of
https://github.com/tj/git-extras.git
synced 2026-09-10 07:26:17 -04:00
81 lines
1.7 KiB
Bash
Executable file
81 lines
1.7 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
SQUASH_MSG=
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
--squash-msg)
|
|
SQUASH_MSG=1
|
|
;;
|
|
*)
|
|
# set the argument back
|
|
set -- "$@" "$arg"
|
|
;;
|
|
esac
|
|
|
|
shift
|
|
done
|
|
|
|
src="$1"
|
|
msg="$2"
|
|
if [[ -n "$msg" ]] && [[ -n "$SQUASH_MSG" ]]; then
|
|
>&2 echo "When commit message is given, --squash-msg is not allowed."
|
|
exit 1
|
|
fi
|
|
|
|
is_branch() {
|
|
git show-ref --verify --quiet "refs/heads/$src"
|
|
}
|
|
|
|
is_commit_reference() {
|
|
git rev-parse --verify --quiet "$src" > /dev/null 2>&1
|
|
}
|
|
|
|
is_on_current_branch() {
|
|
local commit_sha
|
|
commit_sha=$(git rev-parse "$src")
|
|
git rev-list HEAD |
|
|
grep -q -- "$commit_sha"
|
|
}
|
|
|
|
commit_if_msg_provided() {
|
|
if test -n "$msg"; then
|
|
git commit -a -m "$msg"
|
|
fi
|
|
}
|
|
|
|
prompt_continuation_if_squashing_master() {
|
|
if [[ $src =~ ^master$ ]]; then
|
|
read -p "Warning: squashing '$src'! Continue [y/N]? " -r
|
|
if ! [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
echo "Exiting"
|
|
exit 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
squash_branch() {
|
|
prompt_continuation_if_squashing_master
|
|
if [ -n "$SQUASH_MSG" ]; then
|
|
base=$(git merge-base "$src" @)
|
|
msg=$(git log "$base".."$src" --format="%s%n%n%b" --no-merges --reverse)
|
|
fi
|
|
git merge --squash "$src" || exit 1 # quits if `git merge` fails
|
|
commit_if_msg_provided
|
|
}
|
|
|
|
squash_current_branch() {
|
|
if [ -n "$SQUASH_MSG" ]; then
|
|
msg=$(git log "$src"..@ --format="%s%n%n%b" --no-merges --reverse)
|
|
fi
|
|
git reset --soft "$src" || exit 1 # quits if `git reset` fails
|
|
commit_if_msg_provided
|
|
}
|
|
|
|
if is_branch; then
|
|
squash_branch
|
|
elif is_commit_reference && is_on_current_branch; then
|
|
squash_current_branch
|
|
else
|
|
echo "Source branch or commit reference required." 1>&2 && exit 1
|
|
fi
|