Search code examples
gitsquashgit-squash

Squash hundreds of old commits on origin


I made a silly mistake and am not sure the best way to resolve it. Here's what I did:

  • Created a web project based on a boilerplate.
  • Removed .git to remove all history (about 500 commits) before making my initial commit
  • Several months and about 200 of my own project commits later, I merged the upstream boilerplate branch into a local branch of my project. This added around 500 more commits from the upstream boilerplate.
  • Made an additional 10 or so commits in the local branch to get my project working again with the updates from the boilerplate
  • Merged the working local branch into my develop branch
  • Pushed the develop branch to origin
  • Created one more commit on local develop branch (not pushed to origin)
  • Created about a dozen commits on another local branch that hasn't been merged to develop (not pushed to origin)

My git history now has all of the boilerplate history before my first project commit that I initially had removed. It also has a hundreds of commits interspersed in the middle of my commits.

What I'd like to do is squash everything in the merge from upstream into the local branch I was using into a single commit. Is there a somewhat painless way to do this?

Also, I need to rewrite history on origin as well. This is a private repo and only a couple people are using it. How do I do this?


Solution

  • What I'd like to do is squash everything in the merge from upstream into the local branch I was using into a single commit. Is there a somewhat painless way to do this?

    Use two local clone of your repo:

    • in one, you checkout the various state you want to squash (like your upstream merge commit SHA1)
    • in the other, you do a git reset --hard to the first commit which was still correct (ie where the history is good)

    Then, from the second, you can git --work-tree=/path/to/first/clone add . everything from the first, and commit.

    Repeat for the various state of the first repo you want to squash into one commit (achieved in the second repo by adding the working tree of the first repo, and committing).

    Then git push --force.