Search code examples
gitmergegit-mergegit-squash

How to merge to another branch with only two commits and with one commit squashed?


I have created a branch for development and it has some useless commits. Now I want to merge the commits to the mainline branch. The only commits I want in the origin/master branch is the latest commit and another commit that squashes the first commit to the second latest commit.

Edit: Sorry if this was not clear, so let me try make it more clear. Let us say I have 5 commits in the dev branch. I want to merge all the changes done in the dev branch to the origin/master branch. The problem is that I want to squash commits #1-4 into one commit and merge that commit and commit #5 to the origin/master branch.


Solution

  • Depending on the number of commits on that branch, especially those “useless” ones you want to get rid of, you can either do an interactive rebase to get rid of those you do not want, or you can simply cherry-pick the two you actually want to keep:

    # check out master and update it first
    git checkout master
    git merge origin/master
    
    # cherry-pick the latest commit from the development branch
    git cherry-pick dev-branch
    
    # cherry-pick the other commit (use the hash from the log)
    git cherry-pick theothercommitshash
    

    Afterwards, you have those two commits cleanly on top of master and you can squash them using a soft reset or an interactive rebase.

    The problem is that I want to squash commits #1-4 into one commit and merge that commit and commit #5 to the origin/master branch.

    That’s actually the perfect use case for interactive rebasing.

    Start on the dev branch and run git rebase -i dev~5 to launch the editor with an interactive rebasing plan for the last 5 commits. It should look like this:

    pick <hash1> Commit 1
    pick <hash2> Commit 2
    pick <hash3> Commit 3
    pick <hash4> Commit 4
    pick <hash5> Commit 5
    

    Change the inner three pick to squash so it looks like this:

    pick <hash1> Commit 1
    squash <hash2> Commit 2
    squash <hash3> Commit 3
    squash <hash4> Commit 4
    pick <hash5> Commit 5
    

    squash basically means “take the commit but meld it into the previous”. So in this case, commit 1 is being picked as it is, and then commits 2, 3, and 4 are all squashed into it one after another. So you end up with a single commit that contains the changes from all 4 commits.

    Save the plan and exit the editor to start the interactive rebasing, and adjust the commit message for the squashed commit when Git prompts you to do that. Eventually, you will end up with just two commits on the branch: The squashed commit, and commit 5 rebased on top of that.

    Finally, you can just merge the branch into master and you’re done.