Git Interactive Rebase: Removing Selected Commit Log Entries While Preserving Changes

Nov 30, 2025 · Programming · 9 views · 7.8

Keywords: Git | Interactive Rebase | Commit History Optimization

Abstract: This article provides an in-depth exploration of using Git interactive rebase (git rebase -i) to selectively remove specific commit log entries from a linear commit tree while retaining their changes. Through analysis of a practical case involving the R-A-B-C-D-E commit tree, it demonstrates how to merge commits B and C into a single commit BC or directly create a synthetic commit D' from A to D, thereby optimizing the commit history. The article covers the basic steps of interactive rebase, precautions (e.g., avoiding use on public commits), solutions to common issues (e.g., using git rebase --abort to abort operations), and briefly compares alternative methods like git reset --soft for applicable scenarios.

Introduction

In software development, Git, as a distributed version control system, relies on clear and logical commit histories for effective project maintenance. However, as development progresses, redundant or temporary commit entries, such as debug code or experimental changes, may appear in the history. While these entries are no longer valuable to keep, the code changes they introduce must be preserved. Based on a real-world technical Q&A scenario, this article delves into how to use Git interactive rebase to selectively remove specific commit log entries while ensuring that related changes are retained, thus optimizing the commit tree structure.

Problem Scenario Analysis

Assume the current Git repository has a linear commit tree: R--A--B--C--D--E--HEAD. The user aims to remove the B and C commit entries so they do not appear in the commit log, but all changes from A to D should be preserved. Ideally, the commit tree should become R--A--BC--D--E--HEAD (where BC is a merged commit of B and C) or R--A--D'--E--HEAD (where D' represents the cumulative changes from A to B, B to C, and C to D). This requirement is common in early project stages where branch structures are simple and no merge commits interfere.

Core Solution: Interactive Rebase

Git's git rebase -i (interactive rebase) command is the standard tool for addressing such issues. It allows users to interactively reorder, merge, edit, or delete commit entries. Based on best practices, the following steps outline the operational process.

Prerequisites

Before performing an interactive rebase, ensure that:

Operational Steps

To remove commits B and C, follow these steps:

  1. Initiate interactive rebase: Run git rebase -i HEAD~5. This command specifies rewriting the last 5 commits (R, A, B, C, D), where HEAD~5 denotes tracing back 5 commits from HEAD. Upon execution, the default text editor (e.g., Vim or Nano) launches, displaying the commit list and operation instructions.

  2. Edit commit operations: In the editor, commits are listed in chronological order (oldest first). Locate the lines corresponding to B and C, and change the pick at the beginning to squash (or abbreviated s). The squash instruction merges the current commit into the previous one and retains the option to edit commit messages. If a commit needs to be entirely deleted, simply delete its line.

    pick <SHA1-of-A> Commit message A
    squash <SHA1-of-B> Commit message B
    squash <SHA1-of-C> Commit message C
    pick <SHA1-of-D> Commit message D
    pick <SHA1-of-E> Commit message E

    This configuration merges B and C into A, forming a new commit BC (preserving changes from A, B, and C), resulting in the commit tree R--BC--D--E--HEAD.

  3. Save and exit: After saving the editor, Git automatically executes the rebase. If conflicts arise, resolve them manually and run git rebase --continue. Upon completion, the commit history is rewritten, with B and C entries removed and their changes incorporated into the new commit.

Error Handling

If errors occur during rebase or the user wishes to abort, run git rebase --abort to restore the repository to its pre-rebase state. This command is particularly useful in cases of operational confusion, ensuring data safety.

Analysis of Alternative Methods

Besides interactive rebase, git reset --soft combined with git rebase --onto can achieve similar results, but the process is more complex and suited for specific scenarios. For example:

  1. Detach HEAD to commit D: git checkout <SHA1-for-D>.
  2. Soft reset to commit A: git reset --soft <SHA1-for-A>, preserving the working and staging area states.
  3. Re-commit D changes: git commit -C <SHA1-for-D>, reusing the original D commit message.
  4. Apply subsequent commits: git rebase --onto HEAD <SHA1-for-D> master, reapplying commits after D to the new base.

This method directly creates a synthetic commit D' from A to D, achieving the structure R--A--D'--E--HEAD, but note that changes in commit SHA1 may affect references.

Practical Recommendations and Considerations

While interactive rebase is powerful, it must be used cautiously:

Conclusion

Git interactive rebase is an effective tool for optimizing commit histories, allowing selective removal of commit entries while preserving changes via squash operations. This article demonstrated the transformation from R--A--B--C--D--E--HEAD to R--A--BC--D--E--HEAD or R--A--D'--E--HEAD using a linear commit tree example, emphasizing key steps and risk control in the process. Developers should master this technique to maintain clear and efficient version histories, enhancing project management quality.

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.