Posted By: Anonymous
I’ve always thought of
git reset and
git checkout as the same, in the sense that both bring the project back to a specific commit. However, I feel they can’t be exactly the same, as that would be redundant. What is the actual difference between the two? I’m a bit confused, as the svn only has
svn co to revert the commit.
VonC and Charles explained the differences between
git reset and
git checkout really well. My current understanding is that
git reset reverts all of the changes back to a specific commit, whereas
git checkout more or less prepares for a branch. I found the following two diagrams quite useful in coming to this understanding:
From http://think-like-a-git.net/sections/rebase-from-the-ground-up/using-git-cherry-pick-to-simulate-git-rebase.html, checkout and reset can emulate the rebase.
git checkout bar git reset --hard newbar git branch -d newbar
git resetis specifically about updating the index, moving the HEAD.
git checkoutis about updating the working tree (to the index or the specified tree). It will update the HEAD only if you checkout a branch (if not, you end up with a detached HEAD).
(actually, with Git 2.23 Q3 2019, this will be
git restore, not necessarily
By comparison, since svn has no index, only a working tree,
svn checkout will copy a given revision on a separate directory.
The closer equivalent for
git checkout would:
svn update(if you are in the same branch, meaning the same SVN URL)
svn switch(if you checkout for instance the same branch, but from another SVN repo URL)
All those three working tree modifications (
switch) have only one command in git:
But since git has also the notion of index (that “staging area” between the repo and the working tree), you also have
For instance, if we have two branches, ‘
master‘ and ‘
develop‘ pointing at different commits, and we’re currently on ‘
develop‘ (so HEAD points to it) and we run
git reset master, ‘
develop‘ itself will now point to the same commit that ‘
On the other hand, if we instead run
git checkout master, ‘
develop‘ will not move,
HEADwill now point to ‘
So, in both cases we’re moving
HEADto point to commit
A, but how we do so is very different.
resetwill move the branch
HEADpoints to, checkout moves
HEADitself to point to another branch.
On those points, though:
The first paragraph of this answer, though, is misleading: “
git checkout… will update the HEAD only if you checkout a branch (if not, you end up with a detached HEAD)”.
git checkoutwill update the HEAD even if you checkout a commit that’s not a branch (and yes, you end up with a detached HEAD, but it still got updated).
git checkout a839e8f updates HEAD to point to commit a839e8f.
@LarsH is correct.
The second bullet has a misconception about what HEAD is in will update the HEAD only if you checkout a branch.
HEAD goes wherever you are, like a shadow.
Checking out some non-branch ref (e.g., a tag), or a commit directly, will move HEAD. Detached head doesn’t mean you’ve detached from the HEAD, it means the head is detached from a branch ref, which you can see from, e.g.,
git log --pretty=format:"%d" -1.
- Attached head states will start with
- detached will still show
(HEAD, but will not have an arrow to a branch ref.