Ras
Ras

Reputation: 147

How to delete a merge commit from git history?

My git history looks like this:

A---B--------D---F
    \       /   /
     \____C/__E/

Where head is now at F, and D and F are merge commits. I forget a rebase at E from D, but only realized after merging E to F. I wish to do either delete the merge commit D from the git history or do a rebase from D to E to cleanup the history. Is there any way to perform either of this with git commands?

Upvotes: 2

Views: 98

Answers (3)

j6t
j6t

Reputation: 13582

You started with this history:

--A--B---D--F    <-- branch1
      \ /  /
       C--E      <-- branch2

In particular, there are no commits between commits B and D (as per your answer to my question in the comments). That is, D was created with git merge --no-ff branch2 while on branch1, which was still pointing to B at that time. git merge branch2 would have not created D because the history up to C would have been fast-forward-able.

Now you want to remove commit D and somehow rebase E on top of the resulting history. This is just a matter of repointing branch heads to arrive at this history:

--A--B---D---F   <-- (abandoned)
      \ /   /
       C   /     <-- branch1
        \ /
         E       <-- branch2

To do that:

# the first command is only needed if branch1 is currently checked out
git checkout branch2
git branch -f branch1 C

branch2 is already pointing at the correct commit and nothing else has to be done. The simplified history looks like this:

--A--B--C      <-- branch1
         \ 
          E    <-- branch2

Upvotes: 1

dani-vta
dani-vta

Reputation: 7130

I forget a rebase at E from D, but only realized after merging E to F

Assuming that these are the branch names

A --B ------- D -- F  (branch1)
     \       /    /
      \---- C -- E    (branch2)

Just remove commit F from the history of branch1 , and then rebase branch2 (E) on top of branch1 (D).

# make sure to be on branch1
git checkout branch1

# reset branch1 to its first parent
git reset --hard branch1^

# make sure to be on branch2
git checkout branch2

# rebase branch2 (E) on top of branch1 (D) 
git rebase branch1

This is the resulting history:

                E'  (branch2)
               /
A -- B ------ D     (branch1)
      \      /   
       \--- C

Upvotes: 2

Benjamin Scharbau
Benjamin Scharbau

Reputation: 2089

What I would personally do here to clean up is first reset your Head to commit B (be careful not to use --hard as that would destroy your soon to be wanted commits),

git reset B

then first check out a new branch

git checkout -b temp

and cherry pick the two wanted commits C and E (and any wanted commits in between).

git cherry-pick C
git cherry-pick E

After that you can delete the original branch and rename the new branch to whatever branch you had before

git branch -D $ORIGNAL_BRANCH
git branch -m $ORIGNAL_BRANCH

If you have already published the branch you then must commit it with the force option

git push -f

Please be aware that rewriting history of already published branches usually should not be done, as it might interfere with the work of your coworkers

Upvotes: 1

Related Questions