Interactive rebase: modify a recent commit among a bunch of –no-ff merges

The goal

I want to modify a recent commit, using rebase. The magic command is git rebase -i

Let’s say you’re trying to delete the commit-in-question

  • First, find out how far back that commit is (approximately). Then do:
    • git rebase -i HEAD~10

Source:
Greg Hewgill’s answer to a less complicated git question

The problem

That works wonderfully, unless you’ve recently done any –no-ff merges

If you happen to follow git flow, you do –no-ff merges all the time

  • Check the “Sources” section below for examples on the how & why of rebase -i blowing up –no-ff merges
  • For now, just trust me (or try it yourself): It aint pretty

The actual question

If we look at this page we see a --preserve-merges (or simply -p) option that we can try replacing -i with

The problem is, if we do that, we’re no longer given that nice -i pop-up from before
-> The one with choices for “edit this commit, sqaush that one”, etc.
–> And so, we can’t meet our original goal: modify/delete some recent commit using rebase 🙁

So, what do we do?


Sources

Problem section:

  • First example of rebase murdering –no-ff commits
  • Second example
    • His quote: “The TL;DR version is this: When rebasing, always use the -p flag

  • How to verify a git merge contains no extra changes?
  • Git won't re-merge after resetting a merge without a commit
  • Git: Merge to master while automatically choosing to overwrite master files with branch
  • How to resolve a git-svn rebase with moved files?
  • Git commits always rejected when pushing commit with file added from other branch
  • rebase reverted merged branch
  • How do I make Jenkins see a Git merge commit as a change?
  • git changes location of change-id after merge conflict
  • 2 Solutions collect form web for “Interactive rebase: modify a recent commit among a bunch of –no-ff merges”

    -p and -i are not mutually exclusive – you can use both at the same time. However be very very careful when you do this – changing the order of commits is a bad idea. You should also not try to remove merge commits this way; it’s very easy to get things into an improper state.

    git rebase -p -i HEAD~10
    

    The above using -p and -i together is correct – however I wanted to point out that you dont need to use interactive more to get rid of a commit. You can use the --onto instead to explicitly state where you want your base to be. Assuming you want to get rid of HEAD~10,…

    git rebase --onto HEAD~11 HEAD~9 HEAD
    

    This says, take any commits that are in HEAD, but **are not* in HEAD~9, and apply them to the end of HEAD~11. That would mean it skips HEAD~10. The solution above works just fine, but sometimes, for getting rid of larger swaths of history, you may want to use --onto. Keep in mind that as is the case with -p, you can also use interactive mode with --onto.

    With regard to non-fast-forward merges and rebasing, take a look at this answer I gave to another question. It mostly explains the use of --onto, but if you read through, you’ll find an explanation regarding –no-ff merges and rebasing.

    Git Baby is a git and github fan, let's start git clone.