What is the difference in the actual effect of the following two commands? Don't they both make the staging area and the working directory to match the latest commit?
git reset --hard
git checkout <sha-of-latest-commit>
What is the difference in the actual effect of the following two commands? Don't they both make the staging area and the working directory to match the latest commit?
git reset --hard
git checkout <sha-of-latest-commit>
git reset --hard
discards all changes to files in worktree.
git checkout <sha-of-latest-commit>
preserves those changes.
There is another difference in case when your HEAD references a branch (NOT a detached HEAD mode).
git checkout <sha-of-latest-commit>
will detach HEAD.
git reset --hard
will not detach HEAD.
git reset --hard
is equivalent to git reset --hard HEAD
, i.e. it makes your branch point to HEAD (i.e. a NOP) and also resets both the index and the working tree to the same content.
git checkout
with a literal sha1 will enter detached-head-mode, i.e. you will be no longer on your branch. It also does not change working tree or index.
See for yourself:
$ git init
$ touch a b
$ git add .
$ git commit -m 1
$ echo 1 >a; echo 1 >b; git add a #do some changes
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: a
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
$ git reset --hard
$ git status # still on master, changes are gone
On branch master
nothing to commit, working directory clean
$ echo 1 >a; echo 1 >b; git add a #redo changes
$ git checkout HEAD@{0}
$ git status #no longer on master, changes are still there
HEAD detached at be924ba
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: a
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