5

I want to remove a specific commit, C, in git history, as well as some single-commit-merges.

The history looks like this. In this example, I want to remove the single-commit-merge m6 and a problematic commit C.

---m0-------------------m1---m2---m3-------------m4---m5----m6---m7---(...)
     \                 /            \           /       \  /
      b0---b1---b2---b3              b4--(C)--b5         b6

I want to wind up with this (changes highlighted):

                                                      vv 
---m0------------------m1---m2---m3---------m4---m5---b6---m7---(...)
    \                 /            \vvvvvvv/          ^^
     b0---b1---b2---b3              b4---b5
                                    ^^^^^^^

If I use "git rebase -i" to excise C and b6/m6, this works, but I get:

---m0---b0---b1---b2---b3---m1---(...)---

and the history is flattened. I want to preserve the entire structure. Conversely, if I run with the --preserve-merges flag, then I get:

error: Commit <sha-1 corresponding to m6> is a merge but no -m option was given.
fatal: cherry-pick failed
Could not pick <sha-1 corresponding to m6>

and I can't remove b6/m6 (although I can remove C).

What's the right way to wind up with the desired result? I'm using git 1.8.4, if that matters.

(Note that the other questions on StackOverflow that I perused don't seem to account for this very specific case, so as nearly as I can tell, this is not a duplicate question.)

John Feminella
  • 303,634
  • 46
  • 339
  • 357
  • My answer below is not really an answer per se, but is too big/needs-formatting for a comment. I know coming up with a reproducer for this would be a pain, but if you *can* come up with one, and if it is a bug, that will certainly help the git folks fix it. :-) – torek Sep 16 '13 at 17:05
  • I would have used [git reparent](https://stackoverflow.com/a/19143448/1725151) + git-replace + git-filter-repo. – Guildenstern May 06 '23 at 11:25

2 Answers2

0

Looks like it may be a small bug in git-rebase--interactive:

            case "$new_parents" in
            ' '*' '*)
                    test "a$1" = a-n && die "Refusing to squash a merge: $sha1"
            ... snip ...
            *)
                    output eval git cherry-pick "$strategy_args" "$@" ||
                            die_with_patch $sha1 "Could not pick $sha1"
                    ;;

When this hits m6, the new set of parents is singular, so it tries to use cherry-pick, but m6 is a merge so cherry-pick requires a hint about which parent to use.

I'm not sure why it's trying to take m6 at all, though.

torek
  • 448,244
  • 59
  • 642
  • 775
0

Solution/workaround: (for me, anyway) This seems to be a bug in git rebase. I reverted to git 1.7.9 and my problem was solved; git rebase --interactive --preserve-merges worked exactly as I wanted and produces the graph I indicated in my post.

John Feminella
  • 303,634
  • 46
  • 339
  • 357