pro*_*eek 415 git git-checkout git-reset
我一直在想,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,checkout和reset可以模拟反叛.
git checkout bar
git reset --hard newbar
git branch -d newbar
Run Code Online (Sandbox Code Playgroud)
Von*_*onC 183
git reset具体是关于更新索引,移动HEAD.git checkout是关于更新工作树(到索引或指定的树).只有在结帐时才会更新HEAD(如果没有,最终会得到一个分离的HEAD).相比之下,因为SVN没有索引,只有一个工作树,git restore将复制在一个单独的目录中指定的修订版本.
更接近于等于git checkout:
svn checkout (如果您在同一分支中,表示相同的SVN URL)git checkout (如果您签比如同一个分支,但是从另一个SVN回购URL)所有这些三个工作树的修改(svn update,svn switch,svn checkout)在Git中只有一个命令:update.
但由于git的也有指数的概念(即"集结地"回购之间和工作树),你也有switch.
例如,如果我们有两个分支,'
git checkout'和'git reset'指向不同的提交,我们当前正在'master'(因此HEAD指向它)并且我们运行develop,'develop'本身现在将指向同一个提交'git reset master'确实.另一方面,如果我们反而跑
develop,'master'将不会移动,git checkout master它本身也会移动.develop现在将指向'HEAD'.因此,在这两种情况下,我们都转向
HEAD指向提交master,但我们如何这样做是非常不同的.HEAD将分支A点移动到,checkout移动reset自己指向另一个分支.

但是,在这些方面,:
然而,这个答案的第一段是误导性的:"
HEAD......只有在你结账时才更新HEAD(如果没有,你最终得到一个分离的HEAD)".
不是这样:HEAD即使你签出一个不是分支的提交,也会更新HEAD(是的,你最终得到了一个分离的HEAD,但它仍然得到了更新).Run Code Online (Sandbox Code Playgroud)git checkout a839e8f updates HEAD to point to commit a839e8f.
@LarsH是正确的.
第二个问题是关于HEAD所处的错误概念,只有在你结账时才会更新HEAD.
HEAD无论你身在何处,都像阴影一样.
检查一些非分支引用(例如,标记)或直接提交将移动HEAD.分离头并不意味着你已经脱离HEAD,这意味着头部与分支ref分离,你可以从中看到,例如git checkout.
- 附属国家将首先
git checkout,- 分离仍将显示
git log --pretty=format:"%d" -1,但不会有箭头到分支参考.
CB *_*ley 66
在最简单的形式中,reset重置索引而不触及工作树,同时checkout更改工作树而不触及索引.
重置索引以匹配HEAD,单独保留工作树:
git reset
Run Code Online (Sandbox Code Playgroud)
从概念上讲,这会将索引检出到工作树中.要让它实际执行任何操作,您必须使用-f它来强制覆盖任何本地更改.这是一个安全功能,以确保"无参数"形式不具有破坏性:
git checkout
Run Code Online (Sandbox Code Playgroud)
一旦开始添加参数,就会发生一些重叠.
checkout通常与分支,标记或提交一起使用.在这种情况下,它将重置HEAD和给定提交的索引以及执行将索引签出到工作树中.
此外,如果您提供--hard给reset您,可以要求reset覆盖工作树以及重置索引.
如果你当前有一个分支签出出之间有一个关键的不同reset而checkout当你提供一个选择分支或提交.reset将当前分支更改为指向所选提交,而checkout将仅保留当前分支,但将检出提供的分支或提交.
其他形式reset和commit涉及供应路径.
如果您提供的路径reset无法提供--hard,reset则只会将提供的路径的索引版本更改为提供的提交中的版本(或者HEAD如果您未指定提交).
如果您提供路径checkout,就像reset它将更新提供的路径的索引版本以匹配提供的提交(或HEAD),但它将始终检查提供的路径的索引版本到工作树.
简而言之,关键区别在于reset 移动当前分支参考,而checkout不是(它移动HEAD).
正如Pro Git的书在重置揭秘中解释的那样,
首先
reset要做的是移动HEAD指向的内容.这与改变HEAD本身不同(这是做什么的checkout);reset移动 HEAD指向的分支.这意味着如果HEAD设置为master分支(即您当前在master分支上),则运行git reset 9e5e6a4将从master指向开始9e5e6a4.[强调补充]
另请参阅VonC的答案,以获取同一篇文章中非常有用的文本和图表摘录,我在此不再赘述.
当然也有什么影响了很多详细信息checkout,并reset可以对索引和工作树,这取决于使用什么参数.两个命令之间可能存在许多相似之处和不同之处.但正如我所看到的,最关键的区别在于它们是否会移动当前分支的尖端.
简短的助记符:
git reset HEAD : index = HEAD
git checkout : file_tree = index
git reset --hard HEAD : file_tree = index = HEAD
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
114631 次 |
| 最近记录: |