2023-04-02 05:00:03

Git中的HEAD是什么?

您可以看到Git文档中这样说

分支必须在HEAD中完全合并。

但Git HEAD到底是什么?


当前回答

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: $ git branch testing 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.

其他回答

看一下如何创建和使用分支

HEAD实际上是一个文件,其内容决定了HEAD变量的引用位置:

$ cat .git/HEAD
ref: refs/heads/master
$ cat .git/refs/heads/master
35ede5c916f88d8ba5a9dd6afd69fcaf773f70ed

在这个存储库中,HEAD文件的内容引用了名为refs/heads/master的第二个文件。文件refs/heads/master包含主分支上最近提交的哈希值。

结果是HEAD指向主分支提交从.git/refs/heads/master文件。

分支实际上是一个持有提交ID(例如17a5)的指针。 HEAD是指向用户当前工作的分支的指针。

HEAD有一个如下所示的引用流:

ref:

您可以通过访问您正在工作的存储库中的.git/HEAD .git/refs来检查这些文件。

作为一个概念,头是分支中的最新修订。如果每个命名分支有多个头,那么在进行本地提交时可能会创建它,而没有合并,这实际上创建了一个未命名的分支。

为了拥有一个“干净的”存储库,每个命名分支都应该有一个头,并且在本地工作后总是合并到一个命名分支。

Mercurial也是如此。

为了理解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指向当前分支'。

看看http://git-scm.com/book/en/Git-Branching-What-a-Branch-Is

图3 - 5。HEAD文件指向你所在的分支。