【问题标题】:HEAD and ORIG_HEAD in GitGit 中的 HEAD 和 ORIG_HEAD
【发布时间】: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@不完全相同。另外,我还发现HEAD在运行git checkout时与HEAD~0并不完全相同。事实上,@ 等同于HEAD~0。以下截图如下:@ vs HEADHEAD vs HEAD~0

标签: git


【解决方案1】:

来自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它。例如,请参阅stackoverflow.com/a/12418078/6309
  • @VonC @ HEAD 的别名是 reverted (temporarily?) for the Git 1.8.4 release!今天刚刚宣布!
  • 喜欢“单挑”评论!
  • @snakecharmerb 好点。我已经删除了还原部分,只保留公告。
【解决方案2】:

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

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

【讨论】:

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

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 ManualGit Community BookGit 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)。
【解决方案4】:

来自man 7 gitrevisions

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

【讨论】:

    猜你喜欢
    • 2011-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多