我一直认为 git reset
和 git checkout
是一样的,从某种意义上说,它们都会将项目恢复到特定的提交。但是,我觉得它们不能完全相同,因为那会是多余的。两者之间的实际区别是什么?我有点困惑,因为 svn 只有 svn co
来恢复提交。
已添加
VonC 和 Charles 很好地解释了 git reset
和 git checkout
之间的区别。我目前的理解是 git reset
将所有更改恢复到特定提交,而 git checkout
或多或少地为分支做准备。我发现以下两个图表对于理解这一点非常有用:
添加了 3
来自 http://think-like-a-git.net/sections/rebase-from-the-ground-up/using-git-cherry-pick-to-simulate-git-rebase.html , checkout 和 reset 可以模拟 rebase。
git checkout bar
git reset --hard newbar
git branch -d newbar
最佳答案
-
git reset
特别是关于更新索引,移动 HEAD。 -
git checkout
是关于更新工作树(到索引或指定的树)。只有当你 check out 一个分支时它才会更新 HEAD(如果没有,你最终得到一个 detached HEAD )。
(实际上,对于 Git 2.23 Q3 2019,这将是git restore
,不一定git checkout
)
相比之下,由于svn没有索引,只有一个工作树,svn checkout
将在单独的目录中复制给定的修订版。
git checkout
更接近的等价物是:
-
svn update
(如果你在同一个分支,意思是同一个SVN URL) -
svn switch
(例如,如果您从同一个分支 checkout ,但来自另一个 SVN 存储库 URL)
所有这三个工作树修改(svn checkout
、update
、switch
)在 git 中只有一个命令:git checkout
。
但是由于 git 也有索引的概念(repo 和工作树之间的“暂存区”),你也有 git reset
。
Thinkeye提及 in the comments文章“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.
不过,在这些方面:
LarsH添加 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.
@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.
关于git - "git reset"和 "git checkout"有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3639342/