I found @sky's answer helpful.  And I made it into a squash-rebase function.
Assuming you are on your-branch, what this does is create a branch your-branch-tmp that is the result of doing merge --squash on main.  It also preserves all the commit messages and lets you edit.  Importantly, it also leaves your current branch alone.
After running squash-rebase, if you're satisfied with what it did, you must do a hard reset to the tmp branch.  Then in effect you've completed a squash rebase.
function squash-rebase() {
  MESSAGES="$(git log $(git merge-base main HEAD)..HEAD --reverse --format=%B)"
  SRC_BRANCH="$(git_current_branch)"
  TMP_BRANCH="$(git_current_branch)-tmp"
  echo "creating temp branch $TMP_BRANCH from $(git_current_branch)"
  git checkout -b $TMP_BRANCH main  # create tmp branch from main and checkout
  git merge $SRC_BRANCH --squash
  git commit -m "$MESSAGES" -n
  git commit --amend -n # just so you can edit the messages
  git checkout $SRC_BRANCH
  echo "IMPORTANT: run git reset --hard $TMP_BRANCH to complete squash rebase."
  echo "First, though, you may run git diff $TMP_BRANCH to make sure no changes."
  echo "Finally, delete the tmp branch with git branch -D $TMP_BRANCH"
}
Note: assumes you are using oh-my-zsh, otherwise you may have to find another way to get current branch name.