I always get confused with this, so here is a reminder test case; let's say we have this bash
script to test git
:
set -x
rm -rf test
mkdir test
cd test
git init
git config user.name test
git config user.email [email protected]
echo 1 > a.txt
echo 1 > b.txt
git add *
git commit -m "initial commit"
echo 2 >> b.txt
git add b.txt
git commit -m "second commit"
echo 3 >> b.txt
At this point, the change is not staged in the cache, so git status
is:
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: b.txt
no changes added to commit (use "git add" and/or "git commit -a")
If from this point, we do git checkout
, the result is this:
$ git checkout HEAD -- b.txt
$ git status
On branch master
nothing to commit, working directory clean
If instead we do git reset
, the result is:
$ git reset HEAD -- b.txt
Unstaged changes after reset:
M b.txt
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: b.txt
no changes added to commit (use "git add" and/or "git commit -a")
So, in this case - if the changes are not staged, git reset
makes no difference, while git checkout
overwrites the changes.
Now, let's say that the last change from the script above is staged/cached, that is to say we also did git add b.txt
at the end.
In this case, git status
at this point is:
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: b.txt
If from this point, we do git checkout
, the result is this:
$ git checkout HEAD -- b.txt
$ git status
On branch master
nothing to commit, working directory clean
If instead we do git reset
, the result is:
$ git reset HEAD -- b.txt
Unstaged changes after reset:
M b.txt
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: b.txt
no changes added to commit (use "git add" and/or "git commit -a")
So, in this case - if the changes are staged, git reset
will basically make staged changes into unstaged changes - while git checkout
will overwrite the changes completely.