“git reset”和“git checkout”有什么区别?

问题描述 投票:390回答:6

我一直认为git resetgit checkout是一样的,因为它们都会将项目带回特定的提交。但是,我觉得它们不可能完全相同,因为这将是多余的。这两者之间的实际差异是什么?我有点困惑,因为svn只有svn co来恢复提交。

ADDED

VonC和Charles解释了git resetgit checkout之间的差异。我目前的理解是,git reset将所有更改恢复为特定提交,而git checkout或多或少准备分支。我发现以下两个图对于理解这些图非常有用:

ADDED 3

http://think-like-a-git.net/sections/rebase-from-the-ground-up/using-git-cherry-pick-to-simulate-git-rebase.html,结账和重置可以模仿rebase。

enter image description here

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

enter image description here

git git-checkout git-reset
6个回答
174
投票
  • git reset专门关于更新索引,移动HEAD。
  • git checkout是关于更新工作树(到索引或指定的树)。只有在你结账时才会更新HEAD(如果没有,你最终会得到一个detached HEAD)。

相比之下,由于svn没有索引,只有一个工作树,svn checkout会将给定的修订复制到一个单独的目录中。 git checkout的等价物越接近:

  • svn update(如果你在同一个分支,意思是相同的SVN URL)
  • svn switch(如果你签出了相同的分支,但来自另一个SVN repo URL)

所有这三个工作树修改(svn checkoutupdateswitch)在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.


63
投票

在最简单的形式中,git log --pretty=format:"%d" -1重置索引而不触及工作树,而(HEAD ->更改工作树而不触及索引。

重置索引以匹配(HEAD,单独留下工作树:

reset

从概念上讲,这会将索引检出到工作树中。要让它实际执行任何操作,您必须使用checkout强制它覆盖任何本地更改。这是一个安全功能,以确保“无参数”形式不具有破坏性:

HEAD

一旦开始添加参数,就会发生一些重叠。

git reset 通常用于分支,标记或提交。在这种情况下,它会将-f和索引重置为给定的提交,并将索引检出到工作树中。

此外,如果您向git checkout 提供checkout,您可以要求HEAD覆盖工作树以及重置索引。

如果您当前有一个分支检出,当您提供替代分支或提交时,--hardreset之间存在重要的差异。 reset将当前分支更改为指向所选提交,而reset将单独保留当前分支,但将检出提供的分支或提交。

其他形式的checkoutreset涉及提供路径。

如果提供checkout的路径,则无法提供resetcommit只会将提供的路径的索引版本更改为提供的提交中的版本(如果未指定提交,则更改为reset)。

如果您提供--hard的路径,例如reset,它将更新所提供路径的索引版本以匹配提供的提交(或HEAD),但它将始终检查提供的路径的索引版本到工作树中。


29
投票

还原更改时的一个简单用例: 1.如果要撤消已修改文件的暂存,请使用reset。 2.如果要放弃对未分段文件的更改,请使用checkout。


9
投票

checkout给我们一个很好的解释git reset,git checkout等等,git revert。在本文中,将解释这些命令在不同级别上的不同用法 - 文件,暂存快照和提交。

reset


8
投票

简而言之,关键区别在于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的回答,我在此不再赘述。

当然,有很多细节可以了解master9e5e6a4对索引和工作树的影响,具体取决于使用的参数。两个命令之间可能存在许多相似之处和不同之处。但正如我所看到的,最关键的区别在于它们是否会移动当前分支的尖端。


1
投票

两个命令(重置和检出)完全不同。

very helpful text and diagram excerpt不是checkout

如果X是分支名称,reset将更改当前分支,而checkout X则不会。

© www.soinside.com 2019 - 2024. All rights reserved.