3

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?

Tauren
  • 26,795
  • 42
  • 131
  • 167
  • 3
    Why do people do this to themselves? – Joe Phillips Feb 09 '17 at 00:01
  • 1
    @JoePhillips Great question! In my case, I had planned to squash my local branch before merging with develop. But there were some changes someone else needed right away, and I wasn't sure how to do the squash. So I merged the way it was, thinking I could deal with it just after. Of course, other stuff took priority, so here I am now trying to clean up this mess of my own making. – Tauren Feb 09 '17 at 00:39
  • I'm totally against squashes so I guess I don't really see this as a mess – Joe Phillips Feb 09 '17 at 01:05
  • I typically am also against squashes, which is why I wasn't sure how to do them. But this is a private repo for a corporate project. It looks strange to others that the git history dates years before the project started as well as having dozens of committers who are not part of the company. – Tauren Feb 09 '17 at 01:21
  • Interactive rebase is probably the best way to do this but it will be a little bit of manual work in a text editor – Joe Phillips Feb 09 '17 at 01:33
  • `git filter-branch` to change the committers and dates ;) – Luke Hutton Feb 09 '17 at 01:34
  • or at least wipe out commit history before a certain commit into a new repo, create a new root: http://stackoverflow.com/a/7459967/368552 – Luke Hutton Feb 09 '17 at 01:38
  • It sounds like there aren't too many "strings of commits" that you'd like to squash, they're just a little bit everywhere. It looks to me like a diagram on a whiteboard of the whole merge-y situation and their associated hashes (with a clone repo as double-check backup), and then a series of `git reset --hard`s and `git rebase`s will get you there. Once you're done, just garbage collect away all the old stuff you no longer care about. – Mort Feb 09 '17 at 01:51

1 Answers1

2

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.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Thanks, this did the trick! Actually, I only did it once and didn't repeat. Instead of repeating, I cherry-picked the most recent commits. This did lose a bit of data, such as original commit dates and the branches they were in, but I wasn't too concerned about that. – Tauren Feb 10 '17 at 02:15