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

我一直认为git resetgit checkout是一样的,从这个意义上来说,这两个方法都使项目回到了特定的提交。 不过,我觉得他们不可能完全一样,因为这是多余的。 两者的实际区别是什么? 我有点困惑,因为svn只有svn co才能恢复提交。

添加

下图解释了这种差异,尽pipe可能过于简单或不正确。 你怎么看? 这是错误的还是过于简单?

http://a.imageshack.us/img192/5440/screenshot20100903at416.png

加2

VonC和Charles很好地解释了git resetgit checkout之间的区别。 我目前的理解是, git reset会把所有的变化都还原到一个特定的提交,而git checkout或多或less地为分支做准备。 我发现下面的两个图很好用来达成这个理解:

http://a.imageshack.us/img651/1559/86421927.pnghttp://a.imageshack.us/img801/1986/resetr.png

加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的repourl)

所有这三个工作树修改( svn checkoutupdateswitch )在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本身指向另一个分支。

http://git-scm.comhttp://img.dovov.comreset/reset-checkout.png

以最简单的forms, reset重置索引而不接触工作树,而checkout改变工作树而不接触索引。

重置索引以匹配HEAD ,单独工作的树:

 git reset 

从概念上讲,这将检查出工作树中的索引。 为了让它实际上做任何事你必须使用-f强制它覆盖任何本地更改。 这是一个安全function,以确保“无争论”forms不具有破坏性:

 git checkout 

一旦开始添加参数,确实有一些重叠。

checkout通常与分支,标记或提交一起使用。 在这种情况下,它将重置HEAD和给定提交的索引,并将索引检入到工作树中。

此外,如果您提供 – 难以reset您可以要求reset覆盖工作树,以及重置索引。

如果您当前有一个分支已经签出,那么当您提供另一个分支或提交时, resetcheckout出之间存在着至关重要的差异。 reset将更改当前分支指向选定的提交,而checkout将离开当前的分支,但会检查提供的分支或提交。

其他forms的resetcommit涉及提供path。

如果提供resetpath,则不能提供--hardreset只会将提供的path的索引版本更改为提供的提交中的版本(如果未指定提交,则为HEAD )。

如果你提供了checkoutpath,比如reset ,它将更新所提供path的索引版本以匹配所提交的提交(或HEAD ),但是它总会检查提供的path的索引版本到工作树中。

恢复更改时的一个简单用例:
1.如果要撤消对已修改文件的分段,请使用重置。
2.如果要放弃对未分档文件的更改,请使用checkout。

Atlassian给了我们一个关于git resetgit checkout等的很好的解释, git还原 。 在本文中,解释了这些命令在不同级别上的不同用法 – 文件,分段快照和提交。

https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting

这两个命令(重置和结帐)是完全不同的。

checkout Xreset --hard X

如果X是分支名称,那么checkout X将在reset --hard X时更改当前分支 – reset --hard X不会。