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

大憨熊 提交于 2020-02-26 23:22:47

我一直认为git resetgit checkout相同,从某种意义上来说,这两个都将项目带回到特定的提交。 但是,我觉得它们不可能完全相同,因为那将是多余的。 两者之间的实际区别是什么? 我有点困惑,因为svn只有svn co来还原提交。

添加

VonC和Charles很好地解释了git resetgit 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 


#1楼

Atlassian为我们提供了有关git resetgit checkout等的出色解释,因此git revert 。 在本文中,将解释这些命令在不同级别上的不同用法-文件,暂存快照和提交。

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


#2楼

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

checkout X不会reset --hard X

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


#3楼

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


#4楼

  • git reset专门用于更新索引 ,移动HEAD。
  • git checkout更新工作树 (到索引或指定的树)有关。 仅当您签出分支时,它才会更新HEAD(否则,您将获得一个分离的HEAD )。
    (实际上,在Git 2.23 Q3 2019上,这将是git restore ,而不一定是git checkout

相比之下,由于svn没有索引,只有工作树,因此svn checkout会将给定的修订版本复制到单独的目录中。
git checkout的更接近的等效项是:

  • svn update (如果您位于同一分支中,则意味着相同的SVN URL)
  • svn switch (如果您检出例如同一分支,但来自另一个SVN存储库URL)

所有这三个工作树修改( svn checkoutupdateswitch )在git中只有一个命令: git checkout
但是由于git也具有index的概念(存储库和工作树之间的“临时区域”),因此您也需要git reset


Thinkeye 在评论中提到Reset Demystified ”一词。

例如,如果我们有两个分支,分别指向不同的提交的“ master ”和“ develop ”,而我们当前处于“ develop ”(因此HEAD指向它),并且我们运行git reset master ,则“ develop ”本身现在将指向与“ master ”相同的提交。

另一方面,如果我们改为运行git checkout master ,则' develop '将不会移动,而HEAD本身会移动。 HEAD现在将指向“ master ”。

因此,在两种情况下,我们都将HEAD指向提交A ,但是我们的做法却大不相同。 reset将把分支HEAD指向,结帐将HEAD本身指向另一个分支。

但是,在这些方面:

LarsH 在评论中添加:

但是,此答案的第一段是令人误解的:“ git checkout ...仅当您签出一个分支时才会更新HEAD(否则,您将得到一个分离的HEAD)”。
不正确:即使您检出不是分支的提交, git checkout也会更新HEAD(是的,您最终得到一个分离的HEAD,但它仍得到更新)。

git checkout a839e8f updates HEAD to point to commit a839e8f.

De Novo同意以下意见

@LarsH是正确的。
第二个项目符号对HEAD的含义有误解,只有在签出分支后才会更新HEAD。
HEAD随处可见,就像阴影一样。
检出一些非分支引用(例如,标记)或直接提交,将移动HEAD。 分离的head并不意味着您已经与HEAD分离,这意味着head与分支ref分离了,例如,您可以从git log --pretty=format:"%d" -1看到。

  • 附加的头部状态将以(HEAD ->
  • detached仍将显示(HEAD ,但没有指向分支引用的箭头。

#5楼

以其最简单的形式, reset重置索引而不触动工作树,而checkout更改工作树而不触动索引。

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

git reset

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

git checkout

开始添加参数后,确实存在一些重叠。

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

另外,如果您提供- --hard reset ,则可以要求reset覆盖工作树以及重置索引。

如果您当前有一个已签出的分支,则在提供替代分支或提交时, resetcheckout出之间存在至关重要的区别。 reset将更改当前分支,使其指向选定的提交,而checkout将保留当前分支,但将签出提供的分支或提交。

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

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

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!