How can I go about rolling back to a specific commit in git?

The best answer someone could give me was to use git revert X times until I reach the desired commit.

So let's say I want to revert back to a commit that's 20 commits old, I'd have to run it 20 times.

Is there an easier way to do this?

I can't use reset because this repository is public.

13

Best Answer


Try this:

git checkout [revision] .

where [revision] is the commit hash (for example: 12345678901234567890123456789012345678ab).

Don't forget the . at the end, very important. This will apply changes to the whole tree. You should execute this command in the git project root. If you are in any sub directory, then this command only changes the files in the current directory. Then commit and you should be good.

You can undo this by

git reset --hard 

that will delete all modifications from the working directory and staging area.

To rollback to a specific commit:

git reset --hard commit_sha

To rollback 10 commits back:

git reset --hard HEAD~10

You can use "git revert" as in the following post if you don't want to rewrite the history

How to revert Git repository to a previous commit?

Well, I guess the question is, what do you mean by 'roll back'? If you can't reset because it's public and you want to keep the commit history intact, do you mean you just want your working copy to reflect a specific commit? Use git checkout and the commit hash.

Edit: As was pointed out in the comments, using git checkout without specifying a branch will leave you in a "no branch" state. Use git checkout <commit> -b <branchname> to checkout into a branch, or git checkout <commit> . to checkout into the current branch.

The original poster states:

The best answer someone could give me was to use git revert X times until Ireach the desired commit.

So let's say I want to revert back to a commit that's 20 commits old, I'd haveto run it 20 times.

Is there an easier way to do this?

I can't use reset cause this repo is public.

It's not necessary to use git revert X times. git revert can accept acommit range as an argument, so you only need to use it once to revert a rangeof commits. For example, if you want to revert the last 20 commits:

git revert --no-edit HEAD~20..

The commit range HEAD~20.. is short for HEAD~20..HEAD, and means "start from the 20th parent of the HEAD commit, and revert all commits after it up to HEAD".

That will revert that last 20 commits, assuming that none of those are mergecommits. If there are merge commits, then you cannot revert them all in one command, you'll need to revert them individually with

git revert -m 1 <merge-commit>

Note also that I've tested using a range with git revert using git version 1.9.0. If you're using an older version of git, using a range with git revert may or may not work.

In this case, git revert is preferred over git checkout.

Note that unlike this answer that says to use git checkout, git revertwill actually remove any files that were added in any of the commits that you'rereverting, which makes this the correct way to revert a range of revisions.

Documentation

  • git-revert(1) Manual Page.
  • Commit Ranges.

Step 1: fetch list of commits:

git log

You'll get list like in this example:

[Comp:Folder User$ git logcommit 54b11d42e12dc6e9f070a8b5095a4492216d5320Author: author <[email protected]>Date: Fri Jul 8 23:42:22 2016 +0300This is last commit messagecommit fd6cb176297acca4dbc69d15d6b7f78a2463482fAuthor: author <[email protected]>Date: Fri Jun 24 20:20:24 2016 +0300This is previous commit messagecommit ab0de062136da650ffc27cfb57febac8efb84b8dAuthor: author <[email protected]>Date: Thu Jun 23 00:41:55 2016 +0300This is previous previous commit message...

Step 2: copy needed commit hash and paste it for checkout:

git checkout fd6cb176297acca4dbc69d15d6b7f78a2463482f

That's all.

Want HEAD detached mode?

If you wish to rollback X time to a certain commit with a DETACHED HEAD (meaning you can't mess up anything), then by all means, use the following:

(replace X with how many commits you wish to go back)

git checkout HEAD~X

I.E. to go back one commit:

git checkout HEAD~1
git read-tree -um @ $commit_to_revert_to

will do it. It's "git checkout" but without updating HEAD.

You can achieve the same effect with

git checkout $commit_to_revert_togit reset --soft @{1}

if you prefer stringing convenience commands together.

These leave you with your worktree and index in the desired state, you can just git commit to finish.

Let's say you work on a project and after a day or so. You notice one feature is still giving you errors. But you do not know what change you made that caused the error. So you have to fish previous working commits. To revert to a specific commit:

git checkout 8a0fe5191b7dfc6a81833bfb61220d7204e6b0a9 .

Ok, so that commit works for you. No more error. You pinpointed the issue. Now you can go back to latest commit:

git checkout 792d9294f652d753514dc2033a04d742decb82a5 .

And checkout a specific file before it caused the error (in my case I use example Gemfile.lock):

git checkout 8a0fe5191b7dfc6a81833bfb61220d7204e6b0a9 -- /projects/myproject/Gemfile.lock

And this is one way to handle errors you created in commits without realizing the errors until later.

You can find the commit id related to each commit in the commits section of GitHub/BitBucket/Gitlab.Its very simple, suppose your commit id is 5889575 then if you want to go back to this part in your code then you simply need to type

git checkout 5889575 .

This will take you to that point of time in your code.

I'm not sure what changed, but I am unable to checkout a specific commit without the option --detach. The full command that worked for me was:git checkout --detach [commit hash]

To get back from the detached state I had to checkout my local branch: git checkout master

Here is an example to do that

 cd /yourprojects/project-acme git checkout efc11170c78 .

to rollback a specific commit in git:

  • to get back an old git commit: (the ac2ec... is the commit name)
git checkout ac2ece0219689ed86b08c93dfebb0d02c0f1d5b1
  • name a new branch that you want the HEAD detach will point to:
git branch get_back_to_past
  • checkout to that branch
git checkout get_back_to_past

now that branch has the past commit items. you can merge it to the master for example if you would like to.

for more info about git head, and rollback to old version: click here

on the Github find the commit you made and checkout to it.

git checkout <commit#>

example: git checkout b29ce12

enter image description here