在最后一次提交、HEAD和我在目录中看到的文件状态之间似乎存在差异。

什么是HEAD,我可以用它做什么,我应该避免什么错误?


HEAD是对当前签出分支中最后一次提交的引用。


有一个小小的例外,那就是分离的HEAD。当您签出一个提交(或标记)而不是一个分支时,就会出现分离HEAD。在这种情况下,您必须将其想象为一个没有名称的临时分支;所以我们没有命名分支引用,我们只有HEAD。它仍然允许您进行提交(这将更新HEAD),因此如果您将分离的HEAD视为没有名称的临时分支,那么上面的简短定义仍然是正确的。


HEAD是当前检出提交的引用。

在正常情况下,它实际上是对你签出的分支的符号引用——如果你查看.git/HEAD的内容,你会看到类似于“ref: refs/heads/master”的东西。分支本身是对分支顶端提交的引用。因此,在正常状态下,HEAD实际上指的是当前分支顶端的提交。

也有可能有一个“分离的头”。当签出(本地)分支以外的东西时,就会发生这种情况,比如远程分支、特定的提交或标记。最常看到这种情况的地方是在交互式rebase期间,当您选择编辑提交时。在分离HEAD状态下,你的HEAD是对提交的直接引用- .git/HEAD的内容将是一个SHA1哈希。

一般来说,HEAD只是一个方便的名字,意思是“您已检出的内容”,您实际上不必太担心它。只需要注意你签出了什么,并记住如果你不在分支上(分离HEAD状态),你可能不想提交,除非你知道你在做什么(例如,在一个交互式的rebase中)。


Git中的HEAD指针

Git维护了一个名为HEAD的引用变量。我们称这个变量为指针,因为它的目的是引用或指向存储库中的特定提交。当我们进行新的提交时,指针将改变或移动到指向新的提交。HEAD总是指向存储库中当前分支的顶端。现在,这与我们的存储库有关,而不是staging索引或工作目录。

另一种理解它的方式是存储库的最后状态或最后签出的内容,因为它是存储库离开的地方或最后的状态,所以您也可以说HEAD指向下一次提交的父节点,或者它是提交写入将要发生的地方。

我认为一个很好的比喻是盒式磁带录音机的回放和记录磁头。当我们开始录制音频时,磁带会经过磁头,然后记录到磁头上。当我们按下“停止”键时,记录头停止的地方就是我们第二次按下“记录”键时它将再次开始录制的地方。现在我们可以移动,我们可以将磁头移动到不同的地方,但是当我们再次点击录制时,无论磁头在哪里它都会开始录制。

Git中的HEAD指针非常类似,它指向我们接下来要开始记录的地方。它是我们在存储库中停止提交的东西的地方。


从文档;HEAD的作用是:

Tree Role
Header Last commit snapshot, next [future] parent
Index Proposed next commit snapshot
Working Directory Sandbox

HEAD是指向当前分支引用的指针,而当前分支引用又是指向该分支上最后一次提交的指针。 这意味着HEAD将是创建的下一个提交的父节点。通常最简单的方法是将HEAD看作您在该分支上最后一次提交的快照。


我一直认为HEAD~5意味着要进行5次提交。但是它不携带命令的GO部分。它只包含命令的引用部分。

您可以使用该引用做什么,取决于您选择的命令

通俗地说,它用来回答这样的问题:我应该去哪里?向哪个提交?

HEAD表示当前提交(引用) HEAD~1表示(引用)1提交之前 HEAD~ ALSO表示(引用)1提交之前 HEAD~87表示之前提交了87次 头~ 3 . .HEAD表示从3次提交到当前提交(总共3次提交)


用法:

git checkout HEAD~1 will actually GO/checkout to 1 commit/reference before git reset HEAD~3 will uncommit your last 3 commits — without removing the changes, ie you can see all the changes made in the last 3 commits together, remove anything you don't like or add onto it and then commit them all again. git reset --hard HEAD~3 will uncommit your last commit and remove their changes. It will completely remove those changes. For more see here. git diff HEAD~3 to look into the changes of the last 3 commits git diff someFile HEAD~3 to look into the last 3 changes of a specific file git revert --no-commit HEAD~3..HEAD. Reverts 3 commits, without automatically commiting i.e. you have to do git commit -m yourself. For more see here git rev-parse HEAD~2 outputs the SHA of two commit before. See all changes between a pull request and main. It's a multi-step process.

git fetch origin/feature22
git checkout feature22
git merge-base feature22 main # will return the SHA of their 050dc022f3a65bdc78d97e2b1ac9b595a924c3f2
git reset 050dc022f3a65bdc78d97e2b1ac9b595a924c3f2

你可以只做git重置main,但这只有当你的同事创建了拉请求有最新的改变main。如果他们正在开发一个大功能(并且已经好几天没有与main合并了),而你只是想看看他们在最后一次从main中提取后添加了什么,那么你必须遵循上面的步骤。


还要确保你看到了“什么是分离HEAD”的答案。

它有一些关于cat .git/HEAD的好信息


超出范围,但超级有趣:

除了HEAD,还有其他类型的HEAD。参见git修订:

ORIG_HEAD

ORIG_HEAD是由以剧烈的方式移动HEAD的命令创建的,以记录HEAD在操作之前的位置,这样您就可以轻松地将分支的尖端更改回运行它们之前的状态

撤销git合并

git reset --hard ORIG_HEAD

MERGE_HEAD

在结束现有合并之前尝试再次合并后,我收到此错误消息

fatal:你还没有结束你的合并(MERGE_HEAD存在)。 请在合并之前提交您的更改。

为了解决这个问题,我必须结束合并。然后再进行一次合并。

FETCH_HEAD

记录您使用最后一次git获取调用从远程存储库获取的分支

CHERRY_PICK_HEAD

当你运行git cherry-pick时,记录你正在选择的提交。

要了解更多,请参阅其他答案和文档


简单来说,HEAD是当前签出分支中最后一次提交的引用。

将HEAD视为“当前分支”。当您使用git签出切换分支时,HEAD修订将更改为指向新分支的尖端。

你可以通过这样做来查看HEAD指向什么:

cat .git/HEAD

HEAD可以引用与分支名称不关联的特定修订。这种情况被称为分离HEAD。


基本上HEAD是一个指向当前分支中最后一次提交的指针/引用。

您可以使用这两个命令来验证这一点。

$ git log -1

commit 9883e13257f2e7555eb6e3b14b2c814978c75692 (HEAD -> MyLocalBranch)
Author: vikram <vikramguptavit@gmail.com>
Date:   Sun Oct 11 23:32:45 2020 -0400
this is my last commit message

现在使用下面的命令来查看HEAD指向的位置:

$ git rev-parse HEAD
9883e13257f2e7555eb6e3b14b2c814978c75692

可以看到,这两个提交哈希值是相同的。所以HEAD总是指向当前分支中的最新/最后一次提交。