ChatGPT解决这个技术问题 Extra ChatGPT

Rollback to an old Git commit in a public repo

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.

git revert does not work?
As stated in my question, this really doesn't help me if i want to revert back to something 20 commits ago.
This question has been quite well answered here stackoverflow.com/questions/4114095/…
It's not clear what you mean by "rolling back". Does that mean you want to temporarily switch your working copy to a particular revision? Or you do want to permanently revert the history of your repository back to a certain revision?
You should accept an answer, and possibly vote up the any other answers you like.

S
Sunil Kumar

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.


@AlexReisner That period at the end points at the directory you are currently in, which is not necessarily the entire git project, correct? If you wanted to apply the changes to the whole project, would you instead use ':/' like in 'git add :/', if you were not currently in the git project root?
note: if you have added new files to your project since then, this won't delete them. So when you go to build (depending on your platform), you may get errors still. Delete the new files and you're good to go.
@MSpreij 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.
Its great when you can clone a project in another directory and use git checkout [revision] . to get back to a specific revision and then compare it with the same project in other directory. Saves a lot of time.
Damnit, I forgot the "." what damage have I do to my repository ?
C
Community

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?


only difference between this approach and "git checkout [revision] ." is that the latter preserves revisions.
This answer is WRONG as OP specifically states "I can't use reset cause this repo is public"
If repo is public, I think there is no way to rollback the commit on public repository without using force push (git push -f) as it will affect the people who have pulled in the changes before rollback. So, reset can be used in local sandbox of a public repo also.
It's great that this avoids a detached HEAD! Just what I was looking for.
@Yarin the answer is GOOD, the premises of OP are WRONG that he can't use reset on public repo. He can. Sorry for necromancy comment ;)
B
Ben

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.


Doesn't this put you into the weird 'Not currently on any branch' state? How do you commit changes to complete the rollback?
Well, I'm just suggesting the use of git checkout -- he's free to check out into any branch (current or new) that he wishes. I'll update my answer so it's not ambiguous.
I tried this but I don't think this is the proper way to do it cause it leaves stagnate files. This doesn't delete files that weren't in that last commit.
If you're in a working directory and you're staying in master, you need git reset to delete those files, which you say you don't want to do. Try doing it into a separate branch: git checkout <commit> -b <branchname>, you won't have stagnant files in that branch.
The problem with using checkout is that it won't delete files that were added in a previous commit.
佚名

The original poster states:

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 cause this repo is public.

It's not necessary to use git revert X times. git revert can accept a commit range as an argument, so you only need to use it once to revert a range of 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 merge commits. 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 revert will actually remove any files that were added in any of the commits that you're reverting, which makes this the correct way to revert a range of revisions.

Documentation

git-revert(1) Manual Page.

Commit Ranges.


Note: this creates a new commit with the reverted changes. Perfect for OP's question. But make sure that's what you want. (The examples in the git-revert doc linked to above is excellent.) If you instead wish to investigate prior commits (ie before choosing what commit to revert to) use the checkout option mentioned in other answers, keeping in mind the comments others have made about deleted files.
@SherylHohman Reverting back to a previous commit doesn't create a new commit. I can't imagine what you mean here.
I
Igor

Step 1: fetch list of commits:

git log

You'll get list like in this example:

[Comp:Folder User$ git log
commit 54b11d42e12dc6e9f070a8b5095a4492216d5320
Author: author <author@gmail.com>
Date:   Fri Jul 8 23:42:22 2016 +0300

This is last commit message

commit fd6cb176297acca4dbc69d15d6b7f78a2463482f
Author: author <author@gmail.com>
Date:   Fri Jun 24 20:20:24 2016 +0300

This is previous commit message

commit ab0de062136da650ffc27cfb57febac8efb84b8d
Author: author <author@gmail.com>
Date:   Thu Jun 23 00:41:55 2016 +0300

This is previous previous commit message
...

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

git checkout fd6cb176297acca4dbc69d15d6b7f78a2463482f

That's all.


And this affects only your local, right? I need to find where a bug occurred, and was going to use this approach to keep getting different commits until the error went away. I only want to change my local though; not remote.
S
Shiva Prasad

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

j
jthill
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_to
git 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.


This is the only straightforward approach that worked like a charm! I checked out from head, ran this command, and it successfully removed added files that we had introduced and reverted all the changes. Excellent.
D
Daniel Viglione

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.


N
Naved Ahmad

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.


k
ken

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


Checking out master resolves the problem of remaining detached, while doing git reset --hard or git checkout -- . did worked but remained detached
m
mcvkr

Here is an example to do that

    cd /yourprojects/project-acme 


    git checkout efc11170c78 .