Git 中的 HEAD 是什么?

您会看到 Git 文档说出类似

分支必须完全合并在 HEAD 中。

但是到底什么是 Git HEAD

答案

cat .git/HEAD
$ cat .git/HEAD
ref: refs/heads/master

引用其他人

头仅仅是对提交对象的引用。每个头都有一个名称(分支名称或标签名称等)。默认情况下,每个存储库中都有一个称为 master 的头。存储库可以包含任意数量的头。在任何给定时间,将一个头选为 “当前头”。该头别名为 HEAD,始终以大写字母开头”。

注意这种区别:“头”(小写)是指存储库中任何已命名的头; “HEAD”(大写)专门指当前活动的 head。这种区别在 Git 文档中经常使用。

这里可以找到另一个快速介绍 git 内部工作原理的好资料(因此可以更好地了解 heads / HEAD)。引用(ref :) 或标题或分支可以视为粘贴在提交历史中的提交上的便利贴。通常它们指向一系列提交的尖端,但是可以使用git checkoutgit reset等来移动它们。

我从 github 开发人员 Scott Chacon [ 视频参考 ] 推荐了这个定义:

头是您当前的分支。它是一个符号参考。它是对分支的引用。您始终具有 HEAD,但是 HEAD 将指向这些其他指针之一,您所在的分支之一。它是您下次提交的父项。这应该是最后一次签出到工作目录中的内容。这是您的工作目录所处的最后已知状态。

整个视频将对整个 git 系统进行公平的介绍,因此,如果有时间的话,我也建议您观看所有视频。

HEAD 只是一个特殊的指针,它指向您当前所在的本地分支。

Pro Git书籍的第3.1Git 分支 - 坚果壳中的分支, 创建新分支一节中:

如果创建一个新分支会怎样?好吧,这样做会创建一个新的指针供您移动。假设您创建了一个名为 testing 的新分支。您可以使用 git branch 命令执行此操作:

$ git branch testing

这将在您当前正在执行的同一提交处创建一个新的指针

在此处输入图片说明

Git 如何知道您当前在哪个分支?它保留一个称为 HEAD 的特殊指针。请注意,这与您可能习惯的其他 VCS 中的 HEAD 概念有很大不同,例如 Subversion 或 CVS。在 Git 中,这是指向您当前所在的本地分支的指针。在这种情况下,您仍处于掌握状态。 git branch 命令仅创建一个新分支,但未切换到该分支。

在此处输入图片说明

假设这不是称为 “分离式 HEAD” 的特殊情况,那么,如 O'Reilly Git 的书第二版,第 69 页所述, HEAD意思是:

HEAD始终引用当前分支上的最新提交。更改分支时, HEAD将更新为引用新分支的最新提交。

所以

HEAD当前分支的 “提示”

请注意,我们可以使用HEAD来引用最新的提交,并使用HEAD~作为小费之前的提交,而HEAD~~HEAD~2甚至更早地作为提交,依此类推。

HEAD是指您的工作副本指向的当前提交,即您当前已签出的提交。摘自有关指定 Git 修订版的 Linux Kernel 官方文档

HEAD在工作树中命名所做更改的提交。

但是请注意,在即将发布的 Git 1.8.4 版本中, @也可以用作HEAD的简写,正如Git 贡献者 Junio C Hamano 在其 Git Blame 博客中指出的那样

不用输入 “HEAD”,您可以说 “@”,例如 “git log @”。

Stack Overflow 用户VonC还发现了一些有趣的信息,说明了为什么@被选为他对另一个问题的简写

同样令人感兴趣的是,在某些环境中,不必大写HEAD ,特别是在使用不区分大小写的文件系统的操作系统中,尤其是 Windows 和 OSX。

$ cat .git/HEAD
ref: refs/heads/master
$ cat .git/refs/heads/master
35ede5c916f88d8ba5a9dd6afd69fcaf773f70ed
cat .git/HEAD
ref: refs/heads/master
a3c485d9688e3c6bc14b06ca1529f0e78edd3f86
git checkout master
git log --pretty=format:"%h:  %d" -1
# a3c485d:   (HEAD -> master)

git checkout a3c485d -q # (-q is for dramatic effect)
git log --pretty=format:"%h:  %d" -1   
# a3c485d:   (HEAD, master)
git status
# HEAD detached at a3c485d

我想详细介绍 Greg Hewgil 接受的答案中的一些内容。根据Git Pocket Guide

科:

分支本身定义为提交图中从命名提交(分支的 “尖端”)到达的所有点。

HEAD:特殊类型的 Ref

特殊的 HEAD 决定了您所在的分支。

参考

Git 定义了两种引用或命名的指针,它们称为 “引用”:

  • 一个简单的 ref,直接指向对象 ID(通常是提交或标记)
  • 一个符号引用(或 symref),它指向另一个引用(简单或符号)

如 Greg 所述,HEAD 可以处于 “分离状态”。因此,HEAD 可以是简单的 ref(对于分离的 HEAD),也可以是 symref。

如果 HEAD 是现有分支的符号引用,则您位于该分支上。另一方面,如果 HEAD 是直接通过其 SHA-1 ID 直接命名提交的简单引用,则您不是 “在” 任何分支上,而是在 “分离的 HEAD” 模式下,这种情况在您较早签出时会发生。致力于检查。

我认为 “HEAD” 是当前的检出提交。换句话说,“HEAD” 指向当前已签出的提交。

如果您只是克隆但没有签出,我可能不知道它指向什么,可能是某个无效的位置。