“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"?