代码之家  ›  专栏  ›  技术社区  ›  prosseek

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

  •  386
  • prosseek  · 技术社区  · 14 年前

    我一直认为 git reset git checkout 是相同的,从这个意义上说,这两者都会使项目返回到特定的提交。但是,我觉得它们不能完全相同,因为这是多余的。这两者的实际区别是什么?我有点困惑,因为SVN只有 svn co 来恢复提交。

    加入

    VONC和Charles解释了 git reset git checkout really well之间的区别。我目前的理解是, git reset 将所有更改还原回特定的提交,而 git checkout more or less prepares for a branch.我发现以下两个图表对于理解这一点非常有用:

    增加3个

    http://think-like-a-git.net/sections/rebase-from-ground-up/using-git cherry pick to simute git rebase.html.>

    git checkout bar
    Git重置--硬新手
    Git分行-D Newbar
    < /代码> 
    
    

    .svn co恢复提交。

    补充

    VONC和查尔斯解释了Git复位GIT校验真的很好。我目前的理解是Git复位将所有更改恢复为特定的提交,而GIT校验或多或少地为一个分支做准备。我发现以下两个图表对于理解这一点非常有用:

    http://a.imageshack.us/img651/1559/86421927.png http://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,签出和重置可以模拟钢筋。

    enter image description here

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

    6 回复  |  直到 5 年前
        1
  •  171
  •   VonC    5 年前

    相比之下,由于SVN没有索引,只有一个工作目录树, svn checkout >a>will copy a given revision on a separate directory.
    更接近于 git checkout的等价物 would:。

    所有这三个工作树修改( svn checkout , update , switch )在git中只有一个命令: git checkout
    但是,由于Git还具有索引的概念(repo和工作树之间的“临时区域”),因此您还具有 Git reset


    thinkeye 提及 in the comments. the article” Reset demystalized.>A>”。

    < Buff行情>

    例如,如果我们有两个分支,“ master”(指向不同的提交),并且我们当前处于“ develop”(因此head points to it)状态,并且我们运行 git reset master. ,' develop. '本身现在将指向相同的提交,即“ master. ”执行。

    另一方面,如果我们改为运行 git checkout master, ,' develop 'will not move, head self will. head will now point to' master '。

    因此,在这两种情况下,我们都在移动 head to point to commit a ,但是我们这样做的方式是非常不同的。 reset will move the branch head points to,checkout moves head itself to point to another branch.

    < /块引用>

    但在这些方面:

    larsh adds 在注释中

    < Buff行情>

    然而,这个答案的第一段误导了我们:“ git checkout 。只有当您签出分支时才会更新头(如果没有,则以分离的头结束)。
    不正确: git checkout will update the head even if you checkout a commit that's not a branch(and yes,you end up with a detached head,but it still got updated).

    git checkout a839e8f updates head to point to commit a839e8f.
    < /代码> 
    < /块引用>
    
    

    de novoconcurs在comments中

    < Buff行情>

    @Larsh是正确的。
    第二个项目符号对head的概念有误,只有当您签出分支时,head才会更新。
    头可以走到任何地方,就像影子一样。
    签出一些非分支引用(例如标记)或直接提交将移动head。分离的头并不意味着你已经从头上分离了,它意味着头是从分支引用分离的,你可以从中看到,例如,g it log--pretty=format:%d“-1.

    • 附加头状态将以(head->,)开始。
    • 已分离仍将显示(head,但不会有指向分支引用的箭头。
    < /块引用>
    特别是关于更新索引,移动头部。
  • git checkout是关于更新工作树(指向索引或指定的树)。只有当你签出一个分支时,它才会更新头部(如果没有,你最后会得到一个detached HEAD)
  • 相比之下,由于SVN没有索引,只有一个工作树,svn checkout将在单独的目录中复制给定的修订。
    更接近于GIT校验威尔:

    • svn update(如果您在同一个分支中,则表示相同的SVN URL)
    • svn switch(例如,如果您签出同一个分支,但来自另一个SVN repo url)

    所有这三个工作树修改(向量空间检验,update,switch)在git中只有一个命令:GIT校验.
    但是,由于Git还具有索引(repo和工作树之间的“临时区域”)的概念,因此您还可以Git复位.


    Thinkeye提到in the comments文章“Reset Demystified “。

    例如,如果我们有两个分支,master“和”develop'指向不同的提交,我们当前正在'发展(所以头指向它)然后我们跑git reset master, '发展'本身现在将指向相同的提交'主人“是的。

    另一方面,如果我们改为跑git checkout master, '发展“不会移动,HEAD它自己会。现在将指向'主人'.

    所以,在这两种情况下,我们都在移动指向提交A但我们的做法却大相径庭。reset将移动分支指向,签出移动指向另一个分支。

    http://git-scm.com/images/reset/reset-checkout.png

    但在这些方面:

    LarsH添加in the comments:

    不过,这个答案的第一段是误导性的:“GIT校验…只有当您签出一个分支时才会更新头部(如果没有,则以一个分离的头部结束)”。
    不是真的:GIT校验即使签出一个不是分支的提交,也会更新头部(是的,最终会得到一个分离的头部,但它仍然会得到更新)。

    git checkout a839e8f updates HEAD to point to commit a839e8f.
    

    De Novo同意in the comments:

    @拉什是对的。
    第二个项目符号对head的概念有误,只有当您签出一个分支时,head才会更新。
    头走到哪里,就像影子。
    签出一些非分支引用(例如标记)或直接提交将移动head。分离的头部并不意味着你已经从头部分离,它意味着头部已经从分支引用中分离,你可以从中看到,例如,git log --pretty=format:"%d" -1.

    • 附加的头部状态将从(HEAD ->,
    • 分离后仍会显示(HEAD,但没有指向分支引用的箭头。
        2
  •  61
  •   thSoft    10 年前

    以最简单的形式, reset 重置索引而不接触工作树,同时 checkout 在不接触索引的情况下更改工作树。

    将索引重置为匹配 HEAD ,工作树独立:

    git reset
    

    从概念上讲,这会将索引签出到工作树中。为了让它真正做任何你必须使用的事情 -f 强制它覆盖任何本地更改。这是一个安全特性,以确保“无参数”窗体不具有破坏性:

    git checkout
    

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

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

    另外,如果你提供 --hard 重置 你可以问 重置 覆盖工作树并重置索引。

    如果你现在有一个分支被签出了,那么 重置 结帐 当您提供另一个分支或提交时。 重置 将当前分支更改为指向选定的提交,而 结帐 将只保留当前分支,但将签出提供的分支或提交。

    其他形式 重置 commit 包括提供途径。

    如果您提供 重置 你不能供应 --硬 重置 只将所提供路径的索引版本更改为所提供提交中的版本(或 如果不指定提交)。

    如果您提供 结帐 ,像 重置 它将更新所提供路径的索引版本以匹配所提供的提交(或 )但它总是将所提供路径的索引版本签出到工作树中。

        3
  •  26
  •   John Doe    9 年前

    恢复更改时的一个简单用例:
    1。如果要撤消修改文件的暂存,请使用reset。
    2。如果要放弃对未分页文件的更改,请使用签出。

        4
  •  9
  •   Rochadsouza    9 年前

    Atlassian 给我们一个很好的解释 Git复位 , GIT校验 所以, GIT回复 . 在本文中,我们将解释这些命令在不同级别上的不同用法—文件、阶段快照和提交。

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

        5
  •  8
  •   LarsH    6 年前

    简而言之,关键的区别在于 reset 移动当前分支引用 ,同时 checkout 不会(它会移动头部)。

    正如专业图书解释 Reset Demystified ,

    第一件事 重置 将要做的是 移动头部指向 . 这不是 一样 改变头部本身 (这是什么? 结帐 确实); 重置 移动分支 那个头指向。这意味着如果设置了头部 到 master 分支机构(即您目前在 主人 分支机构) 运行 git reset 9e5e6a4 将从 主人 指向 9e5e6a4 . [添加强调]

    另请参见VONC的回答 very helpful text and diagram excerpt 来自同一篇文章,我不会在这里重复。

    当然,还有很多关于什么影响的细节 结帐 重置 可以对索引和工作树进行设置,具体取决于使用的参数。这两个命令之间可能有很多相似之处和不同之处。但正如我所见,最关键的区别是它们是否移动了当前分支的尖端。

        6
  •  1
  •   Mo.    9 年前

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

    checkout X 不是 reset --hard X

    如果x是分支名称, 检验X 将更改当前分支 虽然 重置-硬X 不会。