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.
HEAD
和 ORIG_HEAD
在 Git 中类似于 $PWD
和 $OLDPWD
在 Bash 中。 :)
运行git checkout
时发现HEAD
与@
不完全相同。另外,我还发现HEAD
在运行git checkout
时与HEAD~0
并不完全相同。事实上,@
等同于HEAD~0
。以下截图如下:@
vs HEAD
和HEAD
vs HEAD~0
【参考方案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
它。例如,请参阅***.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_HEAD
是HEAD
的先前状态,由可能具有危险行为的命令设置,以便于恢复它们。现在 Git 有 reflog 的用处不大:HEAD@1
大致相当于 ORIG_HEAD
(HEAD@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,它描述了所有引用提交的方式(包括HEAD
和ORIG_HEAD
)。【参考方案4】:
来自man 7 gitrevisions
:
HEAD 命名您基于该提交的更改 工作树。 FETCH_HEAD 记录您提取的分支 从您上次调用 git fetch 的远程存储库中获取。 ORIG_HEAD 是由将您的 HEAD 移动到 激进的方式,记录 HEAD 在他们之前的位置 操作,让您可以轻松更改分支的尖端 回到你运行它们之前的状态。 MERGE_HEAD 记录 运行时要合并到分支中的提交 混帐。 CHERRY_PICK_HEAD 记录你的提交 运行 git cherry-pick 时进行樱桃采摘。
【讨论】:
以上是关于Git 中的 HEAD 和 ORIG_HEAD的主要内容,如果未能解决你的问题,请参考以下文章