2

I have a repository, it's only mine, so there's no problem on breaking anything. Also there's only one branch, I think that makes things easier. Let's say I have this 7 commits:

A -> B -> C -> D -> E -> F -> G

And I want to delete commits C and D

A -> B -> E -> F -> G

Being A the first commit ever made, and G the last commit.

How can I do that? Without touching my code, just the git history.

The only thing I know I can do is reset the Head, but that won't work since I don't want to remove E, F and G.

Octaviotastico
  • 92
  • 1
  • 10

3 Answers3

1

You can do an interactive rebase (see the git manual on rewriting history, specifically the section on "Reordering Commits").

For example, entering git rebase -i HEAD~5 will open the default file editor with a list of the last 5 commits, oldest to newest:

pick f7f3f6d commit C
pick 310154e commit D
pick a5f4a0d commit E
pick aaaaaaa commit F
pick bbbbbbb commit G

You can remove the lines for commits C and D. Similarly to the example in the link above, when you save and exit the editor, Git rewinds your branch to the parent of these commits (which is commit B), applies commits E and then F and then G, and then stops. You effectively remove commits C and D completely.

This can be a pain to undo, so consider creating a new branch first for experimenting with rebase.

Community
  • 1
  • 1
Eric Munn
  • 563
  • 2
  • 6
1

As others mention an interactive rebase should help you do that.

Here is the procedure.

  1. Open a command line/git bash

  2. You want to remove C and D so go to the commit before C i.e. B. You can either do git rebase -i HEAD~6 or git rebase -i <B's commit hash>

  3. An editor window should open (either vim or something else based on your settings) and should look like below

    pick {A's commit message}
    pick {B's commit message}
    pick {C's commit message}
    pick {D's commit message}
    pick {E's commit message}
    pick {F's commit message}
    pick {G's commit message}
    

Delete the entire line for commits C and D and then save and close the editor. So your editor should now look like.

    pick {A's commit message}
    pick {B's commit message}
    pick {E's commit message}
    pick {F's commit message}
    pick {G's commit message}
  1. The rebase should continue and remove the commits C and D. Make sure you resolve any merge conflicts that may come up in the process and then do git rebase --continue (only if there were conflicts)

  2. Once done, run git log to check if the rebase worked

raghav710
  • 1,091
  • 14
  • 23
0

You can do an interactive rebase:

git checkout myBranch   # with G being myBranch HEAD)
git rebase -i B

That will replay all commits after B, but with the opportunity for you to drop the commits you don't want.

VonC
  • 1,042,979
  • 435
  • 3,649
  • 4,283