gitgit-rewrite-historygit-branch-sculpting

How to remove all commits of a topic Git branch?


Suppose I have the following history:

   A---B---C----------D------------E master
            \         /\         /
            W1--X1--Y1 W2--X2--Y2 
                  topic1      topic2

Is it possible to remove all topic branches and their commits as following

A-B-C-D-E master


Solution

  • You have a few options for doing this.

    Solution 1: Squash Merges

    One solution is to simply use a hard reset with a few squash merges:

    git checkout master
    git reset --hard C
    
    git merge --squash topic1
    git commit -m "Rewrite D"
    
    git merge --squash topic2
    git commit -m "Rewrite E"
    
    # Verify that the new branch is no different from the old one
    git diff sha_of_old_E
    

    The idea here is that a squash merge will copy the final state of a topic branch (i.e. the last commit) into your current working copy, where you can then commit it. It effectively squashes a branch into a single commit.

    Documentation

    Solution 2: Interactive Rebase

    Another method is to use an interactive rebase to squash the topic branches into a single commit. First, invoke the rebase

    git rebase -i C
    

    That will bring up the interactive rebase TODO list editor in your terminal. You'll see the following commits displayed:

    pick sha W1
    pick sha X1
    pick sha Y1
    pick sha W2
    pick sha X2
    pick sha Y2
    

    What you want to do is something similar to the squash merge above. You can to squash the topic branches into single commits, so for each commit of a topic branch, squash (or "fixup") the descendant commit into its parent:

    pick sha W1
    squash sha X1
    squash sha Y1
    pick sha W2
    squash sha X2
    squash sha Y2
    

    Then hit :wq in the Vim editor to begin the interactive rebase. I won't go into detail about the next steps, because they're already adequately detailed in other numerous sources around the internet, such as in Pro Git § 6.4 Git Tools - Rewriting History - Squashing Commits.

    You'll probably want to double check that you did the rebase correctly by verifying that the newly rewritten branch is no different from the previous one by using a simple diff:

    git diff sha_of_old_E
    

    Note that if you'd rather not bother editing the commit messages for each squash, you can use "fixup" instead, which will just reuse the commit message of the previous commit:

    pick sha W1
    fixup sha X1
    fixup sha Y1
    pick sha W2
    fixup sha X2
    fixup sha Y2
    

    Note that you can also use s or f for squash and fixup, respectively.

    Documentation

    Warning about force pushing

    Note that both of the above solutions will rewrite your commit history, of course, so your new commits will have different sha IDs. If you've already pushed the old version of your branch to your remote, then you'll need to force push to overwrite the old copy. This may not be something you want to do if you're sharing your branch with other people, for reasons which I won't detail here, since the possible dangers of force pushing are well documented in numerous other online sources, such as: