Skip to content

Instantly share code, notes, and snippets.

@Pierstoval
Last active August 29, 2015 14:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Pierstoval/d8135e17dd9214e7a005 to your computer and use it in GitHub Desktop.
Save Pierstoval/d8135e17dd9214e7a005 to your computer and use it in GitHub Desktop.
Git squash extension. Put this file on /usr/local/share/git-squash/git-squash on most unix distribs
#!/bin/bash
# Author: Joel Nothman
# Optimized by Pierstoval
# Under BSD-2 license
# See https://github.com/jnothman/git-squash
# See https://github.com/Pierstoval/git-squash
usage() {
echo ""
echo Usage: git squash '[-m <commit msg>] [-a|--append] [-f|--full] <base>'
echo " -m <commit msg> Used to provide a new message for the squashed commit"
echo " -a If specified, the commit msg will be followed by all squashed commits informations"
echo " -f|--full If '-a|--append' is specified, all the messages will contain more informations (author, date...)"
exit 1
}
unset base
unset message
unset append
full=false
base=""
append=false
appendMessage=""
commitsCount=0
message=""
while [ -n "$1" ]
do
case "$1" in
-h)
usage
;;
-m)
shift
if [ -z "$1" ]
then
echo '-m requires an argument' >&2
usage
fi
if [ -n "$message" ]
then
message+=$'\n\n'"$1"
else
message="$1"
fi
;;
-f|--full)
full=true
;;
-a|--append-message)
append=true
;;
*)
if [ -z "$base" ]
then
base="$1"
else
echo 'Multiple bases specified' >&2
usage
fi
esac
shift
done
if [ -z "$base" ]
then
echo 'No base ref provided' >&2
usage
fi
if [ "$append" = true ]
then
nl=$'\n'
commitsCount=`git rev-list ${base}..HEAD --count`
if [ "$commitsCount" -eq "0" ]
then
echo "No commit for base '$base'."
exit 1
fi
appendMessage+=$'\n'
appendMessage+=$'\n'
if [ "$full" = true ]
then
appendMessage+=`git log --pretty=format:"[%h] %ad - %cn <%ce>$nl%s$nl%b" -n${commitsCount}`
else
appendMessage+=`git log --pretty=format:"[%h] %s %b" -n${commitsCount}`
fi
fi
seq_ed="$(mktemp -t squash_edXXXXXX)" &&
echo '#!'$(which bash)'
echo Squashing... >&2
tmp="$(mktemp -t squash_outXXXXXX)"
awk '"'"'NR != 1 { sub(/^pick/, "squash") } {print}'"'"' "$1" > "$tmp"
mv "$tmp" "$1"
' > $seq_ed &&
chmod +x "$seq_ed" &&
echo 'Warning: Forgetting local history. To revert, use:
$ git reset --hard' $(git rev-parse --short HEAD) >&2
if [ -n "$message" ]
then
GIT_SEQUENCE_EDITOR=$seq_ed GIT_EDITOR=touch git rebase -i $base
else
GIT_SEQUENCE_EDITOR=$seq_ed git rebase -i $base
fi
if [ -n "$message" ]
then
echo 'Updating commit message' >&2
git commit --amend -m "$message$appendMessage" | head -n1
fi
rm -r "$seq_ed"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment