135

I'm very new to git, and was wondering if something like this is possible?

>git log --pretty=oneline --abbrev-commit
2f05aba Added new feature
3371cec Fixed screw up    <-- I want to remove this
daed25c Screw up          <-- and remove this.
e2b2a84 First.                So it's like they never happend.

Is this possible?

1
  • 5
    Note to future visitors: I think it's important to note that the answers to this question are split in their interpretation. Some assume "the commits never happened" and so the changes are not preserved ("drop"). Others assume the changes in the removed commits should be preserved ("squash" or "fixup"). Make sure to choose your answer based on which of those you need.
    – TTT
    Commented May 22, 2023 at 17:17

5 Answers 5

119

If you truly wish to delete them (wiping them from history, never to be seen any more), you can

run rebase:

git rebase -i HEAD~4

and then, just delete (or comment out) the lines corresponding to the commits you wish to delete, like so:

pick 2f05aba ... #will be preserved
#pick 3371cec ... #will be deleted
#pick daed25c ... #will be deleted
pick e2b2a84 ... #will be preserved
7
  • 2
    I'm new to github, How do you push the changes after that (when I click Sync, it just reverts what I did). I think I got it : git push origin HEAD --force Commented Aug 6, 2014 at 12:12
  • @NicolasThery you don't. That's why git push refuses to work without --force, because you're re-writing history and you'll break other peoples repositories. If you've already pushed then your only option is to do a git revert. Which, when you think about it is sensible because if you pulled someone else's code you wouldn't want them to be able to erase your old commits without some kind of history would you?
    – Angry Dan
    Commented Aug 29, 2014 at 15:13
  • 2
    @AlexanderMills It doesn't change anything upstream as long as you don't push it (and if you do, you have to add the --force flag as Angry Dan said).
    – Shathur
    Commented Jan 18, 2017 at 19:11
  • 2
    d or drop is the command to remove commits from the history. Commented May 18, 2018 at 18:31
  • 2
    @NicolasThery Seeing as nobody is giving you an honest answer: the reason the Sync button doesn't work is because it does A LOT of garbage in the background to try 'restore' your branch to match your repo (it runs something like 15 individual git commands). If you're sure no one has cloned your repo, just run git push --force from the terminal. Else call it a day and accept the mistake. Commented May 10, 2023 at 2:17
83

This is possible with git rebase. Try the following

git rebase -i HEAD~4

and then, follow the interactive instructions in your editor. In the first step you "squash" the commits. It should look something like this:

pick 2f05aba ... will be preserved
squash 3371cec ... will be squashed with daed25c
squash daed25c ... will be squashed with e2b2a84
pick e2b2a84 .. will contain this and 3371cec and daed25c

In the second step you can edit the commit messages.

3
  • 45
    Isn't the question about deleting the commits rather than squashing them?
    – Richard
    Commented Apr 7, 2013 at 1:24
  • 5
    @Stony: Well, you could probably also delete them. But from the commit comments in the OP ("Screw up" and "Fixed screw up") I assumed that the one is undoing the other and that you could as well just squash the two.
    – Deve
    Commented Apr 7, 2013 at 10:23
  • I'd say that's only your personal assumption. As @Richard mentioned, this is about deleting.
    – DarkTrick
    Commented Sep 16, 2022 at 12:11
25

To completely delete commit(s) there is a new option drop for git interactive rebases now. First run:

git rebase -i HEAD~4

Then replace pick with drop for the commit(s) to be dropped:

pick 2f05aba ... #will be preserved
drop 3371cec ... #will be dropped
drop daed25c ... #will be dropped
pick e2b2a84 ... #will be preserved

This worked on Fedora for me with the following version:

$ git version
git version 2.21.0
9

Squash is useful when you want to generate a list of merged commits under a single hash, but if you are looking to take three separate commits and have a final output that looks like it was a single commit, I recommend fixup

git rebase -i HEAD~4

pick 2f05aba ... will be preserved
fixup 3371cec ... will be merged with 2f05aba (message lost)
fixup daed25c ... will be merged with 3371cec (message lost)
pick e2b2a84 .. will be preserved

You can find more information in the command list of the interactive rebase UI.

0
2

tl;dr: A one line command will work: git rebase 3371cec 2f05aba --onto e2b2a84

The Long:

If the one or more commits are grouped together, you can use a one-line rebase command without needing to bother with interactive mode. For example:

# Suppose you have: A-B-X-Y-C
# and you wish to remove X and Y:

git rebase Y C --onto B
# or (equivalent)
git rebase C~1 C --onto C~3
# both would result in: A-B-C'

# with this question's commit IDs:
git rebase 3371cec 2f05aba --onto e2b2a84
# or (equivalent)
git rebase 2f05aba~1 2f05aba --onto 2f05aba~3

Oftentimes I find myself just needing to remove a single commit from a feature branch's linear history, so assuming the commit ID to remove is X and the commit ID after X is K (the commit you wish to "keep"):

git rebase K~1 K --onto K~2

Note that K~2 is one plus the number of commits in a row that you wish to remove. If you wish to remove 2 commits you would use K~3, or 10 commits would be K~11.

If you wish to preserve the changes in the commits you wish to remove, then you could use an interactive rebase (rebase -i) and then change "pick" for those 2 commits to "squash" or "fixup".

If you wish to remove the commits as if they never happened, without keeping their changes either, then you can also use interactive rebase and in the instructions list, change "pick" for the two commits to "drop", or comment out the lines, or delete the lines, all of which will do the same thing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.