你看到Git文档说的是
The branch must be fully merged in HEAD.
号
但Git-HEAD到底是什么?
- 另请参见stackoverflow.com/questions/964876/head和orig head in git‌&8203;/…
你可以把头部想象成"当前的分支"。当使用git checkout切换分支时,头部修订将更改为指向新分支的尖端。
您可以通过执行以下操作看到head指向什么:
在我的例子中,输出是:
1 2
| $ cat .git/HEAD
ref: refs/heads/master |
号
head可以引用与分支名称无关的特定修订。这种情况被称为分离式头部。
- 所以Git Head的上下文取决于你所在的分支,对吗?更进一步,你是一个开发者?我想我在问,Git Head将是一个存储库范围内的全局事物,还是每个开发人员的个体?
- @波波波波:没错,head就像一个指向当前分支的指针。当您签出一个不同的分支时,head将更改为指向新的分支。当前的头对于每个存储库是本地的,因此对于每个开发人员是单独的。
- 因此,这也应该解释为什么当一个人将修订推送到一个远程"中央"存储库时,由于没有签出的工作副本,所以没有头部,他通常会将本地存储库的头部推送到远程存储库的主分支,对吗?
- 我觉得在这条线索中解释的想法可以用某种图表来更好地说明…有人吗?
- @孟这个帮了我,希望能帮上忙:marklodato.github.com/visual-git-guide/index-en.html
- 除了HEAD是当前分支外,它必须是当前分支中的最后一个提交吗?
- @运动能量:头部可以指向任何提交,不需要是任何分支中的最后一次提交。(当head指向的提交不是分支中的最后一个提交时,它是一个"分离的head")。
- @Greghewgill应该更新这个问题,说"你可以把头部看作‘当前提交’",而不是"当前分支"。当我发现在一个有许多提交的交互式REBASE中,Git更新了HEAD,但没有更新分支(由git reset --hard branchname证明)时,我感到困惑。它还解释了为什么git reflog HEAD显示了包含许多提交的REBASE期间的所有步骤,而git reflog branchname只显示了一个REBASE提交。
- git head是指向给定提交的指针,与分支名称一样,唯一的区别是,虽然分支名称在概念上是指向分支中的最新提交,但是可以使用一个head在同一分支内或跨分支的提交之间跳转。您还可以尝试将head可视化为鼠标指针,以便选择要签出的提交。
- head不是"当前分支"。是为从中初始化工作树当前状态的提交指定的名称。在更实际的术语中,它可以被认为是对签出提交的符号引用。
- @本柯林斯谢谢你。不幸的是,接受的回答(上面)给出了错误的答案。
- @Bencollins引用了Git分支的话——分支是什么,关于HEAD:"在Git中,这是指向您当前所在的本地分支的指针。"此外,请注意分支本身只是一个指针。引用同一个来源的话:"Git中的一个分支只是一个指向[commit]的轻量级可移动指针。(…)Git中的一个分支实际上是一个简单的文件,它包含了提交它指向的40个字符的sha-1校验和。"所以我认为接受的答案是好的。你的也是。区别在哪里?
- @不同的是,一个人根本不必在一个分支机构工作。工作副本可以来自任何提交,不管您在哪个分支,在这种情况下,您将是一个独立的头。
- @本柯林斯我同意,超人是一个特殊的案例,但这个案例也在接受的答案中提到。我的观点是,公认的答案是完全正确的。:)
- 投票否决。我同意@Bencollins。在我看来,第一句话相当令人困惑,可以改为:"你可以把头部看作当前分支的当前提交。"
- @达尔瓦雷兹马蒂内兹-当然。也投了反对票。Git非常复杂,可以接受一些错误的答案。
- @dalvarezmartinez1:如果分支是对任意提交的指针/符号引用,那么"您可以将头部视为当前分支上的当前提交"有什么意义?你在用"分支"这个词来形容其他风投吗?
- @donhatch"假设一个分支是对任意提交的指针/符号引用",嗯,我想说,至少对我来说,就我的理解而言,一个分支是一个提交集合,一个提交数组更有意义。然后你有一个指向这个数组的指针,一个名字,还有更多的东西,这会产生一个分支。然后,您可以使用指向当前提交的头指针,在当前分支上在不同提交之间浏览此数组(读取此分支)(使用签出将其向后移动,使用提交将其向前移动sha1)
- @dalvarezmartinez1:你说的每一句话对我来说都是有意义的,但它是其他VCS使用的术语;Git不这么认为,在Git术语中,"分支"并不意味着你列出的所有有意义的东西;它只是指对提交的引用。我希望Git能以你描述的明智的方式思考——以我的经验来看,Git基本上不可能检查你所说的一系列提交——它只是不记得这些信息。对我来说,这是Git的一个严重失败。
- @Donhatch,也许你应该学会更好地使用git log的选项。您确实可以查看任何给定提交的所有父提交和父提交,并且筛选这些数据以获得所需内容的选项在极端情况下非常强大。
- @通配符-很高兴您对它这么满意,但是尽管您所说的极端特性非常强大,但它缺乏基本信息,我和许多其他人都认为这是必不可少的。请看这一页上著名的图表:nvie.com/posts/a-successful-git-branching-model。这种风格通常被称为"泳道"。你能从吉特那里得到这样一张图纸吗?你当然不能,网上有很多关于这个事实的讨论。仅凭这个事实,许多来自演艺背景的人很难将git视为一个严肃的选择。
- @Donhatch,我认为"Git流"看起来像一个很好的分支模型,直到我读到"Git流被认为是有害的"和后续文章。我个人觉得这个工作流程更可行。
- @通配符-感谢您提供指针。很明显,我不是有意提倡Gitflow(我想这就是本文中讨论的模型);我没有太仔细地研究过它,也没有考虑过其他的选择。但我绝对是一个拥有健壮泳道的图表爱好者,其中的图表在那篇文章中是一个很好的例子,与文章的观点无关。不管是否使用GitFlow,你都不能用通常在Git中的信息来制作这样的图表。
- 修订是否提交?
- 除master外,这是显而易见的。你能解释一下ref: refs/heads/master指的是什么吗?我们有多个脑袋吗?
- 您可以使用git symbolic-ref --short HEAD输出分支头指向的分支头,这对于确认您是否处于分离头状态非常有用。
- @Bencollins re HEAD不是当前的分支,它是对签出提交的符号引用:事实上,它通常都不是。它是对您签出的任何内容的象征性引用。如果是提交,是的,它指向提交,但通常不是。类似地,op、HEAD可以引用与分支名称关联但仍被分离的提交。HEAD只在它不指向提交,而是指向分支时附加。看看我的答案
- 把它敲回家:greg(op),回复:"(当head指向一个分支中不是最后一个commit的commit时,它是一个"分离的head")。"不。如果HEAD直接指向一个commit,那么不管它是什么commit(即使它是分支中的最后一个commit),它都是分离的。
- @Bencollins"[head]是从中初始化工作树当前状态的提交的名称。"不一定。这是典型的事实,但并非总是如此。例如,在git reset --soft 之后,head可以指向完全不同的快照,但不会更改工作树的状态。或者在git commit之后,更准确地说头部提交是从工作树的当前状态(间接)初始化的,而不是相反。
引用他人:
A head is simply a reference to a
commit object. Each head has a name
(branch name or tag name, etc). By
default, there is a head in every
repository called master. A repository
can contain any number of heads. At
any given time, one head is selected
as the"current head." This head is
aliased to HEAD, always in capitals".
Note this difference: a"head"
(lowercase) refers to any one of the
named heads in the repository;"HEAD"
(uppercase) refers exclusively to the
currently active head. This
distinction is used frequently in Git
documentation.
号
这里可以找到另一个很好的资源,它可以快速地覆盖git的内部工作(从而更好地理解头/头)。引用(ref:)或头或分支可以被视为提交历史记录中粘在提交上的post-it注释。通常,它们指向一系列提交的尖端,但它们可以与git checkout或git reset等一起移动。
- 由此可知:"每个人头都有一个名字"。"一个头部被选为"当前头部",这个头部被称为头部"。所以我的结论是,"头"不是指"分离头"状态的情况。
- @GXYD如果头部没有指向"头部",则是分离的头部。它指向您指定的提交的提交ID(例如,使用git checkout HEAD~2),这不是已知头的提交ID。请参阅eagain.net/articles/git-for-computer-scientists上的文章,了解更详细的解释。
- @Silfheed:一般来说,我认为这个答案在概念上比公认的答案更合理(尽管使用小写"head"来指分支会让很多人困惑)。然而,git revert并不是将分支移动到不在尖端的一个好例子,因为git revert只是创建了一些新的提交,仍然将当前分支留在(新的)尖端。
- "这不是已知头的提交ID"-实际上,分离的头可以指向一个提交ID,该ID也是已知头(或多个头)的提交ID。使其分离的是头部直接指向提交ID,而不是头部。这将影响未来的commits、resets等的行为。
- @拉什:在一个分离的头上,指向提交ID而不是引用是一个很好的观点。你可以通过查看.git/head来验证这一点。如果分离了它,它将包含提交的散列,即使它与已知头是同一个提交。如果它是附加的,它将包含指向头部的路径(即"refs:refs/heads/bob")。至于revert命令,8年后我从来没有发现过这种错误。Git重置允许您调整特定的头以指向特定的提交。
- 这个答案对于注意头部和头部之间的区别很有用,但是我发现它有点令人困惑。HEAD只是对将要创建的下一个提交的父级提交的引用。
我建议Github开发者Scott Chacon[视频参考]:
Head is your current branch. It is a symbolic reference. It is a reference to a branch. You always have HEAD, but HEAD will be pointing to one of these other pointers, to one of the branches that you're on. It is the parent of your next commit. It is what should be what was last checked-out into your working directory... This is the last known state of what your working directory was.
号
整个视频将公平地介绍整个Git系统,因此我也建议您在有时间的情况下观看所有内容。
- 所以真正的定义是"下一次提交的父对象"
- 以及"指向将要移动的下一个分支的事物"
- @尼古拉斯-我不认为那是真的。head可以指向任何提交,它不必指向分支——如果不指向分支,则处于"分离head"模式。
- 它确实可以指向任何提交,但这并不能定义它是什么。阿法克在一月写的是它的定义
- 视频很棒,但不幸的是,它对堆栈溢出给出了不合适的答案。如果视频将来某个时候被拍摄下来怎么办?那么你的链接就不会指向任何东西。一个更好的答案将包括一份斯科特在视频中所说的文字记录。
- 斯科特说head是指向一个分支的指针。但Head也可以指出旧的承诺。这太令人困惑了。
- 很高兴看到参考资料,但答案在你的答案中找不到。P
- 为什么github开发人员会成为git相关问题/问题的相关来源?你肯定没把他们两个搞混吧?Git是由Linus Torvalds创建的,程序本身不同于提供在线存储库存储服务的平台,如github、bitbucket或gitlab。此外,必须遵循视频流而不是阅读句子更为乏味-不是最佳的。
head只是一个特殊的指针,指向您当前所在的本地分支。
从pro-git手册的第3.1章git分支-简而言之,在创建新分支一节中:
What happens if you create a new branch? Well, doing so creates a new
pointer for you to move around. Let’s say you create a new branch
called testing. You do this with the git branch command:
This creates a new pointer at the same commit you’re currently on
How does Git know what branch you’re currently on? It keeps a special pointer called HEAD. Note that this is a lot different than
the concept of HEAD in other VCSs you may be used to, such as
Subversion or CVS. In Git, this is a pointer to the local branch
you’re currently on. In this case, you’re still on master. The git
branch command only created a new branch — it didn’t switch to that
branch.
号
- 很好,不过可以用一张照片来显示拆下的头罩
- @Donhatch,分离头StackOverflow.com/a/35301963/1074179的良好解释
- 回答得很好。分支只标记为提交,当您进行新提交时,此标签将移动到新提交。当签出没有标签的提交时,它处于分离头状态。这意味着head指向的提交没有分支标签。如果您在上面的示例中签出34ac2,那么head将指向该commit,它被称为独立head。在这种状态下,您也可以进行更改、试验和提交更改,但是一旦签出另一个分支,您将丢失所有更改,除非您当然创建了一个新的分支。
假设这不是一个称为"分离头"的特殊情况,那么,正如O'Reilly Git书第二版第69页所述,HEAD意味着:
HEAD always refers to the most recent commit on the current
branch. When you change branches, HEAD is updated to refer to the new
branch’s latest commit.
号
所以
HEAD is the"tip" of the current branch.
号
请注意,我们可以使用HEAD来指代最新的提交,使用HEAD~作为TIP之前的提交,使用HEAD~~或HEAD~2作为甚至更早的提交,等等。
HEAD是指您的工作副本指向的当前提交,即您当前已签出的提交。从有关指定git修订版的官方Linux内核文档中:
HEAD names the commit on which you based the changes in the working tree.
号
然而,请注意,在即将到来的Git 1.8.4版本中,正如Git贡献者Junio C Hamano在其Git责备博客中指出的那样,@也可以用作HEAD的简写:
Instead of typing"HEAD", you can say"@" instead, e.g."git log @".
号
堆栈溢出用户vonc还发现了一些有趣的信息,说明为什么在回答另一个问题时选择@作为速记。
另外,在某些环境中,不需要大写HEAD,特别是在使用不区分大小写文件系统的操作系统中,特别是Windows和OS X。
看看创建和使用分支
head实际上是一个文件,其内容决定head变量引用的位置:
1 2 3 4
| $ cat .git/HEAD
ref: refs/heads/master
$ cat .git/refs/heads/master
35ede5c916f88d8ba5a9dd6afd69fcaf773f70ed |
在此存储库中,头文件的内容引用名为refs/heads/master的第二个文件。文件refs/heads/master包含主分支上最近提交的哈希。
结果是从.git/refs/heads/master文件指向主分支提交。
。
- 小心:gitguys.com链接似乎指向一个停放的域。
我只想在格雷格·休吉尔接受的回答中详细说明一些事情。根据Git袖珍指南
分支机构:
the branch itself is defined as all points reachable in the commit
graph from the named commit (the"tip" of the branch).
号
头部:特殊类型的参考
The special ref HEAD determines what branch you are on...
号
参考文献
Git defines two kinds of references, or named pointers, which it calls
"refs":
-
A simple ref, which points directly to an object ID (usually a commit or tag)
-
A symbolic ref (or symref), which points to another ref (either simple or symbolic)
号
正如格雷格所说,头部可以处于"分离状态"。所以head可以是简单的ref(对于分离的head)或symref。
if HEAD is a symbolic ref for an existing branch, then you are"on"
that branch. If, on the other hand, HEAD is a simple ref directly
naming a commit by its SHA-1 ID, then you are not"on" any branch, but
rather in"detached HEAD" mode, which happens when you check out some
earlier commit to examine.
号
- 谢谢你,@mike!这是第一个澄清当您签出早期提交时会发生什么的答案。看了看Git网站上的书,我觉得"超脱的脑袋"是一种病态的状态,只有当你做了一些奇怪的重新平衡的事情。但是检查一个早期的提交并不是一件奇怪的事情,当你这样做的时候,head并不是"当前分支的尖端",所以这是我第一次感觉到我真的明白了。
在这些答案中,有一些可能是微妙但重要的误解。我想我应该加上我的答案来澄清它。
What is HEAD?
号头是你
HEAD是一个符号引用,指向提交历史中的任何位置。无论你走到哪里,无论你做什么,它都像影子一样跟随着你。如果你做出承诺,HEAD将会移动。如果你结账,HEAD就会移动。无论您做什么,如果您在提交历史中移动了一个新的地方,那么HEAD将与您一起移动。为了解决一个常见的误解:你不能脱离HEAD。这不是一个分离的头部状态。如果你发现自己在想:"哦,不,我处于超然状态!我疯了!"记住,这是你的头。头就是你。你没有脱离你的头,你和你的头已经脱离了别的东西。
头部可以连接到什么?
HEAD可以指向提交,是的,但通常不会。我再说一遍。通常情况下,HEAD并不指向提交。它指向一个分支引用。它与该分支相连,当您执行某些操作(例如,commit或reset时,所连接的分支将与HEAD一起移动。你可以从引擎盖下面看到它指向什么。
通常你会得到这样的结果:
号
有时你会得到这样的东西:
1
| a3c485d9688e3c6bc14b06ca1529f0e78edd3f86 |
当HEAD直接指向一个commit时,就会发生这种情况。这被称为分离头,因为HEAD指向的不是分支引用。如果你在这种状态下作出承诺,那么不再依附于HEAD的master将不再与你一起移动。在哪里提交并不重要。您可以与主分支处于同一提交状态,但如果HEAD指向的是提交而不是分支,则它是分离的,并且新提交不会与分支引用关联。
如果您尝试下面的练习,您可以以图形方式查看这个问题。从Git存储库中运行这个。你会得到一些稍微不同的东西,但它们的关键部分会在那里。当需要直接签出提交时,只需使用从第一个输出中得到的任何缩写散列(这里是a3c485d)。
1 2 3 4 5 6 7
| 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仍指与分支名称关联的特定修订。我们还在总分部,是吗?
现在试试:
1 2
| git status
# HEAD detached at a3c485d |
不。我们处于"超然状态"。
您可以看到与git log -1相同的(HEAD -> branch)与(HEAD, branch)的表示。
总结
HEAD是你。它指的是无论你在哪里结帐。通常这不是提交,而是分支。如果HEAD确实指向commit(或tag),即使分支也指向相同的commit(或tag),您(和HEAD已经从该分支分离。由于您没有分支连接到您,因此在您作出新的提交时,分支不会跟随您。但是,HEAD会的。
我认为"head"是当前的签出提交。换句话说,"head"指向当前签出的提交。
如果您刚刚克隆了,但没有签出,我不知道它指向什么,可能是某个无效的位置。
- 是的,特别参考文件HEAD是您当前已签出的任何承诺。详见说明书(相关段落见图3.4)。
- 如果克隆一个存储库,Git将默认签出master分支,因此head将指向master。
- @SLESKE如果克隆一个没有特殊选项的存储库,Git将签出远程头。它通常是master,但并不总是。见remote set-head。
- 我之前的评论是正确的,除了引用remote set-head,它只影响本地默认分支,不会更改服务器上的默认值。
head指向当前签出分支的尖端。
。
在您的存储库中,有一个.git文件夹。在此位置打开文件:.git
efsheads。该文件中的(sha-1 hash)代码(大多数情况下是master)是最新的提交,即在命令git log的输出中看到的代码。有关.git文件夹的详细信息:http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html
- 当前分支的尖端指向最近的提交,这是一个常见的误解。一般来说,这是正确的,但对git reset HEAD^来说,这也并不少见,然后分支尖端不再指向最近的提交(前一个尖端)。
在阅读了所有之前的答案之后,我仍然想要更清晰的答案。在Git官方网站http://git-scm.com/blog上的这个博客给了我想要的东西:
head:指向上一个提交快照的指针,下一个父级
The HEAD in Git is the pointer to the current branch reference, which is in turn a pointer to the last commit you made or the last commit that was checked out into your working directory. That also means it will be the parent of the next commit you do. It's generally simplest to think of it as HEAD is the snapshot of your last commit.
号
- head:last commit snapshot,next parent不准确。HEAD不是commit,它指向一个commit。
- 没有必要讽刺;在你编辑之前,即使引用是准确的,大的粗体字是一个简化和有点误导。现在,更好了。
- 如果您阅读下一行:git中的head是指向当前分支引用的指针,而当前分支引用又是指向您最后一次提交或签出到工作目录中的最后一次提交的指针。--请注意"指针"一词的用法。
- 虽然"最后一次提交快照"的描述确实给出了头部通常应该如何使用的概念上的感觉,但它确实不准确。如果我提交,然后切换到另一个分支,head将不再指向最后一个提交快照。它指向我刚切换到的分支上的最后一个提交快照。如果我是checkout HEAD^,现在head甚至不指向任何分支上的最后一个提交快照。
- "下一次提交的父级(如果您现在要提交的话)"更准确,但是在Git中除了提交之外还有许多其他操作受到head的影响。实际上,在最后,head是head,它的性质是由它如何影响诸如commit、merge、rebase、log等命令来定义的,但从概念上讲,"指向当前位置的指针"是一个很好的总结。
开车回家的一个好方法是跑git reflog HEAD,你可以了解到头所指的所有地方的历史。
感觉好像HEAD只是您签出的最后一个提交的标记。
这可以是特定分支(如"master")的提示,也可以是分支提交之间的某些提示("分离的头")。
看看http://git-scm.com/book/en/git-branching-what-a-branch-is
Figure 3-5. HEAD file pointing to the branch you’re on.
号
- 在StackOverflow上,通常不支持仅链接的答案,请在您的答案中插入相关信息。
- 这不完全正确。HEAD指的是什么,取决于你所说的是"裸回购"还是"非裸回购"。在非裸回购的情况下,它实际上是指当前已签出的承诺,不要求有分支连接到它(即,当处于分离HEAD状态时)。
除了所有的定义之外,我一直在想的是,当您提交时,Git会在存储库中创建一个提交对象。提交对象应该有一个父对象(如果是合并提交,则应该有多个父对象)。现在,Git如何知道当前提交的父级?所以head是指向(引用)最后一次提交的指针,它将成为当前提交的父级。
这两个可能会让你困惑:
头
指向最近提交的分支的命名引用。除非使用包引用,否则头通常存储在$git_dir/refs/heads/中。
头
当前的分支,或者您的工作树通常是由指向的树头生成的。头部必须指向头部,除非使用分离的头部。
作为一个概念,head是分支中的最新版本。如果每个命名分支有多个头部,那么在执行本地提交而不合并时,可能会创建它,从而有效地创建一个未命名分支。
要拥有一个"干净"的存储库,每个命名分支应该有一个头部,并且在本地工作后总是合并到一个命名分支。
这也适用于Mercurial。