Is there a way to squash a number of commits non-interactively?
Make sure your working tree is clean, then
git reset --soft HEAD~3
git commit -m 'new commit message'
To add to the answer by wilhelmtell I find it convenient to soft reset to HEAD~2
and then amending the commit of HEAD~3
:
git reset --soft HEAD~2
git commit --all --amend --no-edit
This will merge all commits to the HEAD~3
commit and use its commit message. Be sure to start from a clean working tree.
I personally like wilhelmtell's solution:
git reset --soft HEAD~3
git commit -m 'new commit message'
However, I made an alias with some error checking so that you can do this:
g.squash 3 'my commit message'
I recommend setting up aliases that actually run scripts so that it is easier to (a) code up your scripts and (b) do more complex work with error checking. Below is a script that does the work of squashing. I put that in a scripts folder in my HOME path.
Script for squashing (squash.sh)
#!/bin/bash
#
#get number of commits to squash
squashCount=$1
#get the commit message
shift
commitMsg=$@
#regular expression to verify that squash number is an integer
regex='^[0-9]+$'
echo "---------------------------------"
echo "Will squash $squashCount commits"
echo "Commit message will be '$commitMsg'"
echo "...validating input"
if ! [[ $squashCount =~ $regex ]]
then
echo "Squash count must be an integer."
elif [ -z "$commitMsg" ]
then
echo "Invalid commit message. Make sure string is not empty"
else
echo "...input looks good"
echo "...proceeding to squash"
git reset --soft HEAD~$squashCount
git commit -m "$commitMsg"
echo "...done"
fi
echo
exit 0
Then to hook up that squash.sh script to an alias, I add the following to my .zprofile:
export PATH="$PATH:$HOME/scripts" # Add scripts folder to PATH
...
alias g.squash='function _gSquash(){ sh squash.sh $1 $2; };_gSquash'
...
Note: You can make your alias anything you want. I have my a lot of my git shortcuts as g.<myCommand>