3

I am exploring the possible options to undo something that has been done with git. I came across this post and I see that there are 3 options git reset, git checkout and git restore.

I think I sort of understand what git reset does (not entirely but I think that's a separate question), however I don't understand what difference is there in running git checkout -- some_file and git restore --staged some_file

Is there a difference in how the two commands change the files in the working directory?

torek
  • 448,244
  • 59
  • 642
  • 775
djvaroli
  • 1,223
  • 1
  • 11
  • 28
  • 1
    Does this answer your question? [What is the \`git restore\` command and what is the difference between \`git restore\` and \`git reset\`?](https://stackoverflow.com/questions/58003030/what-is-the-git-restore-command-and-what-is-the-difference-between-git-restor) – matt Mar 03 '21 at 23:01
  • That's a very useful link and I am going to take a more in-depth look, but it doesn't really explain how git checkout is different from those. – djvaroli Mar 03 '21 at 23:05
  • 1
    @djvaroli: it does (explain the difference), especially if you read [my answer](https://stackoverflow.com/a/66309040/1256452). It is rather long but I think it's worth reading. – torek Mar 04 '21 at 02:33

1 Answers1

5

To summarize Torek's answer:

Torek insists on the fact git restore --source <aCommit> --worktree -- somefile is new (cannot be done with checkout): the ability to restore a file in the working tree without touching the index.


Darren Ng adds in the comments:

Now I can discard staged changes with a single git restore --staged --worktree -- FILE, instead of 2-step git restore --staged FILE+git checkout FILE.

True, but Git 2.41 (Q2 2023) makes it clear that not all options are supported when using both --staged --worktree.

While "git restore"(man) supports options like --ours that are only meaningful during a conflicted merge, but these options are only meaningful when updating the working tree files.
These options are marked to be incompatible when both "--staged" and "--worktree" are in effect.

See commit ee8a888 (26 Feb 2023) by Andy Koppe (akoppe).
(Merged by Junio C Hamano -- gitster -- in commit 67076b8, 19 Mar 2023)

restore: fault --staged --worktree with merge opts

Signed-off-by: Andy Koppe

The 'restore' command already rejects the --merge, --conflict, --ours and --theirs options when combined with --staged, but accepts them when --worktree is added as well.

Unfortunately that doesn't appear to do anything useful.
The --ours and --theirs options seem to be ignored when both --staged and --worktree are given, whereas with --merge or --conflict, the command has the same effect as if the --staged option wasn't present.

So reject those options with '--staged --worktree' as well, using opts->accept_ref to distinguish restore from checkout.

Add test for both '--staged' and '--staged --worktree'.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 1
    Didn't know about `--worktree`. Now I can discard staged changes with a single `git restore --staged --worktree FILE`, instead of 2-step `git restore --staged FILE`+`git checkout FILE`. +1 for that! – Darren Ng Aug 06 '21 at 10:42
  • 2
    @DarrenNg Exactly. The `git checkout` command should not be needed much anymore. Short version: `git restore -SW -- aFile` – VonC Aug 06 '21 at 12:35
  • 1
    hooray short ver! – Darren Ng Aug 06 '21 at 16:23