git reset是否可以切换到另一个分支作为当前分支?

时间:2019-01-09 01:28:41

标签: git

https://git-scm.com/docs/git-reset说:

  

git-reset-将当前HEAD重置为指定状态

  1. HEAD指向当前分支(最近的提交,即其尖端)。可以更改为指向 git checkout来更改其他分支,而无需修改任何分支。

    git reset的联机帮助页中,“重置当前位置”中使用HEAD HEAD进入指定状态”在我看来git reset切换到 另一个分支作为当前分支,类似于git checkout

  2. 但是从我的脑袋git reset来看,实际上更改了哪个提交 当前分支上的最新提交。如果是这样, 那么是否更清楚git reset的联机帮助页不提及HEAD?对于 例如git reset的联机帮助页应显示“ move 当前分支的尖端到同一分支上的先前提交 分支,缩短当前分支”而不是“重置电流 HEAD进入指定状态”?

从字面上看我对手册页中的措辞的理解是正确的,还是我听到的是什么?

谢谢。

2 个答案:

答案 0 :(得分:2)

  

...“将当前分支的尖端移至同一分支上的先前提交,从而缩短当前分支” ...

是使用git reset的方式之一。但是,它也可以加长当前分支,或将其完全移动到其他位置,或者不执行任何操作。如果附加了HEAD(通常情况下),则对指针命名的影响更多是“转到”:

            F   <-- a
           /
       D--E   <-- b (HEAD)
      /
...--C--G--H   <-- master
         \
          I--J   <-- develop

由于HEAD被附加到名称b上,git reset被附加到任意提交,例如HI,因此将移动< / em> b,使其指向该提交。如果选择CD,则可以视为“缩短当前分支”(在这种情况下,其余提交现在仅在分支a上)。但是,如果选择F,以便ba都指向F,则可以视为“延长当前分支”。如果选择提交J,以使bdevelop都指向J,则很难称其为缩短延长。

git reset命令非常复杂,因为与许多其他Git命令一样,它执行的某些事情不一定彼此相关。例如,git reset -p file就像git add -p file的逆,实际上,这两个操作(使用-p进行加法和重置)都是由不同的内部实现的 1

用Perl编写的Git命令,而不是由名为git-resetgit-add的C编码程序编写。

但是,存在三个“主模式”重置,所有这些重置共享一组共同的功能。这些是您通过git reset --softgit reset --mixedgit reset --hard获得的,它们都不允许使用路径名说明符,但是都允许使用提交说明符:

git reset --soft a234567
git reset --mixed cafedad
git reset --hard HEAD~3

例如。

这些是:

  1. 将提交说明符解析为提交哈希ID la git rev-parse。在哈希ID数据库中查找像a234567cafedad这样的短哈希,并变成完整的哈希ID。在名称到哈希ID数据库中查找诸如masterv2.3之类的名称,然后在必要时将其转换为提交哈希。诸如HEAD~3之类的相对名称指示Git解析第一部分,然后应用关系运算符,因此HEAD~3首先查找HEAD的哈希ID,然后在其中计算三个第一对祖父母。提交图。

    由于哈希ID无效或无法将其解析为提交(是树或Blob的哈希ID),因此此步骤可能失败。在这种情况下,git reset会停止并显示一条错误消息。

    您可以省略提交说明符,在这种情况下,将从HEAD的当前值中读取提交说明符。也就是说,如果将HEAD附加到某个分支名称上(例如,如果您使用的是masterdevelop),则Git将从该分支名称中读取哈希ID。如果HEAD已分离,则它已经包含原始哈希ID,因此Git将从HEAD中读取哈希ID。

  2. 现在git reset具有哈希ID,它将哈希ID写入HEAD或通过HEAD 2 即,如果HEAD为附加到分支名称后,Git会将新的哈希ID存储到该分支名称中。如果HEAD被分离,则Git会将新选择的哈希ID写入HEAD

    请注意,如果您在步骤1中指定了HEAD,或者在步骤1中未指定任何内容,则会将从 HEAD读取的当前值写回或-通过HEAD表示没有任何变化。但是,如果您 did 指定了其他一些提交,则此时HEAD本身会更改(分离的HEAD情况),或者--soft的目标也会更改(附件-HEAD情况)。

  3. 如果您使用过git reset,那么--mixed现在就结束了。

    否则,对于--hardgit resetHEAD现在将重置索引,使其内容与--mixed所标识的提交相匹配。

  4. 如果您使用过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-rebasegit-resetgit 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指向特定的提交。不涉及分支。