Categories
git git-checkout git-reset git-revert

How do I revert a Git repository to a previous commit?

7618

How do I revert from my current state to a snapshot made on a certain commit?

If I do git log, then I get the following output:

$ git log
commit a867b4af366350be2e7c21b8de9cc6504678a61b`
Author: Me <[email protected]>
Date:   Thu Nov 4 18:59:41 2010 -0400

blah blah blah...

commit 25eee4caef46ae64aa08e8ab3f988bc917ee1ce4
Author: Me <[email protected]>
Date:   Thu Nov 4 05:13:39 2010 -0400

more blah blah blah...

commit 0766c053c0ea2035e90f504928f8df3c9363b8bd
Author: Me <[email protected]>
Date:   Thu Nov 4 00:55:06 2010 -0400

And yet more blah blah...

commit 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
Author: Me <[email protected]>
Date:   Wed Nov 3 23:56:08 2010 -0400

Yep, more blah blah.

How do I revert to the commit from November 3, i.e. commit 0d1d7fc?

3

11525

This depends a lot on what you mean by “revert”.

Temporarily switch to a different commit

If you want to temporarily go back to it, fool around, then come back to where you are, all you have to do is check out the desired commit:

# This will detach your HEAD, that is, leave you with no branch checked out:
git checkout 0d1d7fc32

Or if you want to make commits while you’re there, go ahead and make a new branch while you’re at it:

git checkout -b old-state 0d1d7fc32

To go back to where you were, just check out the branch you were on again. (If you’ve made changes, as always when switching branches, you’ll have to deal with them as appropriate. You could reset to throw them away; you could stash, checkout, stash pop to take them with you; you could commit them to a branch there if you want a branch there.)

Hard delete unpublished commits

If, on the other hand, you want to really get rid of everything you’ve done since then, there are two possibilities. One, if you haven’t published any of these commits, simply reset:

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.

If you mess up, you’ve already thrown away your local changes, but you can at least get back to where you were before by resetting again.

Undo published commits with new commits

On the other hand, if you’ve published the work, you probably don’t want to reset the branch, since that’s effectively rewriting history. In that case, you could indeed revert the commits. With Git, revert has a very specific meaning: create a commit with the reverse patch to cancel it out. This way you don’t rewrite any history.

# This will create three separate revert commits:
git revert a867b4af 25eee4ca 0766c053

# It also takes ranges. This will revert the last two commits:
git revert HEAD~2..HEAD

#Similarly, you can revert a range of commits using commit hashes (non inclusive of first hash):
git revert 0d1d7fc..a867b4a

# Reverting a merge commit
git revert -m 1 <merge_commit_sha>

# To get just one, you could use `rebase -i` to squash them afterwards
# Or, you could do it manually (be sure to do this at top level of the repo)
# get your index and work tree into the desired state, without changing HEAD:
git checkout 0d1d7fc32 .

# Then commit. Be sure and write a good message describing what you just did
git commit

The git-revert manpage actually covers a lot of this in its description. Another useful link is this git-scm.com section discussing git-revert.

If you decide you didn’t want to revert after all, you can revert the revert (as described here) or reset back to before the revert (see the previous section).

You may also find this answer helpful in this case:
How can I move HEAD back to a previous location? (Detached head) & Undo commits

8

  • 170

    @Rod’s comment on git revert HEAD~3 as the best wat to revert back 3 commits is am important convention.

    Aug 22, 2012 at 15:16


  • 32

    Could you write the whole number? like: git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50

    – Spoeken

    Dec 4, 2012 at 13:58

  • 20

    @MathiasMadsenStav Yes, you can of course specify commits by the full SHA1. I used abbreviated hashes to make the answer more readable, and you also tend to use them if you’re typing out. If you’re copying and pasting, by all means use the full hash. See Specifying Revisions in man git rev-parse for a full description of how you can name commits.

    – Cascabel

    Dec 4, 2012 at 16:55

  • 71

    You can use git revert --no-commit hash1 hash2 ... and after this just commit every single revert in one commit git commit -m "Message"

    Sep 24, 2013 at 12:12

  • @cascabel git revert -m <number> <full SHA1> worked fine for me! I prefer this over git revert <commit SHA1>

    Sep 22, 2021 at 15:38

3022

+50

Lots of complicated and dangerous answers here, but it’s actually easy:

git revert --no-commit 0766c053..HEAD
git commit

This will revert everything from the HEAD back to the commit hash, meaning it will recreate that commit state in the working tree as if every commit after 0766c053 had been walked back. You can then commit the current tree, and it will create a brand new commit essentially equivalent to the commit you “reverted” to.

(The --no-commit flag lets git revert all the commits at once- otherwise you’ll be prompted for a message for each commit in the range, littering your history with unnecessary new commits.)

This is a safe and easy way to rollback to a previous state. No history is destroyed, so it can be used for commits that have already been made public.

6

  • 40

    If you really do want to have individual commits (instead of reverting everything with one big commit), then you can pass --no-edit instead of --no-commit, so that you don’t have to edit a commit message for each reversion.

    – user456814

    Jun 28, 2014 at 20:11

  • 153

    If one of the commits between 0766c053..HEAD is a merge then there will be an error popping up (to do with no -m specified). This may help those encountering that: stackoverflow.com/questions/5970889/…

    – timhc22

    Nov 21, 2014 at 11:55


  • 37

    $ git revert --no-commit 53742ae..HEAD returns fatal: empty commit set passed

    – Alex G

    Aug 1, 2016 at 20:30


  • 5

    If you remove that ‘..HEAD’ at the end of the command, you can remove only a specific commit. For example: git revert --no-commit 0766c053 will remove only the specific changes made for 0766c053 keeping all changes after 0766c053 untouched.

    – wensiso

    Aug 12, 2021 at 14:22

  • 1

    As @timhc22 mentioned, this doesn’t work if there is one or more merge commits in between (which can happen frequently). An answer that really works in all cases and is just as safe is here: stackoverflow.com/a/15563149/4135063

    – Pedro A

    Dec 2, 2021 at 3:36

1902

Rogue Coder?

Working on your own and just want it to work? Follow these instructions below, they’ve worked reliably for me and many others for years.

Working with others? Git is complicated. Read the comments below this answer before you do something rash.

Reverting Working Copy to Most Recent Commit

To revert to the previous commit, ignoring any changes:

git reset --hard HEAD

where HEAD is the last commit in your current branch

Reverting The Working Copy to an Older Commit

To revert to a commit that’s older than the most recent commit:

# Resets index to former commit; replace '56e05fced' with your commit code
git reset 56e05fced 

# Moves pointer back to previous HEAD
git reset --soft [email protected]{1}

git commit -m "Revert to 56e05fced"

# Updates working copy to reflect the new commit
git reset --hard

Credits go to a similar Stack Overflow question, Revert to a commit by a SHA hash in Git?.

3

  • 47

    I did that, but then I wasn’t able to commit and push to the remote repository. I want a specific older commit to become HEAD…

    – Lennon

    Sep 24, 2012 at 18:17

  • 10

    @Lennon. Say you made a change, committed, and pushed it. You want both local and remote to appear as though this never happened. First git reset --hard HEAD^ You’ve now blown away all local changes from the last commit. Then: git push --force origin HEAD This takes the current HEAD commit in local and overwrites the HEAD in the remote, removing the last commit. Note: This isn’t a secure way to delete secrets accidentally pushed to a remote. Assume all secrets are compromised then See caveats for ‘–force’: evilmartians.com/chronicles/…

    – entropo

    Aug 29, 2021 at 5:46

  • After reseting you need to do git push -f. Be VERY careful because it will erase the commits in front of the one you reset to from your remote branch!

    – James L.

    Nov 23, 2021 at 17:30