我一直认为git reset
和git checkout
是一样的,因为它们都会将项目带回特定的提交。但是,我觉得它们不可能完全相同,因为这将是多余的。这两者之间的实际差异是什么?我有点困惑,因为svn只有svn co
来恢复提交。
VonC和Charles解释了git reset
和git checkout
之间的差异。我目前的理解是,git reset
将所有更改恢复为特定提交,而git checkout
或多或少准备分支。我发现以下两个图对于理解这些图非常有用:
从http://think-like-a-git.net/sections/rebase-from-the-ground-up/using-git-cherry-pick-to-simulate-git-rebase.html,结账和重置可以模仿rebase。
git checkout bar
git reset --hard newbar
git branch -d newbar
git reset
专门关于更新索引,移动HEAD。git checkout
是关于更新工作树(到索引或指定的树)。只有在你结账时才会更新HEAD(如果没有,你最终会得到一个detached HEAD)。相比之下,由于svn没有索引,只有一个工作树,svn checkout
会将给定的修订复制到一个单独的目录中。
git checkout
的等价物越接近:
svn update
(如果你在同一个分支,意思是相同的SVN URL)svn switch
(如果你签出了相同的分支,但来自另一个SVN repo URL)所有这三个工作树修改(svn checkout
,update
,switch
)在git中只有一个命令:git checkout
。
但是由于git也有索引的概念(在repo和工作树之间的“staging area”),你也有git reset
。
Thinkeye提到in the comments文章“Reset Demystified ”。
例如,如果我们有两个分支,'
master
'和'develop
'指向不同的提交,我们目前正在'develop
'(所以HEAD指向它)我们运行git reset master
,'develop
'本身现在指向与'master
'相同的提交。另一方面,如果我们改为运行qazxsw poi,'qazxsw poi'将不会移动,qazxsw poi本身会。
git checkout master
现在将指向'develop
'。因此,在这两种情况下,我们都将
HEAD
移动到指向提交HEAD
,但我们如何这样做是非常不同的。master
将分支HEAD
点移动,结账移动A
本身指向另一个分支。
但是,在这些方面,:
reset
添加HEAD
:
然而,这个答案的第一段是误导性的:“
HEAD
......只有在你结账时才更新HEAD(如果没有,你最终得到一个独立的HEAD)”。 不正确:LarsH将更新HEAD,即使你签出一个不是分支的提交(是的,你最终得到了一个分离的HEAD,但它仍然得到了更新)。in the comments
git checkout
比赛git checkout
:
@LarsH是正确的。 第二个问题是关于HEAD所处的错误概念,只有在你结账时才会更新HEAD。 HEAD无论你身在何处,都像阴影一样。 检查一些非分支引用(例如,标记)或直接提交将移动HEAD。分离的头部并不意味着你已经脱离HEAD,这意味着头部与分支ref分离,你可以从中看到它,例如
git checkout a839e8f updates HEAD to point to commit a839e8f.
。
- 附属国家将从De Novo开始,
- 分离仍将显示in the comments,但不会有箭头到分支参考。
在最简单的形式中,git log --pretty=format:"%d" -1
重置索引而不触及工作树,而(HEAD ->
更改工作树而不触及索引。
重置索引以匹配(HEAD
,单独留下工作树:
reset
从概念上讲,这会将索引检出到工作树中。要让它实际执行任何操作,您必须使用checkout
强制它覆盖任何本地更改。这是一个安全功能,以确保“无参数”形式不具有破坏性:
HEAD
一旦开始添加参数,就会发生一些重叠。
git reset
通常用于分支,标记或提交。在这种情况下,它会将-f
和索引重置为给定的提交,并将索引检出到工作树中。
此外,如果您向git checkout
提供checkout
,您可以要求HEAD
覆盖工作树以及重置索引。
如果您当前有一个分支检出,当您提供替代分支或提交时,--hard
和reset
之间存在重要的差异。 reset
将当前分支更改为指向所选提交,而reset
将单独保留当前分支,但将检出提供的分支或提交。
其他形式的checkout
和reset
涉及提供路径。
如果提供checkout
的路径,则无法提供reset
,commit
只会将提供的路径的索引版本更改为提供的提交中的版本(如果未指定提交,则更改为reset
)。
如果您提供--hard
的路径,例如reset
,它将更新所提供路径的索引版本以匹配提供的提交(或HEAD
),但它将始终检查提供的路径的索引版本到工作树中。
还原更改时的一个简单用例: 1.如果要撤消已修改文件的暂存,请使用reset。 2.如果要放弃对未分段文件的更改,请使用checkout。
checkout
给我们一个很好的解释git reset,git checkout等等,git revert。在本文中,将解释这些命令在不同级别上的不同用法 - 文件,暂存快照和提交。
reset
简而言之,关键区别在于HEAD
移动当前分支参考,而Atlassian则不移动(它移动HEAD)。
正如Pro Git书籍在https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting下解释的那样,
reset
将做的第一件事是移动HEAD指向的东西。这与改变HEAD本身不同(这是checkout
所做的); Reset Demystified移动HEAD指向的分支。这意味着如果将HEAD设置为reset
分支(即您目前在checkout
分支上),运行reset
将首先使master
指向master
。 [强调补充]
另请参阅VonC对同一篇文章中git reset 9e5e6a4
的回答,我在此不再赘述。
当然,有很多细节可以了解master
和9e5e6a4
对索引和工作树的影响,具体取决于使用的参数。两个命令之间可能存在许多相似之处和不同之处。但正如我所看到的,最关键的区别在于它们是否会移动当前分支的尖端。
两个命令(重置和检出)完全不同。
very helpful text and diagram excerpt不是checkout
如果X是分支名称,reset
将更改当前分支,而checkout X
则不会。