2004

I "accidentally" pushed a commit to GitHub.

Is it possible to remove this commit?

I want to revert my GitHub repository as it was before this commit.

ivanleoncz
  • 9,070
  • 7
  • 57
  • 49
hectorsq
  • 74,396
  • 19
  • 43
  • 46
  • 222
    **Word of caution**: Do not ever do this when you have a lot of people following your repository, you will make their local repository go out of sync if they have pulled in the latest changes. If this concerns a mistake, you can just do another commit undoing the mistake. If this concerns a password, you might want to change the password instead and don't hurry to delete this. *Forcing things* does not go without drawbacks. – Tamara Wijsman Nov 16 '12 at 17:19
  • 176
    **Word of caution 2:** The commit can still be accessible directly via SHA1. Force push does not delete the commit, it creates a new one and moves the file pointer to it. To truly delete a commit you must delete the whole repo. – Gustav Mar 15 '13 at 13:14
  • 30
    @Gustav _"... you must delete the whole repo."_ - Or just force garbage collection to kick in. – IQAndreas May 19 '14 at 18:16
  • I was looking for how to revert a commit purely though the github interface. For this question I would suggest pushing a new commit that reverts the change instead of rewriting history. – ThorSummoner May 21 '14 at 21:03
  • 5
    With regard to WOC1, the next time followers pull, they will automatically get the new history and lose the old one, which seems quite acceptable behaviour. The problem is if other people may have committed new work *after* your commit: then you are causing a significant amount of hassle for them (they will need to cherry-pick their changes onto the new history). This makes a force push more acceptable after *1 minute* than after *1 week* (fewer followers exposed), and more acceptable for projects which people ***use*** but don't ***modify*** (they won't notice the timeline was changed). – joeytwiddle Jun 17 '14 at 05:17
  • Related: [Undo the last Git commit?](http://stackoverflow.com/q/927358/456814). –  Jul 17 '14 at 18:17
  • 10
    [Bitbucket version of this question](http://stackoverflow.com/questions/14836696/delete-last-commit-in-bitbucket). – naught101 Sep 01 '14 at 05:20
  • 2
    Re **WOC2**: the commit is accessible via the reflog but only *temporarily*, as long as reflog is not expired. `git fsck --no-reflogs` will show it. To force reflog to expire, try: `git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 -c gc.pruneExpire=now gc` – rustyx Jul 27 '15 at 09:54
  • 2
    @IQAndreas [Once you have pushed a commit to GitHub, you should consider any data it contains to be compromised](https://help.github.com/articles/remove-sensitive-data/). – galath Feb 11 '16 at 10:42
  • This might be totally crazy but what about removing the branch from GitHub altogether and then pushing your local branch to GitHub? (considering you're the only one working on this branch or you know and can take care of possible consequences) – Amin Dannak Jun 21 '21 at 17:28
  • 2
    @Gustav and **WOC2**: I just made a test repo and could confirm this. Commit will be available through the hash even if they are deleted, but with the message `This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.` – xaratustra Nov 29 '22 at 14:38
  • Word of caution 3: You can loose all your changes both from local and origin, I did :( – Anil P Babu Aug 18 '23 at 11:44

21 Answers21

1461

Note: please see an alternative to git rebase -i in the comments below—

git reset --soft HEAD^

First, remove the commit on your local repository. You can do this using git rebase -i. For example, if it's your last commit, you can do git rebase -i HEAD~2 and delete the second line within the editor window that pops up.

Then, force push to GitHub by using git push origin +branchName --force

See Git Magic Chapter 5: Lessons of History - And Then Some for more information (i.e. if you want to remove older commits).

Oh, and if your working tree is dirty, you have to do a git stash first, and then a git stash apply after.

Kenly
  • 24,317
  • 7
  • 44
  • 60
Can Berk Güder
  • 109,922
  • 25
  • 130
  • 137
  • 1
    No local tree modification is necessary at all to satisfy the users's request. – Dustin Jan 17 '09 at 22:44
  • Note that removing the commit locally will completely trash it, not just “uncommit” it. I don't think it can be recovered. –  Apr 19 '11 at 14:50
  • 27
    Note that this will still leave the commit in the reflog. If you have sensitive data in there, you may have to delete the repo entirely. – troelskn Jul 21 '11 at 16:02
  • 134
    I'm confused. Why is it not possible to uncommit with `git reset --soft HEAD^` and then do `git push origin +master`? Why are we using `git rebase -i HEAD^^` in this case? – Dennis Oct 23 '12 at 07:23
  • 62
    @Dennis because I wasn't familiar with `reset --soft` 3.5 years ago. =) – Can Berk Güder Oct 27 '12 at 18:33
  • 2
    @Nick Done. I just used the `git reset --soft` approach and it worked beautifully. `git rebase` is some kind of git black magic that scares me. – noahlz Jul 14 '13 at 22:44
  • 44
    Everyone beware. See subutux's comment below. Even after force pushing to GitHub, GH still caches your commit. From https://help.github.com/articles/remove-sensitive-data : "Danger: Once the commit has been pushed you should consider the data to be compromised. If you committed a password, change it! If you committed a key, generate a new one." – Patrick Aug 09 '13 at 07:54
  • 1
    is this really deleting a commit or just reverting changes? – Tejas Manohar Aug 08 '14 at 01:56
  • 1
    sorry, what does "+" in + mean? – vietstone Feb 17 '17 at 06:53
  • 1
    Oh, it means "force push", right? – vietstone Feb 17 '17 at 06:58
  • 1
    Your "delete the second line" comment is out of date or needs clarification. – redwards510 Nov 02 '17 at 18:02
  • Hi tried this but it tells me "Everything up-to-date" and doesn't work. any idea? – LoveCoding Nov 06 '20 at 03:17
  • Thank you, it's working for me but the "delete the second line" seem incorrect to me. I have A - B - C and I've end up deleted B - C not C only :(. – Loc_rabbirt Nov 13 '20 at 14:14
  • why do you put `+` before `branchname`? – Viesturs May 25 '21 at 19:56
  • Here's a good reference on "git reset --soft HEAD^" https://stackoverflow.com/questions/24568936/what-is-difference-between-git-reset-hard-head1-and-git-reset-soft-head – entropo Aug 29 '21 at 04:27
  • Also "HEAD^" is equivalent to "HEAD~1" See: https://salferrarello.com/git-head-tilde-vs-head-caret/ – entropo Aug 29 '21 at 04:30
  • So i followed your solution and it was overwrited and pushed on the wrong repos. So i lost the commit that i want ? is there a solution to retrieve it again ? – Marinos TBH Jun 01 '22 at 14:20
  • Thank a lot! If your remote branch is protected from force push, just change it's settings! – MH Malekian May 26 '23 at 21:08
1108
git push -f origin HEAD^:master

That should "undo" the push.

Dustin
  • 89,080
  • 21
  • 111
  • 133
  • 38
    This worked fine too! It removes the push from github but leaves my local repository intact. Thanks! – hectorsq Jan 18 '09 at 00:41
  • 12
    Well, yes. It only does what you asked for. :) Your repository and the remote repository don't have to have matching refs. – Dustin Jan 18 '09 at 07:45
  • 41
    Note, however, that this only moves the branch pointer. The accidentally pushed commit is still present in the remote repo. In GitHub's case, this means that it can still be seen if you know the SHA-1 hash (from user activity history, for example). – Thiago Arrais Jun 16 '11 at 16:09
  • 89
    do: git push -f origin HEAD^^:master to reverse the 2 last changes, works n times – ianj Jul 17 '11 at 23:38
  • 4
    If you are using the github app you can also navigate to the "history" screen, open up your commit, and click "revert commit" or you can select your previous commit and click "revert to this commit". "revert to this commit" reverts all changes that happened after that commit. I find that the app works fine as long as your working directory is clean. If it's not, things can get weird fast with the app, in which case the command line will help keeps things straight. – Judah Feb 21 '12 at 19:25
  • 4
    I removed local commit with : `git reset --hard HEAD~1` (http://stackoverflow.com/questions/1338728/how-to-delete-a-git-commit) – Jeaf Gilbert Mar 01 '12 at 09:37
  • 26
    @ianj Note that HEAD with n ^'s can be replaced by HEAD~n, e.g. HEAD~3 instead of HEAD^^^. – Mark Reed Aug 29 '12 at 23:53
  • Doesn't work for me. Instead git returns the message "Everything up-to-date" and my commit is still visible on my fork. – Dennis Oct 23 '12 at 07:15
  • @Dennis, your local copy could certainly be different. You can always force push the exact ref you want it to be. Otherwise, it's hard to tell what you're doing. – Dustin Oct 25 '12 at 07:22
  • 1
    Note that if your local branch isn't up to date, you'll lose more than one commit. – aymericbeaumet Aug 02 '13 at 13:15
  • 2
    With zsh use `git push -f origin HEAD\^:master` or `git push -f origin HEAD~:master` – Alter Lagos Sep 11 '13 at 16:52
  • @ThiagoArrais, why is the accidentally pushed commit still present in the remote repo? – traxium Mar 15 '16 at 16:18
  • Don't use this !! it will delete all your commits – Benny Apr 24 '17 at 12:47
  • If your local repo is out of date, it will remove all your commits up until you were. This is very dangerous. – lowcrawler Jan 31 '19 at 05:31
  • It should be `main` instead of `master` for now or maybe your other branch name. – Celuk Sep 08 '22 at 22:36
  • You're heaven-sent. This works perfectly for my specific use case. Thanks as well @ianj for that tip about n times – Aquaphor May 24 '23 at 23:20
514

For an easy revert, here's another possibility (everything since the commit will be deleted):

git reset --hard commit_hash_you_want_to_return_to

For example, if you want to reset your branch to a commit in the past like 71c27777543ccfcb0376dcdd8f6777df055ef479:

git reset --hard 71c27777543ccfcb0376dcdd8f6777df055ef479

The next step would be to push your branch modifications to origin (remote repo):

git push --force

Attention

Keep in mind that if other contributors are working with your branch, they might experience conflicts or other issues, for you are changing the history of the branch, but just for you, and not for those who are already using your branch. Beware.

ivanleoncz
  • 9,070
  • 7
  • 57
  • 49
CodeWalrus
  • 5,628
  • 1
  • 16
  • 18
  • 15
    WARNING: This will rewrite your history, you will lose the commit and is generally not a very nice thing to do in a collaborative environment. – Oliver Nov 17 '15 at 08:57
  • 10
    Yes this was the easiest and best for me. My dev fork needed to be reverted before I could send a PR for something else. I should have put my changes in a branch to begin with. – Web and Flow Dec 10 '15 at 01:47
  • 1
    This works on Unprotected branches. If the Github branch is protected, forced push will fail. – Adarsha Jan 07 '16 at 02:37
  • Or: || git reset --hard HEAD^1 || (1 is the last commit) – Marian07 Mar 11 '17 at 09:55
  • As I couldn't edit I add another comment, in case someone does this silly thing without thinking before just like me, you can go back with a "git reflog" and then a "git reset --hard xxx" where xxx is the last commit you've made before the accidental reset... – Fjallbacka Jul 08 '18 at 20:01
  • Works like a charm. Though the profile page still shows that a commit was pushed to the repository. – Prateek Gulati Sep 30 '19 at 11:07
  • And this will also remove all traces from the remote repo on Github? – timman Apr 06 '21 at 20:20
  • In order to bypass GitHub branch protection rules when you push, you can enable everyone or specific users the ability to force pushes. Edit the branch protection rule, scroll to the bottom, look for "Allow Force Pushes", and configure your options. This can allow you to temporarily or permanently enable force pushes by specific users in order to correct a mistake. You will need to perform this for each branch you wish to enable it for. – ryancdotnet Aug 17 '22 at 14:16
  • WARNING: Running the **git reset** will remove all of your local changes! – Dremiq Nov 13 '22 at 01:28
  • The commit is still accessible on github – TheRealChx101 Jun 15 '23 at 22:43
147
  1. git log to find out the commit you want to revert

  2. git push origin +7f6d03:master while 7f6d03 is the commit before the wrongly pushed commit. + was for force push

And that's it.

Here is a very good guide that solves your problem, easy and simple!

kate
  • 1,769
  • 1
  • 11
  • 10
  • 1
    This works for me for deleting a few latest published commits from a branch. – High Performance Rangsiman Aug 22 '19 at 19:58
  • 2
    After some moment trying to discover why this command was not working, you clearly pointed out here to insert the last desirable commit. And I was trying to make the first commit which is why I received the message it was up-to-date already. – Luis Febro Sep 10 '19 at 04:32
  • 1
    This should the accepted answer since the question did not specify which commit to delete. The accepted answer only deletes the *last* commit. This answer deletes *any* commit. – Dominic Cerisano Oct 07 '19 at 20:42
  • Does this remove it from the remote repo? – timman Apr 06 '21 at 20:22
104

In case you like to keep the commit changes after deletion:

Note that this solution works if the commit to be removed is the last committed one.


1 - Copy the commit reference you like to go back to from the log:

git log

2 - Reset git to the commit reference:

 git reset <commit_ref>

3 - Stash/store the local changes from the wrong commit to use later after pushing to remote:

 git stash

4 - Push the changes to remote repository, (-f or --force):

git push -f

5 - Get back the stored changes to local repository:

git stash apply

7 - In case you have untracked/new files in the changes, you need to add them to git before committing:

git add .

6 - Add whatever extra changes you need, then commit the needed files, (or use a dot '.' instead of stating each file name, to commit all files in the local repository:

git commit -m "<new_commit_message>" <file1> <file2> ...

or

git commit -m "<new_commit_message>" .
Loukan ElKadi
  • 2,687
  • 1
  • 16
  • 20
45
git reset HEAD^ --hard
git push origin -f

This work for me.

alper
  • 2,919
  • 9
  • 53
  • 102
Hilen
  • 761
  • 7
  • 8
45

You'll need to clear out your cache to have it completely wiped. this help page from github will help you out. (it helped me)

Removing sensitive data from a Repository

idanp
  • 973
  • 12
  • 18
subutux
  • 459
  • 4
  • 2
  • 12
    +1: whilst removing the commit from your branch, it's still available on GitHub if you know the URL/SHA-1. The only way of removing the commit from the cache is by contacting GH support (see the 'Cached Data on Github' section in that link – Patrick Aug 09 '13 at 07:53
  • 5
    I do want to note that it may have been a better idea to actually explain what's on the page, and quote the relevant sections. From the [help guide](http://stackoverflow.com/help/how-to-answer), it says: "Links to external resources are encouraged, but please add context around the link so your fellow users will have some idea what it is and why it’s there. Always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline." Rule of thumb: pretend the link isn't there, or they can't click on it. – Jeremy Rodi Feb 09 '16 at 12:10
  • 3
    There is another way to clear the cache: Delete the repository, then recreate and push. While this might not be possible for everyone, for many it is way easier and faster than contacting Github Support (and maybe you do not want to point to a third party [Github] that you pushed sensitive data). – Juliane Holzt Jun 21 '18 at 00:03
43

Delete the most recent commit, keeping the work you've done:

git reset --soft HEAD~1

Delete the most recent commit, destroying the work you've done:

git reset --hard HEAD~1
Ekambaram E
  • 1,184
  • 1
  • 11
  • 9
28

Use git revert for reverting your push.

git-revert - Revert some existing commits

git revert [--edit | --no-edit] [-n] [-m parent-number] [-s] <commit>...
git revert --continue
git revert --quit
git revert --abort

Revert the changes that the related patches introduce, and record some new commits that record them. This requires your working tree to be clean (no modifications from the HEAD commit).

Note: git revert is used to record some new commits to reverse the effect of some earlier commits (often only a faulty one). If you want to throw away all uncommitted changes in your working directory, you should see git-reset, particularly the --hard option.

Jyoti Prakash
  • 3,921
  • 3
  • 21
  • 24
  • 14
    That is the recommended way to avoid breaking other people's clones. It create a new commit that undoes an earlier commit. However it does not answer the question, which was to remove a commit from "history". – joeytwiddle Jun 17 '14 at 05:09
  • many of the other answers are good, but this is the only way that seems to work if you cannot do force pushes to master. – Christopher Hunter Aug 06 '18 at 20:46
  • example usage would help, better than paste from man page. Help people wade through `[]` stuff. – pauljohn32 Dec 01 '21 at 16:01
25

To delete the commit from the remote repository:

 git push -f origin last_known_good_commit:branch_name

In order delete the commit from your local repository:

git reset --hard HEAD~1

link

Community
  • 1
  • 1
george mano
  • 5,948
  • 6
  • 33
  • 43
24

You need to know your commit hash from the commit you want to revert to. You can get it from a GitHub URL like: https://github.com/your-organization/your-project/commits/master

Let's say the hash from the commit (where you want to go back to) is "99fb454" (long version "99fb45413eb9ca4b3063e07b40402b136a8cf264"), then all you have to do is:

git reset --hard 99fb45413eb9ca4b3063e07b40402b136a8cf264
git push --force
Benny Code
  • 51,456
  • 28
  • 233
  • 198
11

Find the ref spec of the commit you want to be the head of your branch on Github and use the following command:

git push origin +[ref]:[branchName]

In your case, if you just want to go back one commit, find the beginning of the ref for that commit, say for example it is 7f6d03, and the name of the branch you want to change, say for example it is master, and do the following:

git push origin +7f6d03:master

The plus character is interpreted as --force, which will be necessary since you are rewriting history.

Note that any time you --force a commit you could potentially rewrite other peoples' history who merge your branch. However, if you catch the problem quickly (before anyone else merges your branch), you won't have any issues.

orb
  • 1,263
  • 1
  • 10
  • 16
11

If you are doing this because you have sensitive data in a commit, using the other answers here is not safe (excepting subutux's, which I'll expand on).

The github guide on this recommends using a external tool, but I prefer using the built-in one.

Firstly, make a backup of your repository. Then:

git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA' \
--prune-empty --tag-name-filter cat -- --all

After this, make sure the repository is in the state you want. You might want to diff against the backup.

If you're sure it's correct, then:

#get rid of old unreferenced commits (including the data you want to remove)
git gc --prune=now
git push origin --force --all

You might want to keep the local backup for a while, just in case.

loopbackbee
  • 21,962
  • 10
  • 62
  • 97
  • 2
    Related: https://stackoverflow.com/questions/872565/remove-sensitive-files-and-their-commits-from-git-history/32840254#32840254 I think this method is not enough, the data is still accessible via the commit. – Ciro Santilli OurBigBook.com Feb 18 '18 at 00:20
7

Run this command on your terminal.

git reset HEAD~n

You can remove the last n commits from local repo e.g. HEAD~2. Proceed with force git push on your repository.

git push -f origin <branch>

Hope this helps!

Kent Aguilar
  • 5,048
  • 1
  • 33
  • 20
4

To preserve the branching and merging structure is important to use the --preserve-merges option when doing the rebase:

git rebase --preserve-merges -i HEAD^^
Carlos Mafla
  • 489
  • 1
  • 6
  • 12
  • Note: it is not recommended to use `--preserve-merges` and `--interactive` together. See the [BUGS section on rebase](https://git-scm.com/docs/git-rebase) – galath Feb 11 '16 at 10:30
4

For GitHub

  • Reset your commits (HARD) in your local repository
  • Create a new branch
  • Push the new branch
  • Delete OLD branch (Make new one as the default branch if you are deleting the master branch)
M_R_K
  • 5,929
  • 1
  • 39
  • 40
2

Save your local changes first somewhere on the side ( backup )

You can browse your recent commits, then select a commit hash by clicking on "Copy the full SHA" button to send it to the clipboard.

If your last commit hash is, let's say g0834hg304gh3084gh ( for example )

You have to run:

git push origin +g0834hg304gh3084gh:master

Using the hash that you've copied earlier to make it the "HEAD" revision.

Add your desired local changes. Done ;)

zOqvxf
  • 1,469
  • 15
  • 18
2

In GitHub Desktop you can just right click the commit and revert it, which will create a new commit that undoes the changes.

The accidental commit will still be in your history (which may be an issue if, for instance, you've accidentally commited an API key or password) but the code will be reverted.

This is the simplest and easiest option, the accepted answer is more comprehensive.

Keith
  • 150,284
  • 78
  • 298
  • 434
  • I have seen this cause problems with git flow. Example, you accidentally merge develop into master for a feature not to be released yet. If you just revert that merge, then when you merge master back down to develop it will remove the feature from there. – pumpkinthehead Apr 12 '19 at 02:09
1

if you want to remove do interactive rebase,

git rebase -i HEAD~4

4 represents total number of commits to display count your commit andchange it accordingly

and delete commit you want from list...

save changes by Ctrl+X(ubuntu) or :wq(centos)

2nd method, do revert,

git revert 29f4a2 #your commit ID

this will revert specific commit

Mohideen bin Mohammed
  • 18,813
  • 10
  • 112
  • 118
0

It is not very good to re-write the history. If we use git revert <commit_id>, it creates a clean reverse-commit of the said commit id.

This way, the history is not re-written, instead, everyone knows that there has been a revert.

vivek_ganesan
  • 658
  • 4
  • 19
  • [This older answer](http://stackoverflow.com/a/17694680/456814) already says to user `git revert`. –  Jul 17 '14 at 18:15
  • That doesn't meet this requirement: "I want to revert my GitHub repository as it was before this commit" – Steve Bennett Jul 20 '15 at 07:48
-1

Add/remove files to get things the way you want:

git rm classdir
git add sourcedir

Then amend the commit:

git commit --amend

The previous, erroneous commit will be edited to reflect the new index state - in other words, it'll be like you never made the mistake in the first place

Note that you should only do this if you haven't pushed yet. If you have pushed, then you'll just have to commit a fix normally.

Chiragkumar Thakar
  • 3,616
  • 5
  • 37
  • 49