1

When I try to interactively rebase (squash) several commits into one, it only ever squashes the last two commits so I end up having to do the squash several times.

I am using source tree, but I have tried doing it from the console with the same results. Any ideas?

4 Answers 4

7

Try -

$ git rebase -i HEAD~4

then

pick 01d1124 commit msg 1
squash 6340aaa commit msg 2
squash ebfd367 commit msg 3
squash 30e0ccb commit msg 4

save and quit your editor

You can do the same in Sourcetree -

http://kwnetzwelt.net/wordpress/archives/2440

2
  • the link you gave me is exactly the steps I take, but it squashes only the last two. The command it runs is : git -c diff.mnemonicprefix=false -c core.quotepath=false -c "sequence.editor='C:\Program Files (x86)\Atlassian\SourceTree\stree_gri'" -c "core.editor='C:\Program Files (x86)\Atlassian\SourceTree\stree_gri'" rebase -i --autosquash 138343cf6eeb74f9f436f4f746442dfdc5213943
    – gcb
    Commented Dec 14, 2015 at 9:30
  • 1
    yeh in my office a few people have the same issue with sourcetree on windows, on Mac it doesn't seem to exist. I think I tried from the terminal and had the same problem some time ago, i'll give it a go again thanks
    – gcb
    Commented Dec 15, 2015 at 13:35
2

(Interactive) rebasing technically squashes only two commits at a time—simply because the so-called "rebase script" you're typically asked to edit before git rebase proceeds applies an action to a single commit at a time.

This does not, however, change the outcome because logically there's no difference between squashing N commits at once or doing this commit-by-commit. In your rebase script, you just pick the action "squash" (also read up on "fixup"—it's often may be more handy than "squash") for a series of adjacent commits, and then git rebase works like this:

  1. Get the commit marked "squash". Squash it to the previous commit—effectively re-writiing that with the new content applied to it (as with git apply).
  2. Given that new state, go to step 1. ;-)

Note that there's also the --squash command-line option of git merge. This one squashes several commits at once for real.

1

Given that your branch points to the last of the commits you want to squash you can use this trick:

git reset --soft <some older commit>
git commit --amend

You have now replaced <some older commit> with a new one containing everything between the two, plus their content.

0

Squash

This is exactly what interactive rebase is for.

You use the git rebase -i @~x where x stand for the number of commits you wish to squash.

Then a dialog will open up for you and you can choose commits and what you wish to do with each commit.

enter image description here

2
  • This is what I am doing (just through sourcetree instead). I am telling it what commits I want to squash, editing the commit message and then when it comes to doing the squash it will tell me something like "rebasing commit 6/7, rebasing commit 7/7"
    – gcb
    Commented Dec 6, 2015 at 8:18
  • Its OK, its updating all the commits in the whole chain since the committed is part of the commit information which is being calculated to the the SHA-1. so all the commits have to be updated
    – CodeWizard
    Commented Dec 6, 2015 at 8:22

Not the answer you're looking for? Browse other questions tagged or ask your own question.