Practical Methods for Squashing Commits with Merge Commits in Git History

Dec 07, 2025 · Programming · 6 views · 7.8

Keywords: Git commit squashing | Interactive rebase | Merge commit handling

Abstract: This article provides an in-depth exploration of techniques for effectively squashing multiple commits into one when Git commit history contains merge commits. Using practical development scenarios as examples, it analyzes the core principles and operational steps of using interactive rebase (git rebase -i) to handle commit histories with merge commits. By comparing the advantages and disadvantages of different approaches, the article offers clear solutions to help developers maintain clean commit histories before merging feature branches into the main branch. It also discusses key technical aspects such as conflict resolution and commit history visualization, providing practical guidance for advanced Git users.

Technical Background of Git Commit Squashing

In distributed version control systems, Git provides powerful branch management and commit history manipulation capabilities. During actual development, developers often need to squash multiple commits on a feature branch into a single clean commit to facilitate code review and project history maintenance. However, when commit history contains merge commits, traditional methods like git merge --squash may not be directly applicable, requiring more refined operational strategies.

Analysis of Commit History with Merge Commits

Consider the following typical development scenario: a developer makes multiple commits on a feature branch, then encounters conflicts when pushing changes to the remote branch. To resolve these conflicts, the developer merges changes from the main branch, manually resolves conflicts, and commits the merge. At this point, the commit history structure appears as follows:

  * D commit 3 (HEAD)
  * M merge
 /|
| * C commit 2
* | B commit on master
|/
* A (master)

In this history structure, commit 3 is the most recent commit, M is the merge commit, and commit 2 is an earlier commit on the feature branch. The goal is to squash these three commits into one while preserving the integrity of code changes.

Core Method: Interactive Rebase

When dealing with commit histories containing merge commits, the most effective approach is using Git's interactive rebase functionality. The specific operational steps are as follows:

  1. Identify Rebase Starting Point: First, determine where the feature branch diverged from the main branch. In the above history structure, this point is commit A, the base commit on the main branch.
  2. Execute Interactive Rebase: Run the command git rebase -i A, where A is the starting commit hash or reference for the rebase. This command opens an editor displaying a list of all commits from the starting point to the current HEAD.
  3. Edit Rebase Instructions: In the opened editor, you will see content similar to:
pick B commit on master
pick C commit 2
pick M merge
pick D commit 3

Note that interactive rebase typically does not directly display merge commits but converts them into a series of linear commits. In practice, you might see commits B and C, but the merge commit M may not appear directly since the rebase process reapplies commits.

<ol start="4">
  • Configure Squash Instructions: Change the instruction for all commits except the first one from pick to squash or s. For example:
  • pick B commit on master
    squash C commit 2
    squash D commit 3

    With this configuration, Git will combine the changes from C and D into the B commit, creating a new squashed commit.

    <ol start="5">
  • Handle Conflicts: During the rebase process, conflicts may arise when reapplying commits, especially those previously resolved through merge commits. Git pauses the rebase process, allowing you to manually resolve these conflicts. After resolving conflicts, use git add to mark them as resolved, then continue with git rebase --continue.
  • Complete Rebase: After resolving all conflicts, Git creates a new squashed commit. You can edit the commit message, typically recommending inclusion of key information from all squashed commits.
  • Comparative Analysis of Alternative Methods

    Besides the interactive rebase method, other approaches exist for handling commit histories with merge commits. One common method involves creating a temporary branch:

    git checkout -b temp main
    git merge --squash feature
    git commit
    git checkout feature
    git reset --hard temp
    git branch -d temp

    This method creates a temporary branch from the main branch, then uses git merge --squash to compress all changes from the feature branch into a single commit, finally resetting the feature branch to this squashed commit. The advantage of this approach is relative simplicity, but drawbacks include loss of the original commit history structure and potential inability to handle complex merge scenarios properly.

    In contrast, the interactive rebase method offers finer control, allowing developers to select which commits to squash while maintaining complete control over the conflict resolution process. This method is particularly suitable for scenarios requiring preservation of certain commit independence or handling complex merge histories.

    Technical Points and Best Practices

    When squashing commits in histories containing merge commits, several key technical points require attention:

    Extended Practical Application Scenarios

    The techniques discussed in this article apply not only to simple feature branch merging scenarios but also extend to more complex development workflows:

    By mastering the technique of squashing commits in Git histories containing merge commits, developers can manage project history more effectively, improve collaboration efficiency, and maintain the cleanliness and maintainability of codebases. Although these advanced Git operations require a learning curve, once mastered, they become powerful tools in daily development work.

    Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.