I would like to know how to delete a commit.

By "delete", I mean it is as if I didn't make that commit, and when I do a push in the future, my changes will not push to the remote branch.

I read git help, and I think the command I should use is git reset --hard HEAD. Is this correct?

share|improve this question
11  
possible duplicate of Git undo last commit – Toon Krijthe Feb 9 '12 at 21:11
12  
I think this is not a duplicate of Git undo last commit as it asks how to delete any commit from a branch. I also think non of the answers actually address this question. They all rewind the last commits, not cherry-pick and delete a single commit that may occurred a while ago. – Chris May 3 '15 at 18:06
1  
@Chris, the answer with git rebase -i HEAD~10 does address the question, as it does let you arbitrarily pick commits to delete. Git applies the commits in the range you specify one-by-one, ignoring commits you have removed from the log. I used this command today to get rid of the second and third most recent commits to my repo while keeping the top one. I agree that none of the other answers are satisfactory. – MST Jun 17 '15 at 21:07
    
@MST yes, I should have said, non of the options in the accepted answer address this question, but you are absolutely right - that command seems to work – Chris Jul 10 '15 at 12:43

19 Answers 19

up vote 2546 down vote accepted

Careful: git reset --hard WILL DELETE YOUR WORKING DIRECTORY CHANGES. Be sure to stash any local changes you want to keep before running this command.

Assuming you are sitting on that commit, then this command will wack it...

git reset --hard HEAD~1

The HEAD~1 means the commit before head.

Or, you could look at the output of git log, find the commit id of the commit you want to back up to, and then do this:

git reset --hard <sha1-commit-id>

If you already pushed it, you will need to do a force push to get rid of it...

git push origin HEAD --force

However, if others may have pulled it, then you would be better off starting a new branch. Because when they pull, it will just merge it into their work, and you will get it pushed back up again.

If you already pushed, it may be better to use git revert, to create a "mirror image" commit that will undo the changes. However, both commits will be in the log.


FYI -- git reset --hard HEAD is great if you want to get rid of WORK IN PROGRESS. It will reset you back to the most recent commit, and erase all the changes in your working tree and index.


Lastly, if you need to find a commit that you "deleted", it is typically present in git reflog unless you have garbage collected your repository.

share|improve this answer
27  
HEAD~1 or just HEAD^. If you pushed, you should use git revert instead. – Jakub Narębski Aug 27 '09 at 10:45
78  
be sure to stash any local changes you want to keep before running this command... – William Denniss Sep 4 '11 at 7:10
7  
Obviously you can also use HEAD~n to "go back" n commits from your head. Maybe from this point you can interpreted ... --hard HEAD also as HEAD~0 => deleting work in progress. – yoshi Jun 11 '12 at 8:05
11  
@beamrider9 imho git rebase is almost always the better way to delete commits (as described in Greg Hewgill's answer) -- not least because rebase does in fact include a big warning that you will be deleting stuff 4realz. – Noah Sussman Oct 26 '12 at 6:39
10  
this doesn't delete changes from the commit tree though. The OP asked for an already made commit. If you reset --hard, and check the log --oneline --all, the commits still remain in the tree. How do we delete these commits from tree? Thanks. – Yasky Mar 17 '13 at 3:09

If you have not yet pushed the commit anywhere, you can use git rebase -i to remove that commit. First, find out how far back that commit is (approximately). Then do:

git rebase -i HEAD~N

The ~N means rebase the last N commits (N must be a number, for example HEAD~10). Then, you can edit the file that Git presents to you to delete the offending commit. On saving that file, Git will then rewrite all the following commits as if the one you deleted didn't exist.

The Git Book has a good section on rebasing with pictures and examples.

Be careful with this though, because if you change something that you have pushed elsewhere, another approach will be needed unless you are planning to do a force push.

share|improve this answer
1  
Note: If you happen to have any --no-ff merges in that last batch of commits, rebase will butcher them :( This is mentioned under -p on this page. The problem is, if you replace -i with -p, you no longer get that pop up with the choices for "edit this commit, sqush that one", etc etc. Anyone know the solution? – Bukov Apr 21 '13 at 0:20
2  
@Costa you can use push -f to force the push and replace the remote branch with your local one. If it's just your own remote repo, no problem. The trouble starts if somebody else has fetched in the meantime. – Greg Hewgill Jan 7 '15 at 6:16
2  
I added and committed a data file that was too big for GitHub (yeah, it probably shouldn't be in the source repo anyway; Oh well). When I tried to push, GitHub refused because of the too-large file. All I wanted to do was undo this one commit, while saving a few other unrelated commits that followed. The git rebase -i HEAD~5 command was exactly what I needed to completely remove this commit from my local repo! Thanks! – aldo Feb 24 '15 at 18:07
1  
@Bukov The documentation says you can use both -i and -p, but if you do, "Editing commits and rewording their commit messages should work fine, but attempts to reorder commits tend to produce counterintuitive results." I'm not sure how well deleting commits would work, but you could try it and then do a reset --hard to before the rebase (using the reflog) if it doesn't work out properly. – Max Nanasy Mar 4 '15 at 2:03
2  
@dumbledad: With rebase -i, the changes corresponding to the deleted commit are not preserved. – Greg Hewgill May 10 at 17:43

Another possibility is one of my personal favorite commands:

git rebase -i <commit>~1

This will start the rebase in interactive mode -i at the point just before the commit you want to whack. The editor will start up listing all of the commits since then. Delete the line containing the commit you want to obliterate and save the file. Rebase will do the rest of the work, deleting only that commit, and replaying all of the others back into the log.

share|improve this answer
1  
thx, btw if you run into any issues (like empty commits) you can use git rebase --continue – realgt Sep 28 '12 at 15:43
6  
Even easier: git rebase -i HEAD~1 – mmell Sep 10 '13 at 21:12
5  
Cheers, this just saved us from a serious mess of a git situation ;) – James Duffy Jul 7 '14 at 8:11
1  
Wowzers. git rebase -i HEAD~1 really cleaned the repo up a lot! It's hard to tell exactly what it did, but the whole thing looks a lot neater. A little alarming, actually. – Charles Wood Dec 2 '14 at 18:02
3  
I think it's worth noting that the commit is not obliterated, merely removed from the list. If you mess up, you can get the commit back using the reflog. – Zaz Apr 29 '15 at 0:11

I'm appending this answer because I don't see why anyone who has just tried to commit work would want to delete all that work because of some mistake using Git!

If you want to keep your work and just 'undo' that commit command (you caught before pushing to repo):

git reset --soft HEAD~1

Do not use the --hard flag unless you want to destroy your work in progress since the last commit.

share|improve this answer
3  
Here's an example of why: you do a small piece of work on a development server that you commit. Then it turns out that that server doesn't have outgoing HTTPS access, so you can't push the commit anywhere. Easiest to just pretend it never happened, and redo the patch from your local machine. – Steve Bennett Jan 3 '13 at 4:32
1  
you could just as easily do git commit --amend in this scenario which is way less confusing – UpAndAdam Jul 24 '13 at 22:26
2  
reset --soft was the life savior to not lose current work. – RaphaelDDL Dec 31 '13 at 16:19
2  
Thanks. This answer should be ranked higher or included in the accepted answer. Deleting a commit != reverting a commit. – Alsciende Mar 5 '14 at 13:32
2  
@RandolphCarter: you will still lose any uncommitted changes though. – naught101 Sep 1 '14 at 8:18

If you didn't publish changes, to remove latest commit, you can do

$ git reset --hard HEAD^

(note that this would also remove all uncommitted changes; use with care).

If you already published to-be-deleted commit, use git revert

$ git revert HEAD
share|improve this answer
    
That didn't work. When I git log, everything is still there, no matter why I do it just adds more commits. I wanna clean up the history. – Costa May 9 '14 at 14:42
    
@Costa: What didn't work (i.e. which version did you use), and how did you git log? – Jakub Narębski May 9 '14 at 14:44
    
I've tried almost everything on this Q&A. (I tried git revert HEAD, most recently) My git log: tree = log --all --graph --format=format:'%C(bold blue)%h%C(reset) %C(dim black)%s%C(reset)%C(bold red)%d%C(reset) %C(green)by %an, %ar%C(reset)' – Costa May 9 '14 at 14:46
1  
I just want to delete the commits (like as if they never existed). I went off on some weird coding adventure, with several new commits, and it all ended up being trash. How can I just erase those from my git log? – Costa May 9 '14 at 14:55
1  
Holy crap something magically did exactly what I wanted.... which one of those commands did it?!!?! – Costa May 9 '14 at 14:57

Removing an entire commit

git rebase -p --onto SHA^ SHA

Obviously replace "SHA" with the reference you want to get rid of. The "^" in that command is literal.

http://sethrobertson.github.io/GitFixUm/fixup.html

share|improve this answer

If you want to fix up your latest commit, you can undo the commit, and unstage the files in it, by doing:

git reset HEAD~1

This will return your repository to its state before the git add commands that staged the files. Your changes will be in your working directory. HEAD~1 refers to the commit below the current tip of the branch.

If you want to uncommit N commits, but keep the code changes in your working directory:

git reset HEAD~N

If you want to get rid of your latest commit, and do not want to keep the code changes, you can do a "hard" reset.

git reset --hard HEAD~1

Likewise, if you want to discard the last N commits, and do not want to keep the code changes:

git reset --hard HEAD~N
share|improve this answer
git reset --hard commitId

git push --force

PS: CommitId refers the one which you want to revert back to

share|improve this answer
    
git push --force <origin> <branchName>. as without mentioning branch name it might change all file on remote. – sheelpriy Jun 22 at 6:46

To delete in local branch, use

git reset --hard HEAD~1

To delete in a remote branch, use

git push origin HEAD --force
share|improve this answer

All the commands above restore the state of your work tree and index as they were before making the commit, but do not restore the state of the repository. If you look at it, the "removed" commit is not actually removed, it is simply not the one on the tip of the current branch.

I think that there are no means to remove a commit with porcelain commands. The only way is to remove it from the log and reflog and then to execute a git prune --expire -now.

share|improve this answer
    
The order in which answers are shown on StackOverflow is not fixed. Please do not refer to “All the commands above”. Make your own answer self-contained. – Pascal Cuoq Jan 16 '14 at 12:56
    
This answer isn't entirely correct. git prune is actually one of the "porcelain" commands. Also, it is rare that you would want to completely clear out your reflog (one use case is to remove sensitive info from your repo, but like I said, that's a rare use case). More often than not, you'll want to keep old commits around in the reflog, in case you need to recover data. See Pro Git: 9.7 Git Internals - Maintenance and Data Recovery. – user456814 May 14 '14 at 7:12

Here's another way to do this:

Checkout the branch you want to revert, then reset your local working copy back to the commit that you want to be the latest one on the remote server (everything after it will go bye-bye). To do this, in SourceTree I right-clicked on the and selected "Reset BRANCHNAME to this commit". I think the command line is:

git reset --hard COMMIT_ID

Since you just checked out your branch from remote, you're not going to have any local changes to worry about losing. But this would lose them if you did.

Then navigate to your repository's local directory and run this command:

git -c diff.mnemonicprefix=false -c core.quotepath=false \
push -v -f --tags REPOSITORY_NAME BRANCHNAME:BRANCHNAME

This will erase all commits after the current one in your local repository but only for that one branch.

share|improve this answer

If you want to keep the history, showing the commit and the revert, you should use:

git revert GIT_COMMIT_HASH

enter the message explaining why are you reverting and then:

git push  

When you issue git log you'll see both the "wrong" commit and revert log messages.

share|improve this answer
    
Yes, but the OP was clear that that's not what they want. – Steve Bennett Dec 1 '15 at 2:57
git rebase -i HEAD~2

Here '2' is the number of commits you want to rebase.

'git rebase -i HEAD`

if you want to rebase all the commits.

Then you will be able to choose one of these options.

p, pick = use commit

r, reword = use commit, but edit the commit message

e, edit = use commit, but stop for amending

s, squash = use commit, but meld into previous commit

f, fixup = like "squash", but discard this commit's log message

x, exec = run command (the rest of the line) using shell

d, drop = remove commit

These lines can be re-ordered; they are executed from top to bottom. If you remove a line here THAT COMMIT WILL BE LOST. However, if you remove everything, the rebase will be aborted. Note that empty commits are commented out

You can simply remove that commit using option "d" or Removing a line that has your commit.

share|improve this answer
    
Probably the easiest way is this. Because with the interactivity you know exactly what you are doing. Thank you – sandino Jun 15 at 12:46

If you just messed up your last commit (wrong message, forgot to add some changes) and want to fix it before pushing it to a public repo why not use:

git commit --amend -m "New message here"

If you have newly staged changes they'll be combined with the last commit (that you're trying to get rid of) and will replace that commit.

Of course if you amend a commit after you've pushed it, you're rewriting history so if you do that be sure to understand the implications.

You can also pass the '--no-edit' option instead of '-m' if you would prefer to use the previous commit's message.

Docs: http://git-scm.com/docs/git-commit.html

share|improve this answer
    
That's not what OP is asking for. – Steve Bennett Dec 1 '15 at 2:58

The mistake:

I git rebase -i --root'ed my branch, ignorantly thinking I could reword the first commit differing from the master (the GitHub for Windows default view is the comparison to master, hiding it's entirety).

I grew a Silicon Valley beard while 900+ commits loaded themselves into Sublime. Exiting with no changes, I charged my battery then proceeded to shave, as all 900+ individual commits nonchalantly rebased - resetting their commit times to now.

Determined to beat Git and preserve the original times, I deleted this local repository and re-cloned from the remote.

Now it had re-added a most recent unneeded commit to master I wished to remove, so proceeded like so.

Exhausting the options:

I didn't wish to git revert - it would create an additional commit, giving Git the upper hand.

git reset --hard HEAD did nothing, after checking the reflog, the last and only HEAD was the clone - Git wins.

To get the most recent SHA, I checked the remote repository on github.com - minor win.

After thinking git reset --hard <SHA> had worked, I updated another branch to master and 1... 2... poof! the commit was back - Git wins.

Checking back out to master, time to try git rebase -i <SHA>, then remove the line... to no avail, sad to say. "If you remove a line here THAT COMMIT WILL BE LOST". Ah...glossed over new feature troll the n00b in the 2.8.3 release notes.

The solution:

git rebase -i <SHA> then d, drop = remove commit.

To verify, I checked out to another branch, and voila - no hiding commit to fetch/pull from the master.

https://twitter.com/holman/status/706006896273063936

Good day to you.

share|improve this answer

Take backup of your code in to temp folder. Following command will reset same as server.

git reset --hard HEAD
git clean -f
git pull

Then copy the required files alone from temp folder, then commit

share|improve this answer

Assuming you have not pushed to the remote repository, you could re-clone the repository. This has been my method of choice a few times.

share|improve this answer
    
Obviously, it's pushed to the repository based on the OP. – Lucas Huang Apr 16 at 2:18

git reset --hard

git push origin HEAD --force

If one or more of the commits is tagged, delete the tag(s) first. Otherwise the tagged commit is not removed.

share|improve this answer

I know this question is fully answered, but I'd like to summarize the (few) safe steps to undo a git commit for those (like me) who were in panic after a bad commit:

  1. go into the source directory and make a backup of your code with command:

    tar czvf code.tgz *

  2. display the git commit list with the command:

    git log

  3. get the "sha1-commit-id" of the commit under your unwanted commit, this is the id of the commit before yours (the git log lists the more recent commit first)

  4. revert back the unwanted commit with the command

    git reset --hard "sha1-commit-id"

    *you can check you did it correctly by issuing anoter git log command*

  5. get back your uncommited code with the command:

    tar xzvf code.tgz

The tar commands are used to get sure your hard work does not get wiped by mistake, as the git reset command will delete your working directory changes, so step 1 and 5 are used to stash the local changes.

share|improve this answer
10  
The tar step is unnecessary; that's the point of git. Use git reflog to see all items in the history (including e.g. your reset). – dbw Jan 16 '13 at 0:47
1  
the tar steps (points 1 and 5) are needed in order not to lost the modified files; perhaps some git commands can do it for you, but I am a git newbie and I prefer to have control of my files this way – Zac Jan 18 '13 at 11:04
9  
The question posted asks how to delete a git commit. I down-voted this answer because it uses a completely unrelated tool, tar, instead of git to accomplish this task. 1. some people may not have that installed depending on what OS they are using, 2. using backup software to do your own version control manually instead of learning to use git correctly is in my opinion a terrible idea and 5 steps compared to the 1 step correct answer of "git rebase -i <sha-commit-id>~1" – pilavdzice Apr 2 '13 at 18:56
2  
P.S. This answer also forgets to delete the created tar file, leaving a large file there to waste hard disk space on your system. Also does not diff but instead copies everything, so this has terrible performance as well. Normally I don't downvote any answers if they are even remotely, sort-of correct as there is always more than one way to skin a cat that might be useful to someone, but in this case it's like skinning the cat by plucking out one hair at a time - use this and risk getting scratched! – pilavdzice Apr 2 '13 at 19:11
2  
If you reset the master head, it will wipe all the changes you already have. In order to get those in unversioned version, you need to stash them. However, I am not sure that the stash would survive head hard reset, so I would rely on using tar instead. The answer is good and idiot-proof. I don't understand why it has -7 votes. Haters gonna hate.. +1 from me! – Nikola Petkanski Jun 23 '14 at 15:42

protected by KyleMit Mar 16 '15 at 15:19

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

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