Skip to content

Instantly share code, notes, and snippets.

@hi-ogawa
Last active April 13, 2022 01:40
Show Gist options
  • Save hi-ogawa/be77a7a27ef8c1f60a463157f0f30930 to your computer and use it in GitHub Desktop.
Save hi-ogawa/be77a7a27ef8c1f60a463157f0f30930 to your computer and use it in GitHub Desktop.
squash-and-merge.sh
#!/bin/bash
set -eux -o pipefail
# Usage
# repository=<...> branch=<...> message=<...> bash squash-and-merge.sh
# validate arguments
[ -z "${repository:-}" ] && { echo "required 'repository'"; exit 1; }
[ -z "${branch:-}" ] && { echo "required 'branch'"; exit 1; }
[ -z "${message:-}" ] && { echo "required 'message'"; exit 1; }
# create temporary directory
tmp_dir=$(mktemp -d)
trap 'rm -rf -- "$tmp_dir"' EXIT
# clone repository
git clone "$repository" "$tmp_dir"
cd "$tmp_dir"
# find default branch
default_branch=$(git rev-parse --abbrev-ref HEAD)
# fetch branch
git fetch origin "$branch"
git checkout -b "$branch" "origin/$branch"
# verify branch is up-to-date (cf. https://stackoverflow.com/questions/20433867/git-ahead-behind-info-between-master-and-branch)
if ! [ "$(git rev-list --left-only --count "$default_branch...HEAD")" = "0" ]; then
echo "branch '$branch' is not up-to-date to '$default_branch'"
exit 1
fi
# extract git log
message_body=$(git log --pretty='format:* %s%n' --reverse "$default_branch...HEAD")
# squash commits
git reset "$default_branch"
git add .
git commit -F - <<EOF
${message}
${message_body}
EOF
# confirm
git diff --name-only "$default_branch"
git --no-pager log "$default_branch"...HEAD
echo -n "Are you sure to force push? [y/n] "
read -e -r -n 1
case "$REPLY" in
y) ;;
*) echo "canceled"; exit 1 ;;
esac
# force push
git push origin "$branch" --force
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment