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
Unlike git reset , git checkout doesn't move any branches around. This is useful for quickly inspecting an old version of your project. However, since there is no branch reference to the current HEAD , this puts you in a detached HEAD state.
So, in short, we can say that “git reset” is a command, whereas “git reset –hard” is its variation that is used when you want to wipe out all the traces of your last commit.
Summary. To review, git reset is a powerful command that is used to undo local changes to the state of a Git repo. Git reset operates on "The Three Trees of Git". These trees are the Commit History ( HEAD ), the Staging Index, and the Working Directory.
The git checkout command lets you navigate between the branches created by git branch . Checking out a branch updates the files in the working directory to match the version stored in that branch, and it tells Git to record all new commits on that branch.
git reset
is specifically about updating the index, moving the HEAD.git checkout
is 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).git restore
, not necessarily git checkout
)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 (svn checkout
, update
, switch
) have only one command in git: git checkout
.
But since git has also the notion of index (that "staging area" between the repo and the working tree), you also have git reset
.
Thinkeye mentions in the comments the article "Reset Demystified ".
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 rungit reset master
, 'develop
' itself will now point to the same commit that 'master
' does.On the other hand, if we instead run
git checkout master
, 'develop
' will not move,HEAD
itself will.HEAD
will now point to 'master
'.So, in both cases we're moving
HEAD
to point to commitA
, but how we do so is very different.reset
will move the branchHEAD
points to, checkout movesHEAD
itself to point to another branch.
On those points, though:
LarsH adds in the comments:
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)".
Not true:git checkout
will 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.
De Novo concurs in the comments:
@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
(HEAD ->
,- detached will still show
(HEAD
, but will not have an arrow to a branch ref.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With