Search code examples
githubsquashgit-squash

Github repo squash commits on master


I'm working with a github repo where a lot of commits historically have been "bugfix", "bugfix for real this time", "ok final bugfix", "finally fixed".

These were committed directly to master. How can I squash them?

Fromt his post a year ago - it basically sounds like this is bad, want to squash multiple commits in github. Has anything changed in the past year?


Solution

  • The answer today is basically the same: Squashing these commits is possible, but rewriting shared history is something to be strongly avoided in Git.

    Imagine that you and I each have a copy of some repository that also exists on GitHub:

    A---B---C
    

    You notice that commits B and C should really have been committed together, so you squash these commits in your local copy. You now have

    A---D
    

    where D is a combination of B and C, while GitHub and I still have

    A---B---C
    

    At this point, even though the file content is the same everywhere, our commit IDs have diverged. Now you can't push to GitHub without --force, because GitHub's master branch contains two commits that are no longer present in your history.

    If you do use --force you can make GitHub accept your changes, but now my repository contains commit objects that are no longer present upstream. I can't push to GitHub without using --force (which will invalidate your changes) or without doing a relatively funky merge to bring your changes in, probably rebasing my work, etc. And that's only possible if you communicate with me outside of Git to tell me what you've done.

    This gets even messier with more developers (imaging doing this on the Linux kernel repository!) and with more work being done concurrently.

    Really, any time you're tempted to git push --force, sit back and think for a moment. You're probably doing something that should only be done with an extremely good reason.

    My recommendation is to accept that your history is a bit messy, but to try to improve things going forward. These commits can be cleaned up locally, before you push to GitHub (or share with other developers). Work in feature branches, use cherry-pick, rebase, etc. to clean up the commit history if necessary, then push.