你看到Git文档说的是
分支必须在HEAD中完全合并。
但是什么是Git HEAD
呢?
答案 0 :(得分:689)
您可以将HEAD视为“当前分支”。当您使用git checkout
切换分支时,HEAD修订版将更改为指向新分支的提示。
您可以通过以下方式查看HEAD指出的内容:
cat .git/HEAD
就我而言,输出是:
$ cat .git/HEAD
ref: refs/heads/master
HEAD可以引用与分支名称无关的特定修订。这种情况称为detached HEAD。
答案 1 :(得分:164)
引用other people:
头部只是对a的引用 提交对象。每个头都有一个名字 (分支名称或标签名称等)。通过 默认情况下,每个都有一个头 存储库称为主。存储库 可以包含任意数量的头。在 任何给定的时间,选择一个头 作为“当前的头脑。”这个头是 别名到HEAD,总是在大写字母“。
注意这个区别:一个“头” (小写)指的是任何一个 存储库中的命名头; “头” (大写)专指 目前活跃的头脑。这个 区别在Git中经常使用 文档。
可以找到另一个快速涵盖git内部工作原理的好资源(以便更好地理解head / HEAD)here。引用(ref :)或头或分支可以被视为在提交历史记录中粘贴到提交的便利贴。通常它们指向一系列提交的提示,但它们可以通过git checkout
或git reset
等移动。
答案 2 :(得分:54)
我从github开发人员Scott Chacon [video reference]推荐这个定义:
Head是您当前的分支。这是一个象征性的参考。它是对分支的引用。你总是有HEAD,但是HEAD将指向其中一个指针,指向你所在的一个分支。它是您下次提交的父级。它应该是最后签出到您的工作目录中的内容......这是您的工作目录的最后已知状态。
整个视频将对整个git系统进行公平的介绍,所以如果有时间,我还建议你全部观看。
答案 3 :(得分:48)
HEAD只是一个特殊指针,指向您当前所在的本地分支。
在Pro Git一书,3.1 Git Branching - Branches in a Nutshell一章的创建新分支一节中
如果您创建新分支会发生什么?好吧,这样做会创造一个新的 指针让你四处走动。假设您创建了一个新分支 叫测试。您可以使用git branch命令执行此操作:
$ git branch testing
这会在您当前所在的同一提交中创建一个新指针
![]()
Git如何知道您目前所在的分支?它保留了一个名为HEAD的特殊指针。请注意,这与...有很大不同 HEAD在您可能习惯的其他VCS中的概念,例如 Subversion或CVS。在Git中,这是指向本地分支的指针 你现在在。在这种情况下,你仍然在掌握。 git branch命令只创建了一个新分支 - 它没有切换到那个分支 分支。
![]()
答案 4 :(得分:33)
假设这不是一个特殊情况,称为"分离的HEAD",那么,正如O' Reilly Git一书中所述,第二版,第69页,HEAD
表示:< / p>
HEAD
始终引用当前的最新提交 科。更改分支时,HEAD
会更新以引用新分支 分支的最新提交。
所以
HEAD
&#34;提示&#34;目前的分支。
请注意,我们可以使用HEAD
来引用最近的提交,并使用HEAD~
作为提示之前的提交,并使用HEAD~~
或HEAD~2
作为提交甚至更早,等等。
答案 5 :(得分:20)
HEAD
指的是您的工作副本指向的当前提交,即您当前已签出的提交。来自official Linux Kernel documentation on specifying Git revisions:
HEAD
命名您在工作树中基于更改的提交。
但请注意,在即将发布的Git版本1.8.4中,@
也可以用作HEAD
的简写,noted by Git contributor Junio C Hamano in his Git Blame blog:
而不是输入“HEAD”,您可以改为说“@”,例如“git log @”。
Stack Overflow用户VonC也找到了一些interesting information on why @
was chosen as a shorthand in his answer to another question。
同样有趣的是,在某些环境中,没有必要将HEAD
大写,特别是在使用不区分大小写的文件系统(特别是Windows和OS X)的操作系统中。
答案 6 :(得分:16)
查看Creating and playing with branches
HEAD实际上是一个文件,其内容决定了HEAD变量引用的位置:
$ cat .git/HEAD
ref: refs/heads/master
$ cat .git/refs/heads/master
35ede5c916f88d8ba5a9dd6afd69fcaf773f70ed
在此存储库中,HEAD文件的内容引用名为 refs / heads / master 的第二个文件。文件 refs / heads / master 包含主分支上最新提交的哈希值。
结果是HEAD指向 .git / refs / heads / master 文件中的主分支提交。
答案 7 :(得分:14)
我想在Greg Hewgil接受的答案中详述一些事情。 根据{{3}}
<强>科:强>
分支本身被定义为提交中可到达的所有点 来自命名提交的图形(分支的“提示”)。
HEAD:特殊类型的参考
特殊参考HEAD确定你在哪个分支......
<强>参考文献强>
Git定义了它调用的两种引用或命名指针 “参考文献”:
- 一个简单的引用,直接指向对象ID(通常是提交或标记)
- 符号引用(或symref),指向另一个引用(简单或符号)
正如格雷格所说,HEAD可能处于“超脱状态”。因此HEAD可以是简单的ref(对于分离的HEAD)或symref。
如果HEAD是现有分支的符号引用,那么你就是“开启” 那个分支。另一方面,如果HEAD直接是简单的参考 通过其SHA-1 ID命名提交,然后您不是“在”任何分支上,但是 相反,在“分离的HEAD”模式下,当您查看一些时会发生这种情况 早些时候承诺检查。
答案 8 :(得分:6)
我认为'HEAD'是当前的结账提交。换句话说,“HEAD”指向当前已签出的提交。
如果您刚刚克隆而未检出,我不知道它指向的是什么,可能是一些无效的位置。
答案 9 :(得分:6)
在这些答案中,有许多可能是细微但重要的误解。我以为我会添加答案来清除它。
什么是
HEAD
?
HEAD
是一个符号引用,指向您在提交历史记录中的任何位置。无论您走到哪里,无论做什么,它都会跟随您,就像阴影一样。如果您提交,HEAD
将移动。如果您结帐,HEAD
将移动。无论您做什么,如果您在提交历史记录中移动了新的位置,那么HEAD
就会与您一起移动。要解决一个常见的误解:您不能脱离HEAD
。那不是分离的HEAD状态。如果您发现自己在想:“哦,不,我处于HEAD分离状态!我迷失了HEAD!”记住,这是你的头。 HEAD是你。您尚未与HEAD分离,您和您的HEAD已与其他物体分离。
HEAD
可以指向一个提交,是的,但是通常没有。让我再说一遍。 通常HEAD
不指向提交。它指向分支引用。它是附加的分支,当您执行某些操作(例如commit
或reset
)时,附加的分支将与HEAD
一起移动。您可以通过在引擎盖下查看来了解它的指向。
cat .git/HEAD
通常您会得到这样的东西:
ref: refs/heads/master
有时您会得到这样的东西:
a3c485d9688e3c6bc14b06ca1529f0e78edd3f86
这就是HEAD
直接指向提交时发生的情况。这称为分离式HEAD,因为HEAD
指向分支引用以外的其他内容。如果您在这种状态下进行提交,master
(不再附加到HEAD
)将不再与您一起移动。提交在哪里都没有关系。 您可能与主分支位于同一提交上,但是如果HEAD
指向该提交而不是该分支,则它是分离的,并且新的提交不会与分支引用关联。 strong>
如果尝试以下练习,则可以以图形方式查看。从git存储库中运行此程序。您会得到一些稍微不同的东西,但是它们的关键部分就在那里。是时候直接检查提交了,只需使用从第一个输出(这里为a3c485d
)获得的任何缩写哈希即可。
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仍指与分支名称关联的特定修订版。我们仍然在主分支上,不是吗?
现在尝试:
git status
# HEAD detached at a3c485d
不。我们处于“分离头”状态。
您可以看到(HEAD -> branch)
与(HEAD, branch)
和git log -1
的表示形式相同。
HEAD
是你。无论您身在何处,它都指向您签出的所有内容。通常,这不是提交,而是分支。如果HEAD
确实指向一个提交(或标签),即使它与分支也指向的提交(或标签)相同,您(和HEAD
)也可以从那个分支中分离出来。由于您没有附加分支,因此在您进行新提交时,该分支也不会跟随您。 HEAD
不过会。
答案 10 :(得分:5)
头指向当前已检出分支的提示。
在您的存储库中,有一个.git文件夹。在以下位置打开文件:.git \ refs \ heads。该文件中的(sha-1哈希)代码(大多数情况下为master)将是最近的提交,即在命令git log
的输出中看到的提交。有关.git文件夹的更多信息:http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html
答案 11 :(得分:4)
将正确答案中的观点归结为一个很好的方法就是跑步
git reflog HEAD
,你得到了HEAD指出的所有地方的历史。
答案 12 :(得分:4)
在阅读了之前的所有答案之后,我仍然想要更清晰。官方网站http://git-scm.com/blog上的这个博客给了我正在寻找的东西:
Git中的HEAD是当前分支引用的指针,而后者又是指针到你上次提交或最后一次提交的提交进入你的工作目录。这也意味着它将成为您下一次提交的父级。通常最简单的想法是HEAD是您上一次提交的快照。
答案 13 :(得分:2)
感觉HEAD
只是您签出的最后一次提交的标签。
这可以是特定分支的尖端(例如“ master”),也可以是某个分支的中间提交(“分离头”)
答案 14 :(得分:1)
Git
全部与提交有关。
Head
指向您当前已签出的提交。
$ git cat-file -t HEAD
commit
无论何时签出分支,HEAD都指向该分支上的最新提交。 HEAD的内容可以按以下方式检查(对于master分支):
$ cat .git/refs/heads/master
b089141cc8a7d89d606b2f7c15bfdc48640a8e25
答案 15 :(得分:1)
我仍在弄清楚git的内部原理,并且到目前为止已经弄清楚了:
比方说,当前分支是 master 。
% cat .git/HEAD
ref: refs/heads/master
% cat .git/refs/heads/master
f342e66eb1158247a98d74152a1b91543ece31b4
% git log --oneline
f342e66 (HEAD -> master,...) latest commit
fa99692 parent of latest commit
所以我的想法是HEAD文件是一种跟踪最新提交的便捷方法,而不是记住长哈希值。
答案 16 :(得分:0)
查看http://git-scm.com/book/en/Git-Branching-What-a-Branch-Is
图3-5。 HEAD文件指向您所在的分支。
答案 17 :(得分:0)
除了所有定义外,我想到的是,当您进行提交时,GIT在存储库中创建一个提交对象。提交对象应具有一个父对象(如果是合并提交,则应具有多个父对象)。现在,git如何知道当前提交的父级?因此HEAD是指向最后提交的(该引用的)指针,它将成为当前提交的父级。
答案 18 :(得分:0)
这两个可能让你感到困惑:
头
指向最近提交的分支的命名引用。除非您使用包参考,否则磁头通常存储在$ GIT_DIR / refs / heads /.
中HEAD
当前分支,或者您的工作树通常是从HEAD指向的树生成的。 HEAD必须指向头部,除非您使用的是分离的HEAD。
答案 19 :(得分:0)
分支实际上是保存提交ID(例如 17a5 )的指针。 HEAD 是指向用户当前正在处理的分支的指针。
HEAD 的参考文件如下:
参考:
您可以通过访问正在使用的存储库中的.git/HEAD
.git/refs
来检查这些文件。
答案 20 :(得分:0)
HEAD实际上只是一个用于存储当前分支信息的文件
如果您在git命令中使用HEAD,则指向当前分支
您可以通过以下方式查看此文件的数据
cat .git/HEAD
答案 21 :(得分:0)
说明 HEAD 是什么的插图,包括在 附加 或 分离 中如何操纵 HEAD 的并排比较> 状态不同。
一个常见的误解是消息 You are in 'detached HEAD' state 是错误的语气,而实际上它只是描述了 HEAD 如何引用当前快照.
要从分离状态转变为附加状态,您可以从您所在的位置创建一个新分支,或者切换到现有分支。请注意,如果您切换到另一个现有分支,则在分离状态下创建的任何提交最终都将被丢弃。
答案 22 :(得分:-4)
作为一个概念,头部是分支中的最新版本。如果每个命名分支有多个头,则可能在进行本地提交时创建它而不进行合并,从而有效地创建一个未命名的分支。
要拥有一个“干净”的存储库,每个命名分支应该有一个头,并且在本地工作后总是合并到一个命名分支。
Mercurial也是如此。