Git 中的 HEAD 和 ORIG_HEAD

Posted

技术标签:

【中文标题】Git 中的 HEAD 和 ORIG_HEAD【英文标题】:HEAD and ORIG_HEAD in Git 【发布时间】:2010-11-01 04:21:15 【问题描述】:

这些符号指的是什么,它们的含义是什么?

(我在官方文档中找不到任何解释)

【问题讨论】:

注意:HEAD 现在(即将推出的 git1.8.4)'@'!见my edited answer below Note-bis: '@' (for HEAD) 仍然存在,但不适用于 1.8.4 answer edited and amended。 注意之三:'@' for HEAD 又回来了 git 1.8.5/1.9。 answer edited again. HEADORIG_HEAD 在 Git 中类似于 $PWD$OLDPWD 在 Bash 中。 :) 运行git checkout时发现HEAD@不完全相同。另外,我在运行git checkout时也发现HEADHEAD~0并不完全相同。事实上,@ 等同于HEAD~0。以下截图如下:@ vs HEADHEAD vs HEAD~0 【参考方案1】:

HEAD 是(直接或间接,即符号)对当前提交的引用。这是您在工作目录中检查的提交(除非您进行了一些更改或等效的更改),并且它是在“git commit”之上创建一个新的提交。通常HEAD 是对其他命名分支的符号引用;此分支当前已签出分支或当前分支。 HEAD 也可以直接指向一个提交;这种状态称为“分离 HEAD”,可以理解为处于未命名的匿名分支上。

@HEAD 的快捷方式,因为 Git 1.8.5

ORIG_HEADHEAD 的先前状态,由可能具有危险行为的命令设置,以便于恢复它们。现在 Git 有 reflog 的用处不大:HEAD@1 大致相当于 ORIG_HEADHEAD@1 始终是 HEAD 的最后一个值,ORIG_HEAD 是危险操作之前HEAD 的最后一个值)。

更多信息请阅读git(1) manpage / [gitrevisions(7) manpage][git-revisions]、Git User's Manual、Git Community Book 和Git Glossary

【讨论】:

嗨,Jakub。 +1 的解释。您能否详细说明 HEAD@1 的“大致等效”部分?我在回答thread.gmane.org/gmane.comp.version-control.git/38379 时提到了线程(早在 2007 年 2 月你就在其中),我并不完全理解你们围绕 @... 语法进行的讨论。 ORIG_HEAD 仅由“危险”命令设置(我认为),这些命令将 HEAD 移动一次以上。所以 ORIG_HEAD 并不总是设置,而 HEAD@1 总是设置。 @1 是 $(git symbolic-ref HEAD)@1,即它使用 reflog 作为当前分支,而不是 HEAD reflog。 Riiight... 我现在明白了 :) 谢谢你的澄清。对于它的价值,我也赞成你的评论! "并且 HEAD 是一个提交,"git commit" 会在它之上创建一个新的。" -- 很好记住,谢谢!同样来自@VonC,'它是在“git commit”之上构建的提交,“git diff --cached”和“git status”进行比较。' git help revisions 会弹出git-scm.com/docs/gitrevisions,它描述了所有引用提交的方式(包括HEADORIG_HEAD)。【参考方案2】:

来自git reset

"pull" 或 "merge" 总是将当前分支的原始提示留在 ORIG_HEAD

git reset --hard ORIG_HEAD

硬重置会使你的索引文件和工作树回到那个状态,并将分支的尖端重置为那个提交。

git reset --merge ORIG_HEAD

查看合并的结果后,你可能会发现另一个分支的变化并不令人满意。运行“git reset --hard ORIG_HEAD”会让你回到原来的位置,但它会丢弃你不想要的本地更改。 “git reset --merge”保留您的本地更改。


在应用任何补丁之前,ORIG_HEAD 被设置为当前分支的尖端。 如果您遇到多个提交的问题,例如在错误的分支上运行'git am',或者通过更改邮箱更容易修复的提交中的错误(例如“发件人:”行中的+错误),这很有用。

此外,合并总是将“.git/ORIG_HEAD”设置为 HEAD 的原始状态,因此可以使用“git reset ORIG_HEAD”删除有问题的合并。


注意:来自here

HEAD 是一个移动指针。有时它意味着当前分支,有时它不是。

所以 HEAD 不是在任何地方都是“当前分支”的同义词。

HEAD 在 git 中表示 “当前”无处不在,但不一定表示“当前分支”(即分离的 HEAD)。

但它几乎总是意味着“当前提交”。 它是在“git commit”之上构建的提交,并与“git diff --cached”和“git status”进行比较。 这意味着当前分支仅在非常有限的上下文中(恰好当我们想要一个分支时) 要操作的名称 --- 通过 commit/rebase/etc. 重置和增长分支提示)。

Reflog 是一种回到过去的工具,时间机器与“当前”的概念有着有趣的互动。

HEAD@5.minutes.ago 可能意味着“取消引用 HEAD symref 以找出我们现在在哪个分支,然后找出 5 分钟前那个分支的尖端在哪里”。 或者,它可能意味着“我将称为 HEAD 5 的提交是什么? 几分钟前,例如如果我当时做了“git show HEAD””。


git1.8.4 (July 2013) 引入 引入新符号! (实际上,它将适用于 2013 年第四季度的 1.8.5:以 commit 9ba89f4 重新引入),作者为 Felipe Contreras

现在您可以说“@”,而不是输入四个大写字母“HEAD”, 例如“git log @”。

见commit cdfd948

输入“HEAD”很乏味,尤其是当我们可以改用“@”时。

选择'@'的原因是它自然地遵循ref@op语法(例如HEAD@u),除了我们没有引用,也没有操作,当我们没有这些时,它假设 'HEAD' 是有道理的。

所以现在我们可以使用 'git show @~1',以及所有这些好东西。

到目前为止,'@' 是一个有效的名称,但它与这个想法相冲突,所以让我们让它无效。可能很少有人(如果有的话)使用这个名字。

【讨论】:

运行 git reset ORIG_HEAD 并提交后。 ORIG_HEAD 仍然在 HEAD 旁边的参考下。为什么它没有从视图中移除? @powder366 但git reset 将生成ORIG_HEAD。所以你需要手动rm它。例如,请参阅***.com/a/12418078/6309。 @VonC @ HEAD 的别名是 reverted (temporarily?) for the Git 1.8.4 release!今天刚刚宣布! 喜欢“单挑”评论! @snakecharmerb 好点。我已经删除了还原部分,只保留公告。【参考方案3】:

来自man 7 gitrevisions

HEAD 命名您基于该提交的更改 工作树。 FETCH_HEAD 记录您提取的分支 从您上次调用 git fetch 的远程存储库中获取。 ORIG_HEAD 是由将您的 HEAD 移动到 激进的方式,记录 HEAD 在他们之前的位置 操作,让您可以轻松更改分支的尖端 回到你运行它们之前的状态。 MERGE_HEAD 记录 运行时要合并到分支中的提交 混帐。 CHERRY_PICK_HEAD 记录你的提交 运行 git cherry-pick 时进行樱桃采摘。

【讨论】:

【参考方案4】:

我的理解是 HEAD 指向当前分支,而 ORIG_HEAD 用于在进行“危险”操作之前存储之前的 HEAD。

例如 git-rebase 和 git-am 在应用任何更改之前记录分支的原始提示。

【讨论】:

HEAD 并不总是指向当前分支(可以分离) 那么当 HEAD “分离”时,“当前分支”是什么? @CurtJ.Sampson 那是“没有分支”。这就是为什么当您处于分离状态时,您会执行 git branch foo -b 以便为该孤儿提交“创建”一个分支。

以上是关于Git 中的 HEAD 和 ORIG_HEAD的主要内容,如果未能解决你的问题,请参考以下文章

Git 中的 HEAD 和 ORIG_HEAD

Git 中的 HEAD 和 ORIG_HEAD

撤消 git pull --rebase?

Git: Git中的HEAD

git 中的 HEAD 是啥?

git 中的 HEAD 是啥?