31

I have a master branch like this..

A -- B -- C -- D -- E -- HEAD

Is there any command that remove one of a old commit and retain the others, say commit C?

finally it becomes like this

A -- B -- D -- E -- HEAD

I know that we can use a reverse patch and apply a new commit with reverse patch to remove commit C, but the tree structure will not be so clear and looks bulky, i.e.

A -- B -- C -- D -- E -- C(apply reverse patch) -- HEAD

Anyone knows?

TheOneTeam
  • 25,806
  • 45
  • 116
  • 158

2 Answers2

41

Use interactive rebase. For example, to go back 5 commits:

git rebase -i HEAD~5

Then in the editor which pops up, delete the line containing the commit you want to remove.

Graham Borland
  • 60,055
  • 21
  • 138
  • 179
  • 12
    With customary warning of don't do this if you have pushed this elsewhere. – manojlds Jul 20 '11 at 15:40
  • 12
    With customary exception that you're certain you're the only one using the remote you pushed it to. – Ryan Stewart Jul 20 '11 at 16:19
  • 12
    With customary addendum that it's also possible if you notify all the other devs and they are able to fix it on their end – Paweł Obrok Jul 20 '11 at 18:24
  • @Graham: I found it works. But in the editor, there are different command, how can i apply those command? i.e., squash, pick etc apart from just deleting that commit line? – TheOneTeam Jul 26 '11 at 02:35
  • 1
    @Kit: just read the help text which appears at the bottom of your editor window. Replace the word "pick" with "edit" or "squash" as needed for each commit, or delete the lines you don't want. – Graham Borland Jul 26 '11 at 09:11
  • What's the best way to do this without a customary {warning, exception, addendum}? – Jay B. Martin May 21 '14 at 15:51
8

Interactive rebase works, but to do it with just one command:

git rebase --onto B C

Still see the comments on the "interactive rebase" answer. They apply here, too.

Ryan Stewart
  • 126,015
  • 21
  • 180
  • 199
  • when executing this command and ending up a with a conflict what does it mean? can you provide some practical examples please? – Fed May 19 '21 at 14:07
  • Where B and C are commit hashes and not branch names? – logicbloke Mar 30 '22 at 11:10
  • 1
    @logicbloke Either one. A branch name is just a friendly alias for a commit. For most any general git command, giving a branch name or a commit hash are interchangeable ways of identifying a commit. See `git help revisions` for many other ways of identifying a specific commit. – Ryan Stewart Mar 30 '22 at 18:22