git - "git reset"和 "git checkout"有什么区别?

标签 git git-checkout git-reset

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

已添加

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

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 , checkout 和 reset 可以模拟 rebase。

enter image description here

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

enter image description here

最佳答案

  • git reset特别是关于更新索引,移动 HEAD。
  • git checkout是关于更新工作树(到索引或指定的树)。只有当你 check out 一个分支时它才会更新 HEAD(如果没有,你最终得到一个 detached HEAD )。
    (实际上,对于 Git 2.23 Q3 2019,这将是 git restore ,不一定 git checkout)

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

  • svn update (如果你在同一个分支,意思是同一个SVN URL)
  • svn switch (例如,如果您从同一个分支 checkout ,但来自另一个 SVN 存储库 URL)

所有这三个工作树修改(svn checkoutupdateswitch)在 git 中只有一个命令:git checkout
但是由于 git 也有索引的概念(repo 和工作树之间的“暂存区”),你也有 git reset


Thinkeye提及 in the comments文章“Reset Demystified ”。

For instance, if we have two branches, 'master' and 'develop' pointing at different commits, and we're currently on 'develop' (so HEAD points to it) and we run git reset master, 'develop' itself will now point to the same commit that 'master' does.

On the other hand, if we instead run git checkout master, 'develop' will not move, HEAD itself will. HEAD will now point to 'master'.

So, in both cases we're moving HEAD to point to commit A, but how we do so is very different. reset will move the branch HEAD points to, checkout moves HEAD itself to point to another branch.

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

不过,在这些方面:

LarsH添加 in the comments :

The first paragraph of this answer, though, is misleading: "git checkout ... will update the HEAD only if you checkout a branch (if not, you end up with a detached HEAD)".
Not true: 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 Novo同意in the comments :

@LarsH is correct.
The second bullet has a misconception about what HEAD is in will update the HEAD only if you checkout a branch.
HEAD goes wherever you are, like a shadow.
Checking out some non-branch ref (e.g., a tag), or a commit directly, will move HEAD. Detached head doesn't mean you've detached from the HEAD, it means the head is detached from a branch ref, which you can see from, e.g., git log --pretty=format:"%d" -1.

  • Attached head states will start with (HEAD ->,
  • detached will still show (HEAD, but will not have an arrow to a branch ref.

关于git - "git reset"和 "git checkout"有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3639342/

相关文章:

c++ - 如何从驻留在其他 git 存储库中的插件访问应用程序中定义的 interfaces.h?

git - 为什么 `git checkout <branch> <file>` 会进行更改?

使用 libgit2 checkout 分支

git - git reset HEAD^ --hard 是否删除所有内容?

Git Merge 仅更改特定提交中的文件(而不是整个差异)

windows - windows下如何创建md文件

Git:您如何检查所有已删除的文件?

git add + git reset 硬删除工作副本文件 - 撤消?

git - 撤消 Git 中已推送到远程仓库的特定提交

如果本地存储库没有 --global , git config insteadOf 就无法工作