git checkout - How do I revert a Git repository to a previous commit?

ID : 121281

viewed : 30

Tags : gitgit-checkoutgit-resetgit-revertgit

Top 5 Answer for git checkout - How do I revert a Git repository to a previous commit?

vote vote

96

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

vote vote

81

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.

vote vote

71

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 HEAD@{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?.

vote vote

70

The best option for me and probably others is the Git reset option:

git reset --hard <commidId> && git clean -f 

This has been the best option for me! It is simple, fast and effective!


** Note:** As mentioned in comments don't do this if you're sharing your branch with other people who have copies of the old commits

Also from the comments, if you wanted a less 'ballzy' method you could use

git clean -i 
vote vote

51

Before answering let's add some background, explaining what this HEAD is.

First of all what is HEAD?

HEAD is simply a reference to the current commit (latest) on the current branch. There can only be a single HEAD at any given time (excluding git worktree).

The content of HEAD is stored inside .git/HEAD, and it contains the 40-bytes SHA-1 hash of the current commit.


detached HEAD

If you are not on the latest commit - meaning that HEAD is pointing to a prior commit in history it's called detached HEAD.

Diagram illustrating the concept of detached HEAD

On the command-line it will look like this - SHA-1 hash instead of the branch name since the HEAD is not pointing to the the tip of the current branch:

Running git checkout HEAD^0 in a terminal


A few options on how to recover from a detached HEAD:


git checkout

git checkout <commit_id> git checkout -b <new branch> <commit_id> git checkout HEAD~X // x is the number of commits t go back 

This will checkout new branch pointing to the desired commit. This command will checkout to a given commit.

At this point you can create a branch and start to work from this point on:

# Checkout a given commit. # Doing so will result in a `detached HEAD` which mean that the `HEAD` # is not pointing to the latest so you will need to checkout branch # in order to be able to update the code. git checkout <commit-id>  # Create a new branch forked to the given commit git checkout -b <branch name> 

git reflog

You can always use the reflog as well. git reflog will display any change which updated the HEAD and checking out the desired reflog entry will set the HEAD back to this commit.

Every time the HEAD is modified there will be a new entry in the reflog

git reflog git checkout HEAD@{...} 

This will get you back to your desired commit.

Running git reflog in a terminal


git reset HEAD --hard <commit_id>

"Move" your HEAD back to the desired commit.

# 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. 
  • Note: (Since Git 2.7) you can also use the git rebase --no-autostash as well.

This schema illustrates which command does what. As you can see there reset && checkout modify the HEAD.

Diagram illustrating staging area and checking out HEAD

Top 3 video Explaining git checkout - How do I revert a Git repository to a previous commit?

Related QUESTION?