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

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


当前回答

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


有一个小小的例外,那就是分离的HEAD。当您签出一个提交(或标记)而不是一个分支时,就会出现分离HEAD。在这种情况下,您必须将其想象为一个没有名称的临时分支;所以我们没有命名分支引用,我们只有HEAD。它仍然允许您进行提交(这将更新HEAD),因此如果您将分离的HEAD视为没有名称的临时分支,那么上面的简短定义仍然是正确的。

其他回答

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

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

你可以通过这样做来查看HEAD指向什么:

cat .git/HEAD

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

Git中的HEAD指针

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

另一种理解它的方式是存储库的最后状态或最后签出的内容,因为它是存储库离开的地方或最后的状态,所以您也可以说HEAD指向下一次提交的父节点,或者它是提交写入将要发生的地方。

我认为一个很好的比喻是盒式磁带录音机的回放和记录磁头。当我们开始录制音频时,磁带会经过磁头,然后记录到磁头上。当我们按下“停止”键时,记录头停止的地方就是我们第二次按下“记录”键时它将再次开始录制的地方。现在我们可以移动,我们可以将磁头移动到不同的地方,但是当我们再次点击录制时,无论磁头在哪里它都会开始录制。

Git中的HEAD指针非常类似,它指向我们接下来要开始记录的地方。它是我们在存储库中停止提交的东西的地方。

基本上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总是指向当前分支中的最新/最后一次提交。

HEAD是当前检出提交的引用。

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

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

一般来说,HEAD只是一个方便的名字,意思是“您已检出的内容”,您实际上不必太担心它。只需要注意你签出了什么,并记住如果你不在分支上(分离HEAD状态),你可能不想提交,除非你知道你在做什么(例如,在一个交互式的rebase中)。

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


有一个小小的例外,那就是分离的HEAD。当您签出一个提交(或标记)而不是一个分支时,就会出现分离HEAD。在这种情况下,您必须将其想象为一个没有名称的临时分支;所以我们没有命名分支引用,我们只有HEAD。它仍然允许您进行提交(这将更新HEAD),因此如果您将分离的HEAD视为没有名称的临时分支,那么上面的简短定义仍然是正确的。