乐闻世界logo
搜索文章和话题

Git 中的 head 是什么?

8 个月前提问
4 个月前修改
浏览次数166

7个答案

1
2
3
4
5
6
7

HEAD在Git中是一个引用(reference),它指向当前工作目录中的最新提交。简单来说,它代表了你最后一次提交的结果,或者说是当前工作的快照。在Git中,HEAD通常用来表示当前的工作分支的尖端。

例如,如果你在master分支上工作,并做了一些提交,HEAD将会指向master分支的最新提交。如果你切换到另一个分支,比如feature,那么HEAD就会更新,以指向feature分支的最新提交。

在Git中,HEAD可以是附着的(attached)状态或游离的(detached)状态。当它处于附着状态时,它指向当前分支的最新提交。当处于游离状态时,它直接指向一个提交,而不是某个分支的尖端。这种情况通常发生在你检出一个特定的提交而不是分支时。

此外,HEAD还可以与其他引用一起使用,比如HEAD~1可以用来引用当前提交的父提交,HEAD~2用来引用父提交的父提交,依此类推。

一个实际的例子是,如果我想查看当前分支的历史中的上一个提交,我可以使用命令git show HEAD~1。如果我想将当前分支重置到这个上一个提交的状态,我可以使用命令git reset --hard HEAD~1。这将会使当前分支的HEAD指向那个提交,并且将工作目录的内容更新为那个提交的内容。

2024年6月29日 12:07 回复

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

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

shell
cat .git/HEAD

就我而言,输出是:

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

HEAD 可以引用与分支名称不相关的特定修订版。这种情况称为detached HEAD

2024年6月29日 12:07 回复

引用别人的话

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

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

可以在这里找到另一个快速介绍 git 内部工作原理(从而更好地理解 head/HEAD)的好资源。引用 (ref:) 或标题或分支可以被视为粘贴在提交历史记录中的提交上的便利贴。git checkout通常它们指向一系列提交的尖端,但它们可以通过或git reset等移动。

2024年6月29日 12:07 回复

这些答案中可能存在一个微妙但重要的误解。我想我应该添加我的答案来澄清它。

什么是HEAD

头就是你

HEAD是一个符号引用,指向您在提交历史记录中的任何位置。无论你走到哪里,无论你做什么,它都会像影子一样跟随你。如果你做出承诺,HEAD就会移动。如果你结账了一些东西,HEAD就会搬家。无论你做什么,如果你在提交历史中移动到了新的地方,HEAD它就会随着你一起移动。为了解决一个常见的误解:你无法将自己与HEAD. 这不是分离的 HEAD 状态。如果你发现自己在想:“哦不,我处于分离的头脑状态!我失去了我的头脑!” 记住,这是你的头。头就是你。你还没有脱离头脑,你和你的头脑已经脱离了其他东西。

HEAD 可以连接什么?

HEAD可以指向提交,是的,但通常不会。让我再说一遍。_通常HEAD不指向提交。_它指向一个分支引用。它_附加_到该分支,当您执行某些操作(例如commitreset)时,附加的分支将随着 一起移动HEAD。您可以通过查看引擎盖下面的内容来了解​​它所指向的内容。

shell
cat .git/HEAD

通常你会得到这样的结果:

shell
ref: refs/heads/master

有时你会得到这样的信息:

shell
a3c485d9688e3c6bc14b06ca1529f0e78edd3f86

HEAD这就是当直接指向提交时会发生的情况。这称为分离头,因为HEAD它指向分支引用之外的其他内容。如果您在此状态下进行提交,master则不再附加到HEAD,将不再与您一起移动。该提交在哪里并不重要。您可以与主分支位于同一提交上,但如果HEAD指向该提交而不是分支,则它会被分离,并且新的提交将不会与分支引用关联。

如果您尝试以下练习,您可以以图形方式查看此内容。从 git 存储库运行此命令。你会得到一些稍微不同的东西,但它们的关键部分会在那里。当需要直接检查提交时,只需使用从第一个输出中获得的任何缩写哈希(此处是a3c485d)。

shell
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)

好的,所以这里的输出有一点小小的差异。直接检查提交(而不是分支)给我们一个逗号而不是箭头。你怎么看,我们是否处于分离的 HEAD 状态?HEAD 仍然指与分支名称关联的特定修订版。我们仍然_在_master 分支上,不是吗?

现在尝试:

shell
git status # HEAD detached at a3c485d

没有。我们处于“分离头”状态。

(HEAD -> branch)您可以看到与 的(HEAD, branch)相同表示git log -1

综上所述

HEAD是你。它指向您查看的任何内容,无论您身在何处。通常这不是提交,而是分支。如果HEAD _确实_指向提交(或标记),即使它与分支也指向相同的提交(或标记),您(和HEAD)也已与该分支分离。由于您没有附加分支,因此当您进行新提交时,分支不会跟随您。HEAD不过,会的。

2024年6月29日 12:07 回复

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

来自Pro Git书籍,第3.1 章 Git 分支 - 简而言之分支,在创建新分支部分:

如果创建一个新分支会发生什么?好吧,这样做会创建一个新的指针供您移动。假设您创建一个名为测试的新分支。您可以使用 gitbranch 命令执行此操作:

shell
$ git branch testing

这会在您当前所在的同一提交处创建一个新指针

在此输入图像描述

Git 如何知道你当前所在的分支?它保留一个称为 HEAD 的特殊指针。请注意,这与您可能习惯的其他 VCS(例如 Subversion 或 CVS)中的 HEAD 概念有很大不同。在 Git 中,这是指向您当前所在的本地分支的指针。在这种情况下,你仍然是master。gitbranch 命令只创建了一个新分支——它并没有切换到该分支。

在此输入图像描述

2024年6月29日 12:07 回复

我推荐 github 开发者 Scott Chacon 的这个定义 [视频参考]:

Head 是您当前的分支。这是一个象征性的参考。它是对分支的引用。你总是有 HEAD,但 HEAD 将指向其他指针之一,指向你所在的分支之一。它是您下一次提交的父级。它应该是上次签出到您的工作目录中的内容...这是您的工作目录的最后一个已知状态。

整个视频将公正地介绍整个 git 系统,因此我也建议您如果有时间的话可以全部观看。

2024年6月29日 12:07 回复

Git 中的 HEAD 是一个引用(reference),指向当前工作目录中所检出(checked out)的最新提交(commit)。换句话说,HEAD 指向当前分支的最新的本地提交,并且它会随着新的提交而移动。

当你切换分支时,HEAD 也会随之切换到新分支的最新提交。在多数情况下,HEAD 会指向一个分支名,比如 mastermain,这被称为“依附的 HEAD”(attached HEAD)。这意味着你正处在正常的开发过程中,你的 HEAD 正依附于一个特定的分支上。

然而,也可以在没有依附任何分支的情况下检出某个特定的提交,这被称作“分离的 HEAD”(detached HEAD)。在这种模式下,你可以查看历史中的代码,或者进行实验性的提交,但要注意,如果你在分离的 HEAD 状态下创建了新的提交,那么,当你切换回一个正常的分支时,这些提交可能会丢失,除非你特别地创建一个新分支来保存这些变化。

你可以通过 git log 查看 HEAD 的指向,或者使用 git show-ref --heads 查看所有分支的当前提交。在 Git 的实现里,HEAD 通常是一个包含指向当前提交 SHA-1 值的文件,位于 .git/ 目录中。

2024年6月29日 12:07 回复

你的答案