Search code examples
gitgithubgit-mergegit-commit

How to convert pushed regular merge into squash-merge in git?


I have accidentally merged my 20 commits using regular commit from feature branch to the main branch. Is there any way to revert it and make it as squash and merge? The purpose is to make the main branch clean. It should only have one commit for my 20 commits in the feature branch.


Solution

  • First, a disclaimer. A standard rule of thumb in Git is:

    Don't force push shared branches, because it can mess up other people.

    But of course a rule of thumb can have exceptions if you are willing to deal with the consequences, and in your case it sounds like you are:

    Everyone in the group notice that, so we would like to figure out this first.

    So the fix for this is fairly straight forward:

    # tell everyone you are going to rewrite the main branch
    git checkout main
    git pull main
    # look at main and make sure other people didn't add more commits after yours
    git reset --hard <last-good-commit-id-before-your-feature-branch>
    git merge feature-branch --squash
    # at this point a single squashed commit is staged and ready to be committed
    git commit -m "Merge and squash feature branch"
    # now replace the remote main branch with your copy
    git push --force-with-lease
    # now tell everyone it is fixed and they can resume work
    

    Note: You asked about "revert", but in Git the term "revert" means to create a new commit which undoes a previous existing commit. That will leave the history intact and change functionality. You actually want the opposite because you want to leave the functionality intact and change the history. To change history you need to "rewrite" commits, which in this case consists of resetting backwards to remove commits, and recreating a new commit.

    Side Note: you might want to consider setting up branch policies on main and using Pull Requests for merges into main. Then (let's hope) someone reviewing your code would see a lot of commits in your PR and could tell you to squash them first. Or, you could set up a squash merge policy so that it happens automatically when the PR is completed.