However I typically squash by just doing a soft `git reset` to the merge-base (the last commit in common with my branch and the one I'm building my work from) and making a new commit. It avoids touching the working tree at all, which avoids breaking my build cache and confusing my IDE.
If I instead want to do a squash-rebase onto the _latest_ of the upstream branch, I do the same as the above, except I `git merge` first (to resolve any merge conflicts in one shot.) Then the merge-base is just the upstream head. This is way easier than doing `rebase -i` and squashing, because you don't have to fix the merge conflicts over and over again for every commit you're trying to squash... just fix the merge conflicts once during the merge, and the "reset and commit" trick is going to create one clean commit in the end anyway.