https://git-scm.com/docs/git-reset说:
git-reset-将当前HEAD重置为指定状态
HEAD
指向当前分支(最近的提交,即其尖端)。可以更改为指向
git checkout
来更改其他分支,而无需修改任何分支。
在git reset
的联机帮助页中,“重置当前位置”中使用HEAD
HEAD进入指定状态”在我看来git reset
切换到
另一个分支作为当前分支,类似于git checkout
。
git reset
来看,实际上更改了哪个提交
当前分支上的最新提交。如果是这样,
那么是否更清楚git reset
的联机帮助页不提及HEAD
?对于
例如git reset
的联机帮助页应显示“ move
当前分支的尖端到同一分支上的先前提交
分支,缩短当前分支”而不是“重置电流
HEAD进入指定状态”?从字面上看我对手册页中的措辞的理解是正确的,还是我听到的是什么?
谢谢。
答案 0 :(得分:2)
...“将当前分支的尖端移至同一分支上的先前提交,从而缩短当前分支” ...
此 是使用git reset
的方式之一。但是,它也可以加长当前分支,或将其完全移动到其他位置,或者不执行任何操作。如果附加了HEAD
(通常情况下),则对指针命名的影响更多是“转到”:
F <-- a
/
D--E <-- b (HEAD)
/
...--C--G--H <-- master
\
I--J <-- develop
由于HEAD
被附加到名称b
上,git reset
被附加到任意提交,例如H
或I
,因此将移动< / em> b
,使其指向该提交。如果选择C
或D
,则可以视为“缩短当前分支”(在这种情况下,其余提交现在仅在分支a
上)。但是,如果选择F
,以便b
和a
都指向F
,则可以视为“延长当前分支”。如果选择提交J
,以使b
和develop
都指向J
,则很难称其为缩短或延长。
git reset
命令非常复杂,因为与许多其他Git命令一样,它执行的某些事情不一定彼此相关。例如,git reset -p file
就像git add -p file
的逆,实际上,这两个操作(使用-p进行加法和重置)都是由不同的内部实现的 1
git-reset
和git-add
的C编码程序编写。
但是,存在三个“主模式”重置,所有这些重置共享一组共同的功能。这些是您通过git reset --soft
,git reset --mixed
和git reset --hard
获得的,它们都不允许使用路径名说明符,但是都允许使用提交说明符:
git reset --soft a234567
git reset --mixed cafedad
git reset --hard HEAD~3
例如。
这些是:
将提交说明符解析为提交哈希ID la git rev-parse
。在哈希ID数据库中查找像a234567
或cafedad
这样的短哈希,并变成完整的哈希ID。在名称到哈希ID数据库中查找诸如master
或v2.3
之类的名称,然后在必要时将其转换为提交哈希。诸如HEAD~3
之类的相对名称指示Git解析第一部分,然后应用关系运算符,因此HEAD~3
首先查找HEAD
的哈希ID,然后在其中计算三个第一对祖父母。提交图。
由于哈希ID无效或无法将其解析为提交(是树或Blob的哈希ID),因此此步骤可能失败。在这种情况下,git reset
会停止并显示一条错误消息。
您可以省略提交说明符,在这种情况下,将从HEAD
的当前值中读取提交说明符。也就是说,如果将HEAD
附加到某个分支名称上(例如,如果您使用的是master
或develop
),则Git将从该分支名称中读取哈希ID。如果HEAD
已分离,则它已经包含原始哈希ID,因此Git将从HEAD
中读取哈希ID。
现在git reset
具有哈希ID,它将哈希ID写入HEAD
或通过HEAD
。 2 即,如果HEAD
为附加到分支名称后,Git会将新的哈希ID存储到该分支名称中。如果HEAD
被分离,则Git会将新选择的哈希ID写入HEAD
。
请注意,如果您在步骤1中指定了HEAD
,或者在步骤1中未指定任何内容,则会将从从 HEAD
读取的当前值写回或-通过HEAD
表示没有任何变化。但是,如果您 did 指定了其他一些提交,则此时HEAD
本身会更改(分离的HEAD情况),或者--soft
的目标也会更改(附件-HEAD情况)。
如果您使用过git reset
,那么--mixed
现在就结束了。
否则,对于--hard
或git reset
,HEAD
现在将重置索引,使其内容与--mixed
所标识的提交相匹配。
如果您使用过git reset
,那么git reset --hard
现在就结束了。
否则,即git reset
仅用于HEAD
,现在git reset
重置工作树,使其内容与在步骤3中刚刚重置的索引匹配。
(步骤3和/或4也可能失败。如果步骤3失败,Git可以将git xyz
及其索引恢复到git-core
之前的状态,因为Git更新了这两个实体通过创建新文件,然后使用原子操作将更新交换到基础文件系统中。但是,如果第4步失败,则可能会一团糟。)
1 运行$PATH
时,Git将内部git --exec-path
的目录推入git-core
中。 (此处的描述以sh / bash为中心,但是即使在Windows上,算法也相同。)运行git-add
以查看此git-commit
目录在您的安装目录中的位置。在该目录中查找,您将找到名为git-rebase
,git-reset
,git xyz
,$PATH
等的程序。因此,git-xyz
的工作方式是Git设置一些上下文,在git-core
的前面插入这个“核心”目录,然后调用git-xyz
。如果该文件存在于$PATH
中,则该文件现在正在运行。否则,将运行git-xyz
中任何位置的任何名为git xyz
的 other 文件。因此,只要此git-core目录中没有git-xyz
,您就可以编写自己的程序,将其构建到名为HEAD
的可执行文件中,并使用git symbolic-ref
运行它。>
2 名称HEAD
在Git中非常特殊。它实际上是硬编码在各种源文件中的,并且可以追溯到Git的远古时代,它被存储为符号链接。该方法在Windows上不起作用,因此在某些时候,名称有些特殊:现在,任何引用都可以被Git称为符号引用。符号参考是通过阅读其他参考来解决的参考。命令HEAD
是用于读取和写入此类引用的外部接口。
虽然现在可以将任何引用设为符号引用,但是{{1}}对于Git仍然很宝贵:如果文件丢失,Git会声明存储库不再是存储库。由于这是存储库中最活跃的文件之一,因此,如果在执行某些Git命令时系统崩溃,则有时该文件会丢失。在这种情况下,通常只需手动创建丢失的{{1}}文件就可以恢复所有内容。
答案 1 :(得分:1)
案例1,HEAD
-> Foo分支->提交A。
案例2,HEAD
->提交A。
在情况1中,HEAD
指向分支,分支指向提交。 git branch
返回* Foo
。在案例2中,它是分离的HEAD状态。 HEAD
直接指向一个提交。 git branch
返回HEAD detached at xxxxxxx
或(no branch)
。
在情况1中,git reset
使Foo
指向特定的提交。 HEAD
指向Foo
时,它也会间接指向提交。
在情况2中,git reset
使HEAD
指向特定的提交。不涉及分支。