您可以看到Git文档中说:
分支必须在HEAD中完全合并。
但是Git中的HEAD
究竟是什么?
我只想详细说明Greg Hewgil的回答中的一些内容。根据Git Pocket Guide所述:
分支:
分支本身被定义为从命名提交(分支的“尖端”)在提交图中可达的所有点。
HEAD:一种特殊类型的引用
特殊引用HEAD确定您所在的分支...
引用
Git定义了两种引用或命名指针,称之为“refs”:
- 一个简单的引用,直接指向对象ID(通常是提交或标签)
- 一个符号引用(或symref),指向另一个引用(无论是简单还是符号)
正如Greg所提到的,HEAD可以处于“分离状态”。因此,HEAD可以是一个简单的引用(对于分离的HEAD)或symref。
如果HEAD是现有分支的符号引用,则您“在”该分支上。另一方面,如果HEAD是直接使用其SHA-1 ID命名提交的简单引用,则您不在任何分支上,而是处于“分离的HEAD”模式下,这种情况发生在您检出某个早期提交以进行审查时。我认为“HEAD”是当前的检出提交。换句话说,“HEAD”指向当前已检出的提交。
如果您刚刚克隆而没有检出,我不知道它指向什么,可能是一些无效的位置。
master
分支 - 因此HEAD将指向master。 - sleskemaster
,但并不总是。请参阅remote set-head
。 - De Novoremote set-head
的引用,它只影响本地默认分支,并不会更改服务器上的默认分支。 - De Novogit reflog HEAD
可以获取HEAD指向的所有位置的历史记录,这是加深正确答案观点的好方法。Head指向当前检出分支的末尾。
在您的存储库中,有一个.git文件夹。打开此位置中的文件:.git\refs\heads。该文件中的(sha-1哈希)代码(在大多数情况下为主分支)将是最新的提交,即在命令 git log
的输出中看到的提交。有关.git文件夹的更多信息:http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html
git reset HEAD^
命令将取消指向最近提交的指针,此时分支末尾不再指向原来的最新提交。 - LarsH感觉HEAD
只是你检出的最后一次提交的标签。
这可以是特定分支(如“master”)的末尾,也可以是分支的某个中间提交(“脱离HEAD”)。
HEAD 几乎就是分支的头部。因此,当你观察一个分支时,你正在查看最新的提交,也就是该分支的头部。然而,你可以将自己指向在该分支历史记录中更早的另一个提交,这样做时,你将把 HEAD 移动到先前的提交。由于 HEAD 自然属于分支中的最新提交,所以它被认为是脱离的。
一个视觉表现。每个分支都像毛毛虫一样,每个提交都是这个生物的一部分。因此,HEAD 将位于最前面的那个部分。如果你将 HEAD 从那里移除到另一个部分中使用,你就将头部从自然部分中分离出来了。希望这有任何意义。
现在,如果你在主分支中分离 HEAD,然后检出 newFeature,再次检出主分支,那么 HEAD 仍将是分离的,并位于另一个提交之上。我认为 HEAD 就像是一个可以指向你想要的地方的镜子。
name~/repo (main)
$ ls -al
total 9
drwxr-xr-x 1 AlphaLy 197121 0 Dec 22 15:09 ./
drwxr-xr-x 1 AlphaLy 197121 0 Dec 21 20:35 ../
drwxr-xr-x 1 AlphaLy 197121 0 Dec 22 15:09 .git/
-rw-r--r-- 1 AlphaLy 197121 20 Dec 21 20:35 README.md
-rw-r--r-- 1 AlphaLy 197121 0 Dec 22 15:09 test.txt
下一个1
name~/repo (main)
$ cd .git/
name~/repo/.git (GIT_DIR!)
$ ls
COMMIT_EDITMSG description HEAD index logs/ ORIG_HEAD refs/
config FETCH_HEAD hooks/ info/ objects/ packed-refs
下一个2
name~/repo/.git (GIT_DIR!)
$ cat HEAD
ref: refs/heads/main
我们可以清楚地看到,HEAD是一个文件,其中有一行指向位于refs/heads
目录内的名为main
的文件(heads
是refs
目录内的一个目录)。请参考Next1步骤以定位refs
目录。
现在让我们进入Next1步骤,使用cd
命令进入refs
目录,并在heads
目录中搜索main
文件并查看其内容。
name~/repo/.git (GIT_DIR!)
$ cd refs
name~/repo/.git/refs (GIT_DIR!)
$ ls
heads/ remotes/ tags/
name~/repo/.git/refs/ (GIT_DIR!)
$ cd heads/
name~/repo/.git/refs/heads (GIT_DIR!)
$ ls
main maxi
name~/repo/.git/refs/heads (GIT_DIR!)
$ cat main
8b25d89f3396177416c055ab07ebf778616eecdd
8b25d89f3396177416c055ab07ebf778616eecdd
是当前提交。因此,我们可以说 HEAD 指的是一个名为 main
的文件(始终以当前分支命名),其中包含当前提交(上面的 40 位字符)。因此,HEAD 指的是当前提交。
第二种情况是 Dev2 的 feature1
分支
在这里,唯一的区别将在 Next2 步骤中出现
name~/repo/.git (GIT_DIR!)
$ cat HEAD
ref: refs/heads/feature1
还有以下内容:
name~/repo/.git (GIT_DIR!)
$ cat feature1
03fbf973ac1014085864234010b82393208ebbd6
03fbf973ac1014085864234010b82393208ebbd6
是feature1
分支上的当前提交。因此,这里的HEAD再次指的是一个名为feature1(以当前分支命名)的文件,其中包含当前提交(上述40位字符)。
结论:
HEAD指的是当前提交而不是当前分支。只是恰巧包含该当前提交的文件被命名为当前分支,我们倾向于说“HEAD指的是当前分支”。
在一个仓库中可以有多个HEAD。头的总数始终等于仓库中存在的分支总数,这意味着HEAD只是每个分支的最新提交。
但是一个仓库只有一个HEAD。HEAD是一个引用,它引用了当前分支上最新的提交。
就像Git用户的眼睛一样。无论HEAD引用哪个提交,仓库都开始反映仓库在该特定提交期间的状态。
HEAD的基本特性是始终引用当前分支的最新提交,但我们可以使用git checkout "commit-hash"将HEAD移动到当前分支的任何提交处。
注意:我们可以使用命令git log --oneline轻松获取提交哈希。
Git
是关于提交的。
而 Head
指向你当前检出的提交。
$ git cat-file -t HEAD
commit
$ cat .git/refs/heads/master
b089141cc8a7d89d606b2f7c15bfdc48640a8e25
git ls-remote
),但“HEAD”的定义似乎很难确定。git branch的文档简单地说明HEAD
实际上是“当前分支的末端”。所有的混淆实际上都必须关于分支的定义 - 这是令人惊讶的微妙:我们到底是什么意思“branch”? - Brent Bradburn