您可以看到Git文档中这样说
分支必须在HEAD中完全合并。
但Git HEAD到底是什么?
您可以看到Git文档中这样说
分支必须在HEAD中完全合并。
但Git HEAD到底是什么?
当前回答
分支实际上是一个持有提交ID(例如17a5)的指针。 HEAD是指向用户当前工作的分支的指针。
HEAD有一个如下所示的引用流:
ref:
您可以通过访问您正在工作的存储库中的.git/HEAD .git/refs来检查这些文件。
其他回答
我自己还没有弄清楚,但Silfheed对“贴在节点上的便利贴”定义的链接是迄今为止我发现的最好的链接。
我想分享一下我对寻找定义的印象,否则我为什么要把它留给自己。 我把它理解为粘在Git树空间当前位置上的贴纸。我错过了这样一个术语——GIT树中的当前位置,它有自己的属性来指示我们所处的位置。
“参考”或“指针”之类的概念我不太清楚。在我看来,它们暗示了一种新的抽象层次,我们从抽象层次的内部来“指”某物。这可能不是真的,但到目前为止,这是我的看法。
为了理解HEAD是什么,让我们使用一个实际的例子,其中有两个不同的分支,main和feature1,来自两个不同的开发人员Dev1和Dev2,他们在同一个项目上工作。
Dev1主分支的案例1:
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
Next1
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
Next2
name~/repo/.git (GIT_DIR!)
$ cat HEAD
ref: refs/heads/main
我们可以清楚地看到HEAD是一个文件,其中一行指向refs/heads目录中的一个名为main的文件(heads是refs目录中的一个目录)。参考Next1步骤定位refs目录
现在让我们转到Next1步骤,cd到refs目录,在heads目录中搜索主文件,看看它包含什么
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分支的案例2
在这里,唯一的区别是在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指向当前分支'。
我还在弄清楚git的内部结构,到目前为止,我已经弄清楚了这个:
假设当前的分支是master。
HEAD是你的.git/目录下的一个文件,通常看起来像这样:
% cat .git/HEAD
ref: refs/heads/master
Refs /heads/master本身是一个文件,通常包含master最新提交的哈希值:
% cat .git/refs/heads/master
f342e66eb1158247a98d74152a1b91543ece31b4
如果你做git日志,你会看到这是master的最新提交:
% git log --oneline
f342e66 (HEAD -> master,...) latest commit
fa99692 parent of latest commit
所以我的想法是HEAD文件是一种跟踪最新提交的方便方法,而不是记住长散列值。
一个存储库中可以有多个头。并且头的总数总是等于存储库中存在的分支的总数,这意味着头只是每个分支的最新提交
但是一个存储库只有一个HEAD。HEAD是一个引用,它引用在当前分支完成的最新提交。
它就像git用户的眼睛。无论HEAD引用哪个提交,存储库都开始反映该特定提交期间存储库的条件。
HEAD的基本性质是总是引用当前分支的最新提交,但我们可以通过使用git checkout "commit-hash"将HEAD移动到当前分支的任何提交。
注意:我们可以使用git log——oneline命令轻松获得commit-hash
假设这不是一种叫做“分离HEAD”的特殊情况,那么,正如O'Reilly Git书第2版第69页所述,HEAD的意思是:
HEAD总是指当前节点上最近的提交 分支。当您更改分支时,HEAD将被更新为引用新的分支 布兰奇的最新提交。
so
HEAD是当前分支的“尖端”。
注意,我们可以使用HEAD表示最近的提交,使用HEAD~表示提示之前的提交,使用HEAD~~或HEAD~2表示更早的提交,以此类推。