看起来最后一次提交(last commit)、HEAD 和我在目录中看到的文件状态之间似乎存在差异。
什么是 HEAD,我能用它做什么,以及应该避免哪些错误?
HEAD指的是当前检出的分支中最近的提交。
这里有一个小例外,那就是"detached HEAD"。当你检出一个提交(或标签),而不是一个分支时,就会出现"detached HEAD"的情况。在这种情况下,你可以将其想象成没有名称的"临时分支";所以我们只有HEAD,而没有命名的分支引用。它仍然允许您进行提交(这将更新HEAD),因此如果您将"detached HEAD"视为没有名称的临时分支,则上述简短的定义仍然是正确的。
refs/heads
中。小写的head与HEAD
不同。我的回答稍微澄清了一下这一点。 - Cascabel^
只是 Git 表示“前一个提交”的符号,指的是当前提交的前一个提交。如果当前提交是一个合并提交,则使用第一个父提交。 - CascabelHEAD
是指当前检查出来的提交的引用(reference)。
在正常状态下,它实际上是对你所检出的分支的符号引用 - 如果你查看 .git/HEAD 的内容,你会看到类似于 "ref: refs/heads/master" 的东西。分支本身是对分支末端的提交的引用。因此,在正常状态下,HEAD
实际上是指当前分支末端的提交。
也可能存在“分离的 HEAD” 的情况。这发生在你检出的不是(本地)分支,比如远程分支、特定的提交或标签时。最常见的情况是交互式 rebase 过程中,当你选择编辑提交的时候。在分离的 HEAD 状态下,你的 HEAD 直接引用一个提交 - .git/HEAD 的内容将是 SHA1 值。
一般来说,HEAD 只是一个方便的名称,表示“你已经检出的内容”,你并不需要太过担心它。只需了解你所检出的内容,并记住如果你没有在分支上(处于分离的 HEAD 状态),则可能不想提交,除非你知道自己在做什么(例如正在进行交互式 rebase)。
git rebase <branch> HEAD
。这将找到 <branch>
和 HEAD
的最后一个共同祖先,然后取出从那里到 HEAD
的所有提交,并将它们应用(rebase)到 <branch>
上。它本质上是通过将它们作为补丁来应用它们的,因此如果两个分支非常不同,则可能会产生冲突。但是如果 <branch>
是 HEAD
的祖先(即你在正确的位置,只是忘记了你已经分离了 HEAD
),则 rebase 就是一个快进式合并。 - CascabelHEAD~5
意味着回到前面5个提交。但它并不包含命令中的“GO”部分,只包含命令中的参考部分。HEAD
表示(对)当前提交的引用HEAD~1
表示(对)前一个提交的引用HEAD~
也表示(对)前一个提交的引用HEAD~87
表示(对)前87个提交的引用HEAD~3..HEAD
表示从前3个提交到当前提交(总共3个提交)git checkout HEAD~1
实际上会回退到前一个提交/引用git reset HEAD~3
会取消你最近的3个提交 - 但不会删除更改,也就是说你可以查看最近3个提交中的所有更改,删除你不喜欢的任何内容,或者添加内容然后再次提交它们。git reset --hard HEAD~3
会取消你最近的提交并删除其更改。它会完全删除这些更改。更多信息请参见这里。git diff HEAD~3
查看最近3个提交的更改git diff someFile HEAD~3
查看特定文件最近3个更改git revert --no-commit HEAD~3..HEAD
。撤销3个提交,但不会自动提交,即你需要自己执行git commit -m
。更多信息请参见这里git rev-parse HEAD~2
输出两个提交之前的SHA。git fetch origin/feature22
git checkout feature22
git merge-base feature22 main # will return the SHA of their 050dc022f3a65bdc78d97e2b1ac9b595a924c3f2
git reset 050dc022f3a65bdc78d97e2b1ac9b595a924c3f2
git reset main
,但这只适用于你的同事在拉取请求中创建时拥有最新的主分支更改。如果他们正在开发一个大型功能(并且已经有几天没有与主分支合并),而你只想查看他们在上次从主分支拉取后的新增内容,那么你需要按照上述步骤操作。
cat .git/HEAD
的好信息。
超出范围,但非常有趣:
除了HEAD
之外,还有其他类型的头。请参阅git revisions:
ORIG_HEAD
ORIG_HEAD
是由将您的HEAD
在重大方式下移动的命令创建的,以记录在其操作之前HEAD
的位置,以便您可以轻松将分支的尖端更改回运行它们之前的状态
要撤消git merge
git reset --hard ORIG_HEAD
MERGE_HEAD
我在尝试合并之前再次合并时遇到了这个错误信息,这是因为我没有完成一个已存在的合并。
致命错误:您尚未完成合并(MERGE_HEAD存在)。 请在合并之前提交您的更改。
为了解决这个问题,我必须完成我的合并,然后再进行另一个合并。
FETCH_HEAD
记录了您最后一次使用git fetch命令从远程仓库获取的分支。
CHERRY_PICK_HEAD
记录了您在运行
git cherry-pick
时正在挑选的提交。
强烈推荐查看文档中的this页面。
Git作为一个系统,在正常操作中管理和操作三棵树。(在这里,“树”实际上指的是“文件集合”,而不是特定的数据结构。)
HEAD
的作用是:
Git维护了一个称为HEAD的参照变量。我们将这个变量称为指针,因为它的目的是在存储库中引用或指向特定的提交。当我们创建新的提交时,指针会改变或移动以指向新的提交。HEAD始终指向存储库中当前分支的末端。现在,这与我们的暂存区或工作目录无关。
另一种思考方式是仓库的上一个状态或最后检出的内容,因为它是仓库停止的地方,你也可以说HEAD指向下次提交的父提交或者是写入提交的地方。
我认为一个好的比喻来理解这个是磁带录音机上的播放和录音头。当我们开始录制音频时,磁带经过头部并记录到它上面。当我们按下停止键时,记录头所停留的位置是下次按下录制键时开始录制的位置。现在我们可以四处移动,我们可以将头部移动到不同的位置,但是当我们再次按下录制键时,无论头部的位置在哪里,它都将从那里开始录制。
Git中的HEAD指针非常类似,它指向我们下一次要开始记录的位置。它是我们已提交内容在存储库中离开的地方。
简单来说,HEAD 是指当前检出分支中的最后一次提交。
可以将 HEAD 视为“当前分支”。当使用 git checkout 切换分支时,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始终指向当前分支中最新/最后一次提交。
HEAD
或head
的答案现在可以使用@
代替HEAD
。请参见此答案(最后一节)以了解为什么可以这样做。 - user456814