What is the HEAD in git?
最后一次提交、头文件和我在目录中看到的文件状态之间似乎存在差异。
头是什么,我能用它做什么?我应该避免什么错误?
- 另请参见stackoverflow.com/questions/964876/head和orig head in git‌&8203;/…
- 从Git v1.8.4开始,下面所有使用HEAD或HEAD的答案现在都可以使用@代替HEAD。请参阅此答案(最后一节),了解您为什么可以这样做。
- 从git scm:git中的head是指向当前分支引用的指针,而当前分支引用又是指向您最后一次提交或签出到工作目录中的最后一次提交的指针。这也意味着它将是您所做的下一次提交的父级。一般来说,最简单的方法是将它看作head,它是最后一次提交的快照。
- 什么是git中head的可能副本?
head是对当前签出分支中最后一次提交的引用。
有一个小的例外,这是分离头。分离的头部是指当您签出提交(或标记)而不是分支时,您最终会遇到的情况。在这种情况下,您必须将其想象为一个没有名称的临时分支;因此,我们只有head,而没有命名的分支引用。它仍然允许您进行提交(这将更新head),因此如果您将分离的head视为没有名称的临时分支,那么上面的简短定义仍然是正确的。
- 为什么你能有两个头?
- @e-satis:因为head是一个您已经签入工作目录的提交,并且由于工作目录一次只能显示一个提交(从中进行一些修改),所以您只能有一个head。
- @e-satis:有时你会看到树枝被称为头——它们被存储在refs/heads中。不过,小写的head与HEAD不同。我的回答澄清了这一点。
- 好的,那么head是什么意思?我用在"重置"中,但不知道为什么。在这里看到任何帮助我的regexp知识。
- @E-satis:那不是regex。^只是git的"commit before"符号,即当前的commit之前的commit。(如果当前是合并,则使用第一个父级。)
- @e-satis:有关指定提交的所有方法的详细信息,请参阅Git版本列表手册页的指定修订部分-这只是一个很小的部分。kernel.org/pub/software/scm/git/docs/…
- 您说"(如果当前是合并,则使用第一个父级。)"为什么会这样?
- 因为合并提交有多个父级,而且只有一个符号。所以他们决定给你现有孩子的第一个家长。但是,您可以使用rev^2获取修订的第二个父级,或者例如,HEAD^3获取头部提交的第三个父级。
- 好啊。合并的第一个父级,是我们合并的父级还是我们合并的父级?如果rev是最高版本,那么rev^2和head^2之间有区别吗?很抱歉让你感到不安:-)我不喜欢和我不明白的事情一起工作。
- 不,当rev和head指向相同的commit时,没有区别。甚至可以编写提交ID(sha-1值),而不是rev或head。别担心,你不会用这些问题来骚扰我们的:(我至少:P)
- 干杯。爱如此。你可以有14K的代表,但仍然是一个noob:-p
- 尽管这是公认的答案,但我不认为总是正确的。如果签出的提交不是当前分支中的最后一次(按时间顺序排列的最新)提交,那么head不是对当前签出分支中最后一次提交的引用。
- @Larsh如果您签出了一个commit,那么您就不再处于分支的上下文中(因为commits不属于分支);您将获得一个独立的head,这意味着head是您当前所在的"临时分支"的唯一引用。我已经在我的答案中添加了这个解释,所以希望能澄清这个问题。
- 这是我第一次听说提交不属于分支。我以为他们有。我去查一下。
- @Larsh分支只是提交的指针,这使得提交和它的所有父级都包含在该分支中。但是提交中没有将它们链接到分支的内容。那个链接只是反向存在的。因此,当您签出一个提交时,您无法判断哪一个分支可能意味着它可能是一个分支,也可能是所有分支,甚至没有分支。
HEAD是对当前签出提交的引用。
在正常状态下,它实际上是对您签出的分支的一个符号引用-如果您查看.git/head的内容,您将看到类似"ref:ref s/heads/master"的内容。分支本身是对分支末端提交的引用。因此,在正常状态下,HEAD实际上是指当前分支尖端的提交。
也可以有一个"分离的头部"。当您签出除(本地)分支之外的某个分支(如远程分支、特定提交或标记)时,就会发生这种情况。最常见的地方是在交互式重新平衡期间,当您选择编辑提交时。在分离头状态下,您的头是对commit的直接引用,.git/head的内容将是sha1散列。
一般来说,head只是一个方便的名字,意思是"你已经签出了什么",你不必为此担心太多。只需知道您签出了什么,并记住,如果您不在分支(分离的头状态)上,您可能不想提交,除非您知道您正在做什么(例如,处于交互的重新平衡中)。
- 这是我不明白的。如果你签出一个远程分支,为什么你最终会得到一个"分离的头"。为什么你不自动跳到你的本地回购中对应于你的远程?
- @e-satis:如果你想要本地的分支机构,可以去当地的分支机构看看。记住,这两者不一定是相同的-您必须告诉本地的一个合并远程的一个(或拉)。跟踪只是为了让它知道当你问的时候自动拉哪一个。它被分离的原因是,远程分支旨在作为指向远程repo中分支最后一次看到的位置的指针。如果您试图提交,远程回购不会改变,因此远程分支也不应该改变。
- 好吧,这是我没有得到的:以某种方式命名一个本地分支并不意味着它与远程分支相同。一开始真的很难理解,因为我来自SVN背景。-)谢谢。顺便问一句,您如何将无头头部移动到本地分支以在此处提交它?
- @e-satis:一般的答案是git rebase HEAD。这将找到和HEAD的最后一个共同祖先,然后将所有从那里向HEAD的承诺都应用到上。它本质上是通过将它们作为补丁应用来实现的,因此如果这两个分支真的不同,就可能存在冲突。但是,如果是HEAD的祖先(即你在正确的位置,只是忘记了你分离了HEAD的话),那么rebase只是一个快速向前的合并。
- 更完整的答案:stackoverflow.com/a/4381549/520567
- @阿科斯塔迪诺夫确实提到了"头"是什么,但至于"头"是什么,我的回答肯定更完整。
- 这是我在搜索了一段时间后看到的关于Git头的最清晰和准确的描述之一。
以Git为单位的指针
Git维护一个名为head的引用变量。我们称这个变量为指针,因为它的目的是引用或指向存储库中的特定提交。当我们进行新提交时,指针将更改或移动以指向新提交。head总是指向存储库中当前分支的尖端。现在,这与我们的存储库有关,而不是我们的临时索引或工作目录。
另一种方法是考虑存储库的最后一个状态或上次签出的内容,因为它是存储库停止的位置或最后一个状态,所以您也可以说头部指向下一次提交的父级,或者说它是进行提交写入的位置。
我觉得一个很好的比喻就是在盒式磁带录音机上播放和录制磁头。当我们开始录制音频时,磁带从磁头上移动,然后记录到磁头上。当我们按下"停止"时,记录头停止的地方就是当我们第二次按下"录制"时,它将再次开始录制的地方。现在我们可以四处移动,我们可以将记录头移动到不同的地方,但是当我们再次按下"录制"时,记录头所在的位置就是开始录制的地方。
Git中的指针非常类似,它指向下一个开始录制的位置。这是我们在存储库中为我们所承诺的事情而放弃的地方。
这应该是一个注释,但对于提交来说太长了
我一直认为HEAD~5意味着之前要进行5次承诺。但它没有执行命令的执行部分。它只携带命令的引用/"Where to"部分。
用外行术语来说,它用来回答这样一个问题:我应该去哪里?向谁承诺?
如果你说
HEAD表示(引用)当前提交
HEAD~1是指(参考)1在
HEAD~87是指(参考)87在
git checkout HEAD~1将实际转到该引用/提交
简单来说,head是对当前签出分支中最后一次提交的引用。
把头部想象成"当前的分支"。使用git checkout切换分支时,头部修订将更改为指向新分支的尖端。
您可以通过执行以下操作看到head指向什么:
head可以引用与分支名称无关的特定修订。这种情况被称为分离式头部。