Is there a way to squash a number of commits non-interactively?

GitInteractiveRebaseSquash

Git Problem Overview


I'm trying to squash a range of commits - HEAD to HEAD~3. Is there a quick way to do this, or do I need to use rebase --interactive?

Git Solutions


Solution 1 - Git

Make sure your working tree is clean, then

git reset --soft HEAD~3
git commit -m 'new commit message'

Solution 2 - Git

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>

Solution 3 - Git

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.

Solution 4 - Git

I used:

EDITOR="sed -i '2,/^$/s/^pick\b/s/'" git rebase -i <ref>

Worked quite fine. Just don't try to have a commit log with a line that starts with "pick" :)

Solution 5 - Git

Use the following command to squash the last 4 commits within the last commit:

git squash 4

With the alias:

squash = !"f() { NL=$1; GIT_EDITOR=\"sed -i '2,$NL s/pick/squash/;/# This is the 2nd commit message:/,$ {d}'\"; git rebase -i HEAD~$NL; }; f"
sq = !git squash $1
sqpsf = !git squash $1 && git psf 

From https://github.com/brauliobo/gitconfig/blob/master/configs/.gitconfig

Solution 6 - Git

Here is a one liner to squash the last 2 commits. In this example, the message of second last commit will be retained. You may change the message as you wish.

git commit -am "$(git log -1 --skip=1 --pretty=%B | xargs && git reset --soft HEAD~2)"

This command will be very useful if you create an alias for this command and use the alias instead.

Solution 7 - Git

To squash everything since the branch was forked from master:

git reset --soft $(git merge-base --fork-point master) \
  && git commit --verbose --reedit-message=HEAD --reset-author

Solution 8 - Git

You can get pretty close with

git rebase --onto HEAD4 HEAD master

This assumes you're on master with a linear history. It's not quite a squash because it discards the intermediate commits. You'd need to amend the new HEAD to modify the commit message.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPhillipView Question on Stackoverflow
Solution 1 - GitwilhelmtellView Answer on Stackoverflow
Solution 2 - Gitn8trView Answer on Stackoverflow
Solution 3 - GitharmoniousView Answer on Stackoverflow
Solution 4 - GitJulien WajsbergView Answer on Stackoverflow
Solution 5 - GitbraulioboView Answer on Stackoverflow
Solution 6 - GitJasir KTView Answer on Stackoverflow
Solution 7 - GitAndyView Answer on Stackoverflow
Solution 8 - GitGreg BaconView Answer on Stackoverflow