2

I need to restore all files in my local machine to earlier revision and keep the untracked files as they are. I found this Rollback file to much earlier version using Git and did first

git reset <hash>

My files were still the same as before so I did

git checkout <hash>

This didn't help either. Then I noticed that git log didn't show up revisions which were done after revision.

Im confused what to do restore the state of earlier revision, any advice?

Community
  • 1
  • 1
jjei
  • 1,180
  • 3
  • 13
  • 21

1 Answers1

11

Both reset and checkout commands have several meanings depending on arguments and the meanings are slightly mixed.

  • reset:
    • with revision argument: Sets current branch to point to the revision specified and:
      • reset --soft <rev>: leaves both index and files intact
      • reset --mixed <rev> (this is the default with rev): makes index reflect the state at revision, but leaves files intact
      • reset --hard <rev>: overwrites both index and the files with state of the revision specified.
    • with path argument: makes index contain the checked in content of the files specified, but does not change files on disk (= undoes git add).
  • checkout:
    • with revision argument: Switches to branch or revision specified, but preserves local modifications. If some file is modified and differs between the current HEAD and the revision specified, refuses to run.
    • with path argument: Modifies the files specified to match the index, i.e. reverts unadded changes.

It follows that:

git reset <rev>
git checkout <rev>

is equivalent to just

git reset --mixed <rev>

and does not modify the state on disk. You should have done either:

git reset --hard <rev>

or

git checkout <rev>

where the first would have modified where the current branch points, while the later would switch branches. Neither would touch nonversioned files.

If you did

git reset <rev>

already and want the effect of

git reset --hard <rev>

just follow it up with

git checkout .

(the pathspec form instead of the revision form).

Update: Note, that

git reset --hard <rev>

will make current branch point to <rev>, so it will be like the commits after <rev> never happened. This is called a "rewind" and will cause some trouble if somebody based their own work on the branch already, because their history will still have those revisions. If you instead want to create a new commit that undoes all changes since <rev>, you can do:

git revert <rev>..

This command creates a new commit that undoes all changes done in commits specified. It can't revert a merge. To revert to content of revision before merge and keep history, you could try:

git reset --mixed <rev>
git reset --soft HEAD@{1}
git commit

The first reset will move HEAD and index and the second reset will return HEAD to where it has been one operation ago, so after that point you have index from <rev> and HEAD back where it has been. So you can now commit. The work tree will be unchanged by the operation. You can either git checkout . afterwards, or just make the first reset --hard to get the work tree content from <rev> too.

Jan Hudec
  • 73,652
  • 13
  • 125
  • 172
  • Thanks for informative answer! One more question. When I do git reset --hard git log doesn't show the revisions that r created later than anymore. Can I make them appear again? – jjei Aug 19 '11 at 12:27
  • @jjei: Well, the usual reason to run `git reset --hard` is to declare that those revisions were mistake and get rid of them. However they still live in the reflog (by default that's pruned after some time, the default being IIRC 90 days). You can access the reflog using the `@{...}` ref suffix. Immediately after the reset, it will be in `HEAD@{1}` (which means previous value of `HEAD`), but that will obviously move as you do further operations. But you can also use date+time in the curly brackets and you can use `git reflog` command to see the list. – Jan Hudec Aug 19 '11 at 12:46