312

I have performed git commit followed by a git push. How can I revert that change on both local and remote repositories?

$ git log
commit 364705c23011b0fc6a7ca2d80c86cef4a7c4db7ac8
Author: Michael Silver <Michael Silver@gmail.com>
Date:   Tue Jun 11 12:24:23 2011 -0700
jub0bs
  • 60,866
  • 25
  • 183
  • 186
michael
  • 106,540
  • 116
  • 246
  • 346

8 Answers8

518
git reset --hard HEAD~1
git push -f <remote> <branch>

(Example push: git push -f origin bugfix/bug123)

This will undo the last commit and push the updated history to the remote. You need to pass the -f because you're replacing upstream history in the remote.

Edit:

Please note that --hard will make your commit unreachable (i.e. it will appear to be deleted, but you can still git show <hash> or git log <hash> it if you remember its hash). If you want to keep your changes, run:

git reset [--mixed] HEAD~1

At this point you have unstaged changes because you used --mixed, which is the default.

You may first want to update the remote tree first (i.e. remove the commit): git push -f <remote> <branch>

Since you still have your changes locally you can create another branch and commit them there (and push as you see fit).

Alexander Groß
  • 10,200
  • 1
  • 30
  • 33
  • Thanks. I get '$ git reset head~1 fatal: ambiguous argument 'head~1': unknown revision or path not in the working tree.' – michael Jun 23 '11 at 18:59
  • 37
    Alternatively, use `git reset --hard `. – Alexander Groß Jun 23 '11 at 19:03
  • 2
    The reference is called HEAD (case sensitive) – dunni Jun 23 '11 at 19:36
  • @dunni, I cannot reproduce case-sensitivity on my system. – Alexander Groß Jun 24 '11 at 15:18
  • 29
    Also, be careful - AFAIK you shouldn't be doing this if other people have pulled from the repo. – Amadan Aug 15 '13 at 00:44
  • @AlexanderGroß, is that command directly affect the master branch or working branch ? – Bipin Vayalu Apr 22 '14 at 17:37
  • 1
    @BipinVayalu It affects the branch you're currently on. More precisely, the HEAD. The HEAD is most often "attached" to a branch (pointing to a branch name instead of directly pointing to a commit). So, generally speaking, it will affect the branch HEAD points to. Use `git log --decorate --oneline` to find out where your HEAD points to. – Alexander Groß Apr 29 '14 at 09:51
  • 7
    `git reset HEAD~1` if you don't want your changes to be gone(unstaged changes). Change, commit and push again `git push -f [origin] [branch]` – softvar Jun 25 '14 at 13:41
  • @chech I'd like to see what you typed and what was the output. It could be that Git (forcefully) pushed all branches differing from the remote if you have `push.default` configured to `matching`. – Alexander Groß Oct 23 '14 at 15:49
  • @Alexander Groß fortunately I still have the output. I was in a custom branch and master was reseted too. http://pastebin.com/97FAkws9 – chech Oct 24 '14 at 06:25
  • @chech Yes, that's `push.default` pushing all branches that have changed w.r.t. origin – Alexander Groß Oct 24 '14 at 13:14
  • This only works when your Git repo settings allow history re-writes. – crmpicco Feb 10 '15 at 16:19
  • 1
    Just to point out that I tried this answer and it didn't work because my remote branch was protected. Gitlab said that it doesn't allow force push to remote branch. So I had to resort to the answer of @Amadan – DarkForce Jun 07 '17 at 16:29
  • Just note that that's a tilde, not a dash between 'HEAD' and '1' – larboyer Mar 03 '20 at 20:04
  • 1
    I almost lost a commit using the arg `--hard`, can anybody mention in the answer that, without the arg `--hard` it will also work, but will keep the changes in local? – Abu Sufian Dec 22 '22 at 21:31
  • Thanks @Abu - I did lose some work for this exact reason ... but thankfully not much work – danday74 Dec 23 '22 at 11:45
  • @AbuSufian / @danday74 You never will "lose" commits by running `git reset`. They just have become "unreachable", meaning they still exist on disk albeit not referenced by any ref (`HEAD`, a branch, or tag). You can still access those unreachable commits by their SHA. But you will not see them unless you explicitly ask for them to be shown. To retrieve such SHAs, either scroll up in your terminal or inspect `git reflog `. – Alexander Groß Dec 23 '22 at 13:25
214

Generally, make an "inverse" commit, using:

git revert 364705c

then send it to the remote as usual:

git push

This won't delete the commit: it makes an additional commit that undoes whatever the first commit did. Anything else, not really safe, especially when the changes have already been propagated.

Amadan
  • 191,408
  • 23
  • 240
  • 301
  • 9
    This is a safer (thus probably better) answer than Alexander Groß's (the chosen answer). – Graeck Sep 13 '13 at 23:32
  • 7
    @Graeck Every one of the solutions has its implications and merits. – Alexander Groß Dec 13 '13 at 13:55
  • 5
    This should be the accepted answer, it's best practice never to overwrite history, even more if collaborating with a team. `git reset` is only accepted if you still have not pushed the changes to the server. – Josue Alexander Ibarra Apr 24 '14 at 19:53
  • 20
    @JosueIbarra I disagree for all cases. For most cases, yes, you should not overwrite history. However, I believe that there are legitimate cases where you absolutely should. For instance, you accidentally commit and push up your secrets file. That shouldn't be up in the git repo. So you can quickly remove it using the accepted answer here. – bfcoder Apr 25 '14 at 19:31
  • 14
    @bfcoder if you pushed a "secret" to a remote repo, it is no longer a secret. And the proper fix is to create a new secret, not to try to hide your mistake. – Carl-Emil Kjellstrand Dec 03 '14 at 14:46
  • Just a note, this sha is to be the commit you're reverting from, not to. – scape Mar 29 '18 at 16:02
  • 1
    @Carl-EmilKjellstrand You are partially correct. The issue is not a matter of "hiding the mistake" but rather one of protecting the secret even once it is changed or in the event that the secret cannot be immediately changed (for example, in a production environment). One such case of protecting a secret is where there is secret information ABOUT a secret (such as the secret itself must conform to a limited subset of characters (alphanumeric only)) and you do not want even that information visible in the future to someone who should not have such information. – Speeddymon Oct 28 '21 at 22:56
  • @Speeddymon That is a good point, there might be exceptions as usual :) – Carl-Emil Kjellstrand Nov 25 '21 at 13:01
  • Also, there's a missing command in this solution. After reverting and before pushing you need to commit. `git revert 364705c` then `git commit -m "Some message like reverting commit 364705c."` then `git push` – Kaleb Coberly Aug 17 '22 at 00:09
59

First of all, Relax.

"Nothing is under our control. Our control is mere illusion.", "To err is human"

I get that you've unintentionally pushed your code to remote-master. THIS is going to be alright.

1. At first, get the SHA-1 value of the commit you are trying to return, e.g. commit to master branch. run this:

git log

you'll see bunch of 'f650a9e398ad9ca606b25513bd4af9fe...' like strings along with each of the commits. copy that number from the commit that you want to return back.

2. Now, type in below command:

git reset --hard your_that_copied_string_but_without_quote_mark

you should see message like "HEAD is now at ". you are on clear. What it just have done is to reflect that change locally.

3. Now, type in below command:

git push -f

you should see like

"warning: push.default is unset; its implicit value has changed in..... ... Total 0 (delta 0), reused 0 (delta 0) ... ...your_branch_name -> master (forced update)."

Now, you are all clear. Check the master with "git log" again, your fixed_destination_commit should be on top of the list.

You are welcome (in advance ;))

UPDATE:

Now, the changes you had made before all these began, are now gone. If you want to bring those hard-works back again, it's possible. Thanks to git reflog, and git cherry-pick commands.

For that, i would suggest to please follow this blog or this post.

kmonsoor
  • 7,600
  • 7
  • 41
  • 55
  • it is good measure to specify the remote and the branch too when doing "git push -f", but "git push -f" will work anyway most of the time – Robson Jun 05 '15 at 15:31
  • you could please condense and make a shorter reply...people wouldnt like reading a novel with unnecesary lines in a coding community – Ayan Mitra Jun 08 '22 at 15:08
15

git reset HEAD~1 if you don't want your changes to be gone(unstaged changes). Change, commit and push again git push -f [origin] [branch]

softvar
  • 17,917
  • 12
  • 55
  • 76
7

Try using

git reset --hard <commit id> 

Please Note : Here commit id will the id of the commit you want to go to but not the id you want to reset. this was the only point where i also got stucked.

then push

git push -f <remote> <branch>
Mohit Dhawan
  • 543
  • 6
  • 11
3

You can do an interactive rebase:

git rebase -i <commit>

This will bring up your default editor. Just delete the line containing the commit you want to remove to delete that commit.

You will, of course, need access to the remote repository to apply this change there too.

See this question: Git: removing selected commits from repository

Community
  • 1
  • 1
Jack Edmonds
  • 31,931
  • 18
  • 65
  • 77
2

Alternatively:

git push origin +364705c23011b0fc6a7ca2d80c86cef4a7c4db7ac8^:master

Force the master branch of the origin remote repository to the parent of last commit

MicRum
  • 1,711
  • 2
  • 21
  • 23
0

Using git reset --hard HEAD~1, as most suggest, will undo the last commit locally, but you will also lose those local changes.

If you don't want to lose the local changes, and rather just undo last commit:

git reset HEAD~1

Then force push it to the origin to undo the commit in the remote (assuming <remote> == origin)

git push -f origin <branch>
Bersan
  • 1,032
  • 1
  • 17
  • 28