“git reset”和“git checkout”有什么区别?
我一直认为git reset和git checkout是一样的,因为它们都将项目带回特定的提交。 但是,我觉得他们不可能完全一样,因为这是多余的。 两者的实际区别是什么? 我有点困惑,因为svn只有svn co才能恢复提交。
添加
下图解释了这种差异,尽管可能过于简单或不正确。 你怎么看? 这是错误还是过于简单?

加2
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,结帐和重置可以模拟基地。

git checkout bar
git reset --hard newbar
git branch -d newbar

git reset是专门关于更新索引 ,移动HEAD的。 git checkout是关于更新工作树 (索引或指定的树)。 它只会在您检出一个分支时才会更新HEAD(如果没有,最终会出现分离的HEAD)。 相比之下,由于svn没有索引,只有一个工作树, svn checkout会将一个给定的修订版复制到一个单独的目录中。
对于git checkout来说,更接近等效的是:
svn update (如果你在同一个分支,意味着相同的SVN URL) svn switch (如果您检出实例相同的分支,但来自另一个SVN repo URL) 所有这三个工作树修改( svn checkout , update , switch )在git: git checkout只有一个命令。
但是因为git也有索引的概念(即回购和工作树之间的“暂存区域”),所以你也有git reset 。
Thinkeye在评论中提到了文章“重新揭秘”。
例如,如果我们有两个分支,' master '和' develop '指向不同的提交,并且我们目前处于' develop '(所以HEAD指向它),我们运行git reset master ,' develop '本身现在会指向“ master ”所做的相同的提交。
另一方面,如果我们运行git checkout master ,' develop '将不会移动, HEAD本身会运行。 HEAD现在将指向' master '。
所以,在这两种情况下,我们都将HEAD指向提交A ,但我们的做法是完全不同的。 reset将移动分支HEAD点,结帐移动HEAD本身指向另一个分支。

以最简单的形式, reset重置索引而不触摸工作树,而checkout更改工作树而不会触摸索引。
重置索引以匹配HEAD ,单独留下工作树:
git reset
从概念上讲,这将检查出工作树中的索引。 为了让它实际上做任何你不得不使用-f强制它覆盖任何本地更改。 这是一个安全功能,以确保“无争论”形式不具有破坏性:
git checkout
一旦开始添加参数,确实存在一些重叠。
checkout通常与分支,标记或提交一起使用。 在这种情况下,它将重置HEAD和给定提交的索引,并将索引检入到工作树中。
此外,如果您对供应--hard来reset你可以问reset覆盖工作树以及重置索引。
如果你当前有一个分支被checkout当你提供另一个分支或提交时,在reset和checkout之间有一个重要的区别。 reset会将当前分支更改为指向所选提交,而checkout将仅保留当前分支,但会检出提供的分支或提交。
其他形式的reset和commit涉及提供路径。
如果提供reset路径,则不能提供--hard和reset只会将提供的路径的索引版本更改为提供的提交中的版本(如果未指定提交,则为HEAD )。
如果您提供checkout路径(如reset ,它将更新所提供路径的索引版本以匹配提供的提交(或HEAD ),但它始终会将提供的路径的索引版本检出到工作树中。
恢复更改时的一个简单用例:
1.如果要撤消对已修改文件的分段,请使用重置。
2.如果您想放弃对非挂起文件的更改,请使用checkout。
上一篇: What's the difference between "git reset" and "git checkout"?
