2

If I commit and then make changes to a file foo, I can undo these changes by git checkout foo. If I make changes to foo AND add them with git add foo, then git checkout foo doesn't do anything (and doesn't say anything)

What is the reasoning behind this?

Bananach
  • 1,419
  • 13
  • 34
  • I think that if a file is already saved in a commit you are supposed to checkout the commit. – lilezek Sep 20 '17 at 15:29
  • The answers you have now are correct, but the key insight here is that there are not one, not two, but *three* active versions of any one file at all times: one in the current or `HEAD` commit, one in the index, and one in the work-tree. `git checkout` copies *to* the work-tree, but it can copy *from* either of the other two, or in fact from any other commit as well. There's one more oddity: copying *from* any commit at all (`HEAD` or not) writes to *both* the index *and* the work-tree, replacing *both* versions. The *why* answer to this is mostly "because that was easy to implement." – torek Sep 20 '17 at 17:28

3 Answers3

3

When you say

git checkout foo

without additional arguments, you're telling git to replace the foo in your worktree with the foo in your index. So if you've added (i.e. staged, i.e. updated the index with) all the changes to foo, then of course there's nothing for this checkout command to do.

The normal procedure to back out the change would be to first reset (update the index from the HEAD commit) and then use checkout to update the working version.

Then again, you can use checkout to get the version of foo from the previous commit

git checkout HEAD foo

This works just as well; the two-step approach is probably just a bit more widely known since it uses commands suggested by git status for un-staging and un-doing changes.

Mark Adelsberger
  • 32,904
  • 2
  • 24
  • 41
  • I'm confused that you say the normal procedure is two steps when checkout actually can do what I want in one step. What is the disadvantage of the checkout solution then? – Bananach Sep 20 '17 at 16:37
  • There is no disadvantage. It's just that the git UI happens to recommend commands that each only do one of the two steps, so out of habit even when I need to do both I (and I think many users) tend to use the two-command approach. Clarified this point a bit. – Mark Adelsberger Sep 20 '17 at 18:49
0

Because you can unstage it and then check it out :)

git reset <file>

git checkout <file>

The reason behind not checking them out as well is because if you change your files locally and then want to update to the master branch in example, your work and staged files should be overridden.

Spitzbueb
  • 3,636
  • 1
  • 17
  • 34
0

With Git 2.23 (August 2019), you now can avoid using the confusing git checkout command (which deals with files or branches), and the new (still experimental) git restore command.

You can restore both the index and the working tree (this the same as using git-checkout)

git restore --source=HEAD --staged --worktree hello.c

or the short form which is more practical but less readable:

git restore -s@ -SW hello.c

That will restore both working tree and staging area (cache).

VonC
  • 1,042,979
  • 435
  • 3,649
  • 4,283