Skip to content

Instantly share code, notes, and snippets.

@rk295
Created March 5, 2018 10:50
Show Gist options
  • Save rk295/dfeb74f3ad795ff6629b17be3910bf51 to your computer and use it in GitHub Desktop.
Save rk295/dfeb74f3ad795ff6629b17be3910bf51 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# Simulate a merge from the current branch into the target. Squash that merge
# into a single commit. Make that commit the new HEAD of the current branch.
#
# Based on work from the following sites:
# https://gist.github.com/patik/b8a9dc5cd356f9f6f980
# http://stackoverflow.com/questions/3697178/git-merge-all-changes-from-another-branch-as-a-single-commit
# https://makandracards.com/makandra/527-squash-several-git-commits-into-a-single-commit
against=$1
if [[ -z "$against" ]]; then
echo "Missing branch or commit we squash against" >&2
exit 1
fi
against=$(git rev-parse "$against" 2> /dev/null)
current=$(git symbolic-ref HEAD 2> /dev/null)
undoCommit=$(git rev-parse HEAD 2> /dev/null)
if [[ -z "$against" ]]; then
echo "Unable to find commit to squash against" >&2
exit 1
fi
if [[ -z "$current" ]]; then
echo "Unable to find reference to current branch" >&2
exit 1
fi
current=${current#refs/heads/}
echo "Squashing $current against $against"
# Check if this is a clean repository
if git status | grep "^nothing to commit, working" -q; then
stashed=false
else
stashed=true
git stash save -a -u
fi
git checkout -b "squash-$against" "$against"
git merge --squash "$current"
git commit
squashedCommit=$(git rev-parse HEAD)
git checkout "$current"
git reset --hard "$squashedCommit"
git branch -D "squash-$against"
if $stashed; then
git stash pop
fi
echo "To undo this action, run this command:"
echo " git reset --hard $undoCommit"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment