git里的HEAD是什么?

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

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

106337 次浏览

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


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

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

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

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

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

Git中的HEAD指针

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

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

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

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

从文档;HEAD角色是:

角色
最后一次提交快照,下一个 [future]父
指数 建议的下一次提交快照
工作目录 沙盒

HEAD是指向当前分支引用的指针,而当前分支引用又是指向该分支上最后一次提交的指针。

这意味着HEAD将是创建的下一个提交的父节点。通常最简单的方法是将HEAD看作您在该分支上最后一次提交的快照。


我一直认为HEAD~5意味着 5之前提交。但是它不携带命令的GO部分。它只携带命令的参考部分。

您可以使用该引用做什么,取决于您选择的命令

通俗地说,它用于回答问题:在哪里我应该去吗?向哪个提交?

  • HEAD表示当前提交(引用)
  • HEAD~1表示(引用)1提交之前
  • HEAD~ ALSO表示(引用)1提交之前
  • HEAD~87表示87次提交之前
  • HEAD~3..HEAD表示从3次提交到当前提交(总共3次提交)

用法:

  • git checkout HEAD~1实际上会GO/checkout到1提交/引用之前
  • git reset HEAD~3将取消提交你的最后3次提交-不删除更改,即你可以一起看到在最近3次提交中所做的所有更改,删除任何你不喜欢或添加的内容,然后再次提交。
  • git reset --hard HEAD~3将取消你上次提交的并删除它们的更改。它将完全删除这些更改。更多信息见在这里
  • git diff HEAD~3来查看最近3次提交的变化
  • git diff someFile HEAD~3来查看特定文件的最后3个变化
  • git revert --no-commit HEAD~3..HEAD。返回3次提交,而不是自动提交,即你必须自己做git commit -m。更多信息见在这里
  • git rev-parse HEAD~2输出之前两次提交的SHA。
  • 查看pull请求和main之间的所有变化。这是一个多步骤的过程。
git fetch origin/feature22
git checkout feature22
git merge-base feature22 main # will return the SHA of their 050dc022f3a65bdc78d97e2b1ac9b595a924c3f2
git reset 050dc022f3a65bdc78d97e2b1ac9b595a924c3f2

你可以只做git reset main,但只有当你的同事创建了pull请求,并对main进行了最新的修改,这才有效。如果他们正在开发一个大功能(并且已经好几天没有与main合并了),而你只是想看看他们在最后一次从main中提取后添加了什么,那么你必须遵循上面的步骤。


也使确定,你会看到这个什么是独立的HEAD的答案。

它有一些关于cat .git/HEAD的好信息


超出范围,但超级有趣:

除了HEAD之外,还有其他类型的正面。看到git修正:

ORIG_HEAD

ORIG_HEAD是由命令创建的,这些命令以激烈的方式移动你的HEAD,以记录HEAD在操作之前的位置,这样你就可以轻松地将分支的顶端更改回运行它们之前的状态

撤销git merge

git reset --hard ORIG_HEAD

MERGE_HEAD

我在尝试再次合并之前并结束现有的合并后得到此错误消息

fatal:您还没有结束您的合并(MERGE_HEAD存在)。 请在合并前提交您的更改。

为了解决这个问题,我必须结束合并。然后再进行一次合并。

FETCH_HEAD

记录您使用最后一次git获取调用从远程存储库获取的分支

CHERRY_PICK_HEAD

记录你在运行git cherry-pick时选择的提交。

有关更多信息,请参阅另一个答案文档

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

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

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

cat .git/HEAD

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