2

The answer here explains well how to squash the last few commits after they've already been pushed, but what about the e.g. the last 12 into three groups of four? That is, I have pushed commits 1-12 and would like to now squash them down to three commits. These three squashed commits would contain original commits 1-6, 7-8, and 9-12, respectively. How can I do this?

Bonus points: how can I specify a new commit message for each of the three squashed commits?

Community
  • 1
  • 1
BoltzmannBrain
  • 5,082
  • 11
  • 46
  • 79

2 Answers2

3

You can squash multiple sets of commits at once:

git rebase -i HEAD~15

pick 3f3416d T11 - some issue
pick 23031eb T12 - fix
pick 8239b70 T13 - improvements 
squash e1e23fd T13 - one more fix
squash 200c8c6 T13 - last fix
pick e5b0286 T14 - great feature
pick d18bf1b T15 - removing unused files
pick a1b1821 T16 - refactor part 1.
squash dd090dc T16 - refactor part 2.
squash d87db6b T16 - refactor part 3.
pick da1dd09 T17 - new model of database
pick 39b4ace T18 - restfull api
pick 65521eb T19 - registration form
squash 8924091 T19 - login form
pick b44a25c T20 - new super feature

During rebase you will be asked about new commit messages for each group:

1 group

# This is a combination of 3 commits.
# The first commit's message is:
T13 - improvements

# This is the 2nd commit message:

T13 - one more fix

# This is the 3rd commit message:

T13 - last fix

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# Author:    Your Name <your.email@domain.com>
# ...

2 group

# This is a combination of 3 commits.
# The first commit's message is:
T16 - refactor part 1.

# This is the 2nd commit message:

T16 - refactor part 2.

# This is the 3rd commit message:

T16 - refactor part 3.

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# Author:    Your Name <your.email@domain.com>
# ...

3 group

# This is a combination of 2 commits.
# The first commit's message is:
T19 - registration form

# This is the 2nd commit message:

T19 - login form

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# Author:    Your Name <your.email@domain.com>
# ...
noisy
  • 6,495
  • 10
  • 50
  • 92
  • Thank you, this did the trick. To finish it up I had to `git push -f`. – BoltzmannBrain Jul 29 '15 at 16:04
  • `git push -f` is necessary if commits in range `8239b70`-`b44a25c` were already pushed. If you last pushed commit would be `pick 23031eb T12 - fix`, this would mean, that you only change your local history. BTW. if you would have to retrive old branch, you can just use old HEAD hash, to create new branch `git checkout b44a25c -b ufff_Its_good_to_have_old_commits_back__branch` – noisy Jul 31 '15 at 13:13
1

Use git rebase -i [commit-preceding-ones-you want-to-squash

Mark those that you want to squash s (for squash) and those that you want to keep e for edit.

It will then interactively squash the intermediate ones, and stop at the others. Then use git commit -a --amend to edit the commit message, and git rebase --continue to continue.

man git rebase should help.

abligh
  • 24,573
  • 4
  • 47
  • 84