git 中的 HEAD 是啥?

Posted

技术标签:

【中文标题】git 中的 HEAD 是啥?【英文标题】:What is the HEAD in git?git 中的 HEAD 是什么? 【发布时间】:2011-02-01 13:34:20 【问题描述】:

上次提交、HEAD 和我在目录中可以看到的文件状态之间似乎存在差异。

什么是 HEAD,我可以用它做什么,应该避免什么错误?

【问题讨论】:

另见***.com/questions/964876/head-and-orig-head-in-git/… 从 Git v1.8.4 开始,下面所有使用 HEADhead 的答案现在都可以使用 @ 代替 HEAD。请参阅 this answer (last section) 了解您为什么可以这样做。 From git-scm :Git 中的 HEAD 是指向当前分支引用的指针,它又是指向您所做的最后一次提交或检出到工作目录的最后一次提交的指针。这也意味着它将成为您下一次提交的父级。通常将其视为 HEAD 是您上次提交的快照是最简单的。 What is HEAD in Git?的可能重复 【参考方案1】:

HEAD 是对当前签出分支中最后一次提交的引用。


对此有一个小例外,即分离的 HEAD。 分离的 HEAD 是您在签出 commit(或标签)而不是分支时最终遇到的情况。在这种情况下,你必须把它想象成一个没有名字的临时分支;所以我们只有有 HEAD,而不是有一个命名的分支引用。它仍然允许您进行提交(这将更新 HEAD),因此如果您将分离的 HEAD 视为没有名称的临时分支,上述简短定义仍然适用。

【讨论】:

那为什么可以有两个头呢? @e-satis:有时你会看到被称为头的分支——它们存储在refs/heads。不过,小写头部与HEAD 不同。我的回答稍微澄清了这一点。 @e-satis:这不是正则表达式。 ^ 只是 git 对“之前的提交”的表示法——这是当前提交之前的提交。 (如果当前是合并,则使用第一个父级。) @e-satis:有关指定提交的所有方法的更多信息,请参阅 git-rev-list 手册页的指定修订部分 - 这只是一小部分。 kernel.org/pub/software/scm/git/docs/… @LarsH 分支只是指向提交的指针,这使得该提交及其所有父级包含在该分支上。但是提交中没有将它们链接到 分支的任何内容。该链接仅在反向中存在。因此,当您检查一个提交时,您无法判断您可能指的是哪个分支——它可能是一个分支,也可能是所有分支,甚至没有。【参考方案2】:

HEAD 是对当前签出提交的 ref(引用)。

在正常状态下,它实际上是您签出的分支的符号引用 - 如果您查看 .git/HEAD 的内容,您会看到类似“ref: refs/heads/master”的内容。分支本身是对分支顶端提交的引用。因此,在正常状态下,HEAD实际上是指当前分支顶端的提交。

也可以有一个“分离的 HEAD”。当您检出(本地)分支以外的内容时,会发生这种情况,例如远程分支、特定提交或标记。最常见的情况是在交互式 rebase 期间,当您选择编辑提交时。在分离的 HEAD 状态下,您的 HEAD 是对提交的直接引用 - .git/HEAD 的内容将是 SHA1 哈希。

一般来说,HEAD 只是一个方便的名称,意思是“您检查过的内容”,您不必太担心。请注意您已签出的内容,并记住如果您不在分支上(分离的 HEAD 状态),您可能不想提交,除非您知道自己在做什么(例如在交互式变基中) .

【讨论】:

这是我不明白的。如果您签出远程分支,为什么最终会出现“分离的 HEAD”。为什么不自动跳转到与远程对应的本地仓库中的分支? @e-satis:如果您想要本地分支,请查看本地分支。请记住,两者不一定相同 - 您必须告诉本地的合并远程的(或拉)。跟踪只是为了知道当您询问时自动拉出哪一个。它分离的原因是远程分支旨在成为指向远程仓库中分支的最后一次看到位置的指针。如果你尝试提交它,远程仓库不会改变,所以远程分支也不应该改变。 好的,这就是我没有得到的:以某种方式命名的本地分支并不意味着它与远程分支相同。一开始真的很难,因为我来自 SVN 背景 :-) 谢谢伙计。顺便说一句,您如何将无头 HEAD 移动到本地分支以在此处提交? @e-satis:一般答案是git rebase <branch> HEAD。这将找到<branch>HEAD 的最后一个共同祖先,然后将所有提交从那里带到HEAD 并将它们应用(重新定位它们)到<branch>。它本质上是通过将它们作为补丁应用来做到这一点的,因此如果两个分支确实不同,则可能存在冲突。但是如果<branch>HEAD 的祖先(即你在正确的地方,只是忘记你已经分离了HEAD),那么rebase 只是一个快进合并。 这是我看到的对git HEAD最清晰准确的描述之一,搜索了一段时间。【参考方案3】:

我一直认为HEAD~5 的意思是转到 5 次之前的提交。但它不携带命令的 GO 部分。它只带有命令的reference部分。

您可以对该参考执行的操作因您选择的命令而异

通俗地说,它用于回答以下问题:我应该去哪里?提交到哪个提交?

HEAD 表示(对当前提交的引用) HEAD~1 表示(参考)之前的 1 次提交 HEAD~ ALSO 表示(参考)之前的 1 次提交 HEAD~87 表示(参考)之前的 87 次提交 HEAD~3..HEAD 表示从 3 次提交到当前提交

用法:

git checkout HEAD~1 实际上会在之前 GO/checkout 到 1 个提交/引用 git reset HEAD~3 将取消提交您的最后 3 次提交 - 不删除更改,即您可以一起查看最后 3 次提交中所做的所有更改,删除您不喜欢的任何内容或添加到其中,然后再次提交。李> git reset --hard HEAD~3 将取消提交您的最后一次提交并删除他们的更改。它将完全删除这些更改。更多信息请见here。 git diff HEAD~3 查看最近 3 次提交的更改 git diff someFile HEAD~3 查看特定文件的最后 3 次更改 git revert --no-commit HEAD~3..HEAD。通过还原最后 3 次提交来进行新的提交:更多信息请参见 here

还要确保你看到What is a detached HEAD的这个答案。

它在cat .git/HEAD 上有一些很好的信息

【讨论】:

回到我自己的答案:)【参考方案4】:

Git 中的 HEAD 指针

Git 维护一个名为 HEAD 的引用变量。我们称这个变量为指针,因为它的目的是引用或指向存储库中的特定提交。当我们进行新的提交时,指针将会改变或移动以指向新的提交。 HEAD 总是指向我们存储库中当前分支的尖端。现在,这与我们的存储库有关,而不是我们的暂存索引或我们的工作目录。

另一种理解它的方式是我们存储库的最后一个状态或最后签出的内容,因为它是存储库停止的位置或最后一个状态,您也可以说 HEAD 指向下一个的父级commit 或者它是提交写入的地方。

我认为一个很好的比喻是磁带录音机的播放和录音头。当我们开始录制音频时,磁带经过磁头,并记录在上面。当我们按下停止时,记录磁头停止的地方是当我们第二次按下记录时它将再次开始记录的地方。现在我们可以四处移动,我们可以将磁头移动到不同的位置,但是磁头所在的位置当我们再次点击 Record 时,它将开始录制。

Git 中的 HEAD 指针非常相似,它指向我们接下来要开始录制的位置。这是我们在存储库中为我们已提交的内容留下的地方。

【讨论】:

【参考方案5】:

简单来说,HEAD 是对当前签出分支中最后一次提交的引用。

将 HEAD 视为“当前分支”。当您使用 git checkout 切换分支时,HEAD 修订版会更改为指向新分支的尖端。

您可以通过执行查看 HEAD 指向的内容:

cat .git/HEAD

HEAD 可以引用与分支名称无关的特定修订。这种情况称为分离的 HEAD。

【讨论】:

【参考方案6】:

基本上 HEAD 是一个指针/引用,它指向当前分支中的最后一次提交。

您可以使用这两个命令来验证这一点。

$ git log -1

commit 9883e13257f2e7555eb6e3b14b2c814978c75692 (HEAD -> MyLocalBranch)
Author: vikram <vikramguptavit@gmail.com>
Date:   Sun Oct 11 23:32:45 2020 -0400
this is my last commit message

现在使用以下命令查看 HEAD 指向的位置:

$ git rev-parse HEAD
9883e13257f2e7555eb6e3b14b2c814978c75692

如您所见,这两个提交哈希是相同的。所以 HEAD 总是指向当前分支中的最新/最后一次提交。

【讨论】:

以上是关于git 中的 HEAD 是啥?的主要内容,如果未能解决你的问题,请参考以下文章

HEAD、master、origin的git概念是啥?

Git: Git中的HEAD

git中的hg clone --noupdate等价物是啥?

Git 中的 HEAD 和 ORIG_HEAD

Git 中的 HEAD 和 ORIG_HEAD

Git 中的 HEAD 和 ORIG_HEAD