你看到Git留档说
分支必须完全合并到HEAD中。
什么是GitHEAD?
HEAD
您可以将HEAD视为“当前分支”。当您使用git checkout切换分支时,HEAD修订版更改为指向新分支的尖端。
git checkout
您可以通过执行以下操作来查看HEAD指向的内容:
cat .git/HEAD
在我的例子中,输出是:
$ cat .git/HEADref: refs/heads/master
HEAD可能引用与分支名称无关的特定修订版。这种情况称为分离头。
引用其他人:
一个head是一个简单的引用提交对象。每个头都有一个名称(分支机构名称或标签名称等)。由默认情况下,每个人都有一个头名为master的存储库。一个存储库可以包含任意数量的头。在任何时候都有一个头被选中作为“现任头”。这个头是别名为HEAD,总是大写字母”。注意这个区别:一个“头”(小写)是指任何一个存储库中的命名头;“HEAD”(大写)专门指目前活跃的头。这区分在Git中经常使用留档
一个head是一个简单的引用提交对象。每个头都有一个名称(分支机构名称或标签名称等)。由默认情况下,每个人都有一个头名为master的存储库。一个存储库可以包含任意数量的头。在任何时候都有一个头被选中作为“现任头”。这个头是别名为HEAD,总是大写字母”。
注意这个区别:一个“头”(小写)是指任何一个存储库中的命名头;“HEAD”(大写)专门指目前活跃的头。这区分在Git中经常使用留档
另一个快速涵盖git内部工作原理的好来源(因此可以更好地理解head/HEAD)可以在这里中找到。引用(ref:)或头或分支可以被视为提交历史中粘贴在提交上的便利贴。通常它们指向一系列提交的尖端,但它们可以用#0或#1等移动。
我推荐这个定义来自github开发者Scott Chacon[视频参考]:
head是你当前的分支。它是一个符号引用。它是对一个分支的引用。你总是有HEAD,但是HEAD会指向其他指针之一,指向你所在的分支之一。它是你下一次提交的父级。它应该是最后一次签出到你的工作目录的内容…这是你工作目录的最后已知状态。
整个视频将对整个git系统进行公平的介绍,所以如果有时间,我也建议你全部观看。
作为一个概念,head是分支中的最新版本。如果每个命名分支有多个head,则可能是在进行本地提交而不合并时创建的,从而有效地创建了一个未命名分支。
要拥有一个“干净”的存储库,您应该每个命名分支都有一个头,并在本地工作后始终合并到一个命名分支。
Mercurial也是如此。
一个很好的方法来开车回家的点在正确的答案是运行git reflog HEAD,您将获得HEAD指向的所有位置的历史记录。
git reflog HEAD
看看http://git-scm.com/book/en/Git-Branching-What-a-Branch-Is
图3-5。HEAD文件指向您所在的分支。
我认为HEAD是当前签出的提交。换句话说,HEAD指向当前签出的提交。
如果你刚刚克隆,没有签出我不知道它指向什么,可能是一些无效的位置。
HEAD指的是您的工作副本指向的当前提交,即您当前签出的提交。从官方Linux内核留档指定Git版本:
HEAD命名您在工作树中基于其进行更改的提交。
但是请注意,在即将发布的Git 1.8.4版本中,@也可以用作HEAD的简写,如Git贡献者Junio C Hamano在他的Git Blame博客中提到:
@
而不是键入“HEAD”,你可以说“@”代替,例如“git log@”。
Stack Overflow用户VonC也发现了一些关于为什么在回答另一个问题时选择#0作为速记的有趣信息。
同样有趣的是,在某些环境中,没有必要将HEAD大写,特别是在使用不区分大小写的文件系统的操作系统中,特别是Windows和OS X。
我想在Greg Hewgil接受的答案中详细说明一些事情。根据Git Pocket指南
部门:
分支本身定义为提交中可到达的所有点来自命名提交的图(分支的“提示”)。
头:特殊类型的参考
特殊的ref HEAD决定你在哪个分支…
Refs
Git定义了两种引用,或命名指针,它调用"ref":请求参数 一个简单的ref,直接指向对象ID(通常是提交或标记)符号ref(或Symref),指向另一个ref(简单或符号)
Git定义了两种引用,或命名指针,它调用"ref":
正如Greg提到的,HEAD可以处于“分离状态”。因此HEAD可以是简单的ref(用于分离的HEAD)或Symref。
如果HEAD是现有分支的符号引用,则为“on”另一方面,如果HEAD是一个简单的直接引用通过其SHA-1 ID命名提交,那么您不是“在”任何分支上,而是而是在“分离头”模式下,当你检查出一些先检查一下
这两个可能会让你困惑:
头
指向最近提交的分支的命名引用。除非您使用包引用,否则头通常存储在$GIT_DIR/refs/head/中。
当前分支或您的工作树通常是从HEAD指向的树生成的。HEAD必须指向一个头,除非您使用的是分离的HEAD。
看看创建和玩树枝
HEAD实际上是一个文件,其内容决定了HEAD变量引用的位置:
$ cat .git/HEADref: refs/heads/master$ cat .git/refs/heads/master35ede5c916f88d8ba5a9dd6afd69fcaf773f70ed
在此存储库中,HEAD文件的内容引用了名为主裁判的第二个文件。文件主裁判包含主分支上最新提交的哈希值。
结果是HEAD指向来自. g it/refs/head/master文件的主分支提交。
假设它不是一个称为“分离的HEAD”的特殊情况,那么,正如O'Reilly Git书中所述,第2版,第69页,HEAD意味着:
HEAD总是引用当前服务器上最近的提交当您更改分支时,将更新HEAD以引用新分支分支的最新提交。
所以
HEAD是当前分支的“尖端”。
请注意,我们可以使用HEAD来引用最近的提交,并使用HEAD~作为提示之前的提交,使用HEAD~~或HEAD~2作为更早的提交,依此类推。
HEAD~
HEAD~~
HEAD~2
在阅读了之前的所有答案之后,我仍然想要更清晰。官方git网站http://git-scm.com/blog上的这个博客给了我想要的东西:
Git中的HEAD是当前分支引用的指针,它反过来是您上次提交或签出到工作目录中的最后一次提交的指针。这也意味着它将是您下一次提交的父级。通常最简单的想法是HEAD是上一次提交的快照。
HEAD只是一个特殊的指针,指向您当前所在的本地分支。
从progit书,第3.1 Git分支-果壳中的分支章,在第创建一个新的分支节:
如果创建一个新分支会发生什么?这样做会创建一个新的分支指针供您移动。假设您创建了一个新分支调用测试。您可以使用git分支命令执行此操作: $ git branch testing 这将在您当前正在进行的同一提交处创建一个新指针 Git如何知道你当前在哪个分支上?它保留了一个名为HEAD的特殊指针。请注意,这与您可能习惯的其他VCS中的HEAD概念,例如Subversion或CVS。在Git中,这是指向本地分支的指针你现在在。在这种情况下,你仍然是主人。那个混蛋分支命令只创建了一个新分支-它没有切换到那个分支分支。
如果创建一个新分支会发生什么?这样做会创建一个新的分支指针供您移动。假设您创建了一个新分支调用测试。您可以使用git分支命令执行此操作:
$ git branch testing
这将在您当前正在进行的同一提交处创建一个新指针
Git如何知道你当前在哪个分支上?它保留了一个名为HEAD的特殊指针。请注意,这与您可能习惯的其他VCS中的HEAD概念,例如Subversion或CVS。在Git中,这是指向本地分支的指针你现在在。在这种情况下,你仍然是主人。那个混蛋分支命令只创建了一个新分支-它没有切换到那个分支分支。
head指向当前签出分支的尖端。
在您的存储库中,有一个. git文件夹。在此位置打开文件:. git\refs\head。该文件(大多数情况下为master)中的(sha-1哈希)代码将是最近的提交,即在命令git log的输出中看到的提交。有关. git文件夹的更多信息:http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html
git log
感觉HEAD只是您签出的最后一次提交的标签。
这可以是特定分支的尖端(例如“master”)或分支的一些中间提交(“分离头”)
除了所有的定义之外,困扰我的是,当你进行提交时,GIT会在存储库中创建一个提交对象。提交对象应该有一个父级(如果是合并提交,则应该有多个父级)。现在,git是如何知道当前提交的父级的?所以HEAD是一个指针,指向最后一次提交的(引用),它将成为当前提交的父级。
在这些答案中,有一个也许微妙但重要的误解。我想我应该加上我的答案来澄清它。
什么是HEAD?
HEAD是一个象征性的引用,指向你在提交历史中的任何位置。无论你去哪里,无论你做什么,它都像影子一样跟着你。如果你做了一个提交,HEAD会移动。如果你签出了某个东西,HEAD也会移动。无论你做什么,如果你在提交历史中移动了新的地方,HEAD都会和你一起移动。要解决一个常见的误解:你不能将自己与HEAD分离。分离的HEAD状态不是这样的。如果你发现自己在想:“哦,不,我处于分离的HEAD状态!我失去了我的HEAD!”记住,这是你的HEAD。HEAD就是你。你没有脱离头脑,你和你的头脑已经脱离了别的东西。
HEAD可以指向提交,是的,但通常不会。让我再说一遍。通常#0不指向提交。它指向一个分支引用。它是该分支的附,当你做某些事情(例如,commit或#3)时,附加的分支将与HEAD一起移动。你可以通过查看引擎盖下看到它指向的内容。
commit
通常你会得到这样的东西:
ref: refs/heads/master
有时你会得到这样的东西:
a3c485d9688e3c6bc14b06ca1529f0e78edd3f86
这就是HEAD直接指向提交时发生的情况。这称为分离的HEAD,因为HEAD指向的不是分支引用。如果您在此状态下进行提交,不再附加到HEAD的master将不再与您一起移动。无论提交在哪里。您可以与主分支处于同一提交状态,但如果#0指向提交而不是分支,则它将被分离,并且新提交不会与分支引用相关联。
master
如果您尝试以下练习,您可以以图形方式查看此内容。从git存储库中,运行此操作。您会得到一些略有不同的东西,但它们的键位将在那里。当需要直接签出提交时,只需使用您从第一个输出中获得的任何缩写哈希(这里是a3c485d)。
a3c485d
git checkout mastergit 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仍然引用与分支名称关联的特定修订。我们仍然是0号主分支,不是吗?
现在试试:
git status# HEAD detached at a3c485d
不。我们处于分离头状态。
您可以看到(HEAD -> branch)与git log -1的相同表示。
(HEAD -> branch)
git log -1
HEAD就是你。它指向你签出的任何内容,无论你在哪里。通常这不是一个提交,它是一个分支。如果HEAD确实指向一个提交(或标签),即使它与分支也指向相同的提交(或标签),你(和HEAD)已经与该分支分离。由于你没有附加分支,当你进行新提交时,分支不会跟随你。然而,HEAD会。
A分支实际上是一个保存提交ID的指针,例如17a5。HEAD是指向用户当前正在处理的分支的指针。
HEAD有一个参考文件,如下所示:
参考:
您可以通过访问您正在使用的存储库中的.git/HEAD.git/refs来检查这些文件。
.git/HEAD
.git/refs
Git是关于提交的。Head指向您当前签出的提交。
Git
Head
$ git cat-file -t HEADcommit
每当签出分支时,HEAD都会指向该分支上的最新提交。HEAD的内容可以检查如下(对于主分支):
$ cat .git/refs/heads/masterb089141cc8a7d89d606b2f7c15bfdc48640a8e25
HEAD实际上只是一个用于存储当前分支信息的文件
如果您在git命令中使用HEAD,则指向当前分支
您可以通过以下方式查看此文件的数据cat .git/HEAD
我还在弄清楚git的内部结构,到目前为止已经弄清楚了这一点:
假设当前分支是大师。
% cat .git/HEADref: refs/heads/master
% cat .git/refs/heads/masterf342e66eb1158247a98d74152a1b91543ece31b4
% git log --onelinef342e66 (HEAD -> master,...) latest commitfa99692 parent of latest commit
所以我的想法是HEAD文件是跟踪最新提交的便捷方式,而不是记住长哈希值。
HEAD是指向当前签出的分支或提交的指针,它回答了以下问题:我现在在存储库的哪里?或者,换句话说,它是Git知道在哪个提交上镜像您的本地工作树的方式,以及您当前是否正在处理分支(附)或不(分离)。
HEAD可以处于两种状态之一,<强>附着强>或<强>分离强>,具体取决于您是否签出了分支。默认状态为附,其中对历史记录的任何操作都会自动记录到HEAD当前引用的分支。
在分离状态下,可以在不影响任何现有分支的情况下进行实验性更改。请参阅下面的信息图,其中说明了连接状态与分离状态下的犯下之间的差异。
一个常见的误解是消息您处于“分离头”状态的语气是错误的,而实际上它只是描述了HEAD如何引用当前快照。
操作可以使HEAD处于分离状态:
$ git checkout 14ko3
$ git checkout origin/master
$ git switch master --detached
$ git checkout v1.0.1
从分离状态移动到附加状态
要从分离状态移动到附加状态,您可以从您所在的位置创建一个新分支,或者切换回现有分支。
备注:如果您切换到另一个现有分支,在分离状态下创建的任何提交最终都会被丢弃(后垃圾回收机制),而不会首先在新分支中持久化您的更改。
弄清楚HEAD当前处于哪个状态可以通过不同的方式完成,这里有两个选项。
show
$ git show HEAD --oneline14ko3 (HEAD, master) C1 # If attached, the output would have been14ko3 (HEAD -> master) C1
status
$ git statusHEAD detached at 14ko3
如果您想显式查看HEAD引用的内容,您可以随时检查.git/HEAD文件,这是Git在内部用于管理HEAD的实际文件。该文件包含分支或提交哈希的名称,具体取决于HEAD是否分离。
$ cat .git/HEADref: refs/heads/master # If detached, the output would have been14ko36e295f1a98ec57397b3acc7bc247da61ff5
来源:以上摘录来自这个主题的全长帖子:什么是Git中的HEAD?
存储库中可以有多个头。并且头的总数始终等于存储库中存在的分支总数,这意味着头只是每个分支的最新提交
但是对于一个repository.HEAD只有一个HEAD是引用在当前分支完成的最新提交的引用。
无论HEAD引用哪个提交,存储库都会开始反映存储库在该特定提交期间的条件。
HEAD的基本性质是总是引用当前分支的最新提交,但我们可以通过使用git签出“提交哈希”将HEAD移动到当前分支的任何提交
注意:我们可以很容易地使用命令git log--oneline来获取提交哈希
HEAD几乎是分支的头部。所以当你观察一个分支时,你看到的是最新的提交,也就是这个分支的头部。但是,你可以指出自己正在查看该分支历史上更远的另一个提交,当你这样做时,你将HEAD移动到以前的提交。由于HEAD自然属于分支中的最新提交,它被认为是分离的。
可视化表示。每个分支都是一条毛毛虫,每个提交都是该生物的一部分。因此HEAD将位于最前面的部分。如果您将HEAD从该部分移至另一个要使用的部分,则您已经将头部从自然部分分离。希望它有任何意义。
现在,如果您在主分支中分离HEAD,然后签出newFeature,并再次签出main,HEAD仍将被分离,并在另一个提交之上。我认为HEAD是一面镜子,你可以指向你想要的地方。