Git称之为分离的头部最终会发生什么

Git称之为分离的头部最终会发生什么,git,smartgit,Git,Smartgit,我想通过SmartGit恢复到以前的提交。通过SmartGit,我选择了一个较早的提交并进行了签出。系统提示我输入分支名称。我选择不创建分支,因为当我只想在现有分支上“向后移动”时,创建分支似乎是不必要的,甚至是愚蠢的。这导致头部脱落。这似乎是一个坏主意,继续发展一个独立的头部,所以我没有继续 我切换到命令行,并做了一个git日志,以识别我感兴趣的早期提交的哈希代码。我做了一个git重置——硬0dfc994b23ea 现在,git log似乎是来自更早的时间,这就是我想要的。同样,SmartGi

我想通过SmartGit恢复到以前的提交。通过SmartGit,我选择了一个较早的提交并进行了签出。系统提示我输入分支名称。我选择不创建分支,因为当我只想在现有分支上“向后移动”时,创建分支似乎是不必要的,甚至是愚蠢的。这导致头部脱落。这似乎是一个坏主意,继续发展一个独立的头部,所以我没有继续

我切换到命令行,并做了一个
git日志
,以识别我感兴趣的早期提交的哈希代码。我做了一个
git重置——硬0dfc994b23ea


现在,
git log
似乎是来自更早的时间,这就是我想要的。同样,SmartGit看起来也不错。无论是
git日志还是SmartGit日志(至少表面上看),都没有任何迹象表明我犯了错误(头部脱落)。分离的头部会发生什么情况?

让我简单解释一下。分离头意味着您的工作树“指向”您要求git签出的修订版,从这里您可以“像往常一样”工作。你可以提交东西,合并东西,随便什么。唯一的问题是git不会移动任何“分支”(也称为修订指针),因为您没有签出“分支”,而是签出了修订(如果您要求使用--detach签出分支,也可以实现同样的效果)。如果你想快速完成某件事,但又不想有一个真正的指针指向它,分离头是非常有用的(比如……做一个快速测试,然后返回到你以前工作的地方。创建一个分支只是为了及时返回,然后返回到你以前工作的地方,然后“临时”删除你创建的分支有什么意义只是为了能够结帐?)。长话短说:你可以从“超脱的头”的位置搬到你喜欢的任何地方,这不会有什么不同

作为旁白。。。当您提供一个范围的修订时,git重置-难做什么?因为我只使用它提供了一个单一修订版。刚刚检查了git help reset,我没有看到它。

这不是一个真正的错误,这里的一切仍然正常。你的头还在分离,只是在另一个地方分离了

不过,通常更明智的做法是使用
git checkout
切换到所需的提交。要了解原因,请继续阅读

长描述 理解这一点的关键是多部分。首先,Git主要关注提交。正如您所看到的,提交具有大而难看的散列ID,
0dfc…
等等,这对于人类来说很难使用,但是对于Git来说工作得很好。因此,这些散列ID是每次提交的“真实名称”

此外,每个提交通过其哈希ID记录一个父提交。此父提交是在它之前的提交。一些提交合并记录了多个父项,并且存储库中至少有一个提交没有父项,因为这是第一次提交,所以它不可能记录任何早期提交的ID:没有任何早期提交

所有这一切意味着,我们可以绘制一个提交图,使用它们的哈希ID或使用单个大写字母代表大而丑陋的哈希ID,只要我们不介意在26次提交后用完:

A <-B <-C
我们可以停止绘制内部箭头,因为(1)一旦提交,就永远不会更改;(2)它们都必须向后,因为当父级提交时,子级提交不存在,但当子级提交时,父级确实存在。我们仍然需要
master
箭头,因为现在我们可以看到Git如何向存储库添加新提交

添加提交更改分支名称 如果我们签出
master
并做一些工作,然后运行
git add
,然后运行
git commit
,git将构建一个新的commit,我们称之为
D
,并将
D
的哈希ID作为
D
的父级:

A--B--C   <-- master
       \
        D
现在我们有了一个新的承诺。让我们理顺这个链,并添加另一个指向commit
D
的分支名称:

A--B--C--D   <-- develop, master
Git现在需要将
E
的散列ID写入两个分支名称中的一个,以对其进行更新。但是哪一个呢?这就是
HEAD
的作用

头通常附加在分支名称上 让我们再画一次,但将标题附加到
develope

A--B--C--D   <-- develop (HEAD), master
          \
           E
现在Git知道使用
develope
应该使用commit
E
,而使用
master
应该使用commit
D

注意,对于这种附加头,
HEAD
实际上只包含。我们稍后再讨论分离的头部案例

git reset
移动你的头 如果我们仍在
develope
上并运行
git reset
,则会发生以下情况:

A--B--C   <-- develop (HEAD)
       \
        D   <-- master
         \
          E   <-- ???
然后运行
git reset--hard HEAD
,我们将我们的HEAD(即名称
develope
)从
e
移动到
e
,这样它就可以保持不变。
git reset
的其他效果也适用,这大概就是为什么我们要做这个
git reset
,因为我们的头部是自由运动的

你现在已经准备好去理解一个分离的头 分离的头仅仅意味着Git更改了头,因此它不包含分支的名称,而是直接包含原始提交哈希ID。我们可以这样画:

A--B--C--D   <-- master
          \
           E   <-- develop, HEAD
当头部被分离时,我们所做的任何其他
git重置--hard
都将简单地移动
HEAD
(再加上使用
git重置--hard
,我们想要做的其他事情)

git checkout
命令也可以完成大部分工作 当您运行
git checkout master
git checkout develope
时,您要求git做两件事:

  • 切换提交:使用名称
    master
    develope
    ,找到要签出的提交,并提取该提交,以便
    A--B--C--D   <-- develop (HEAD), master
              \
               E
    
    A--B--C--D   <-- master
              \
               E   <-- develop (HEAD)
    
    A--B--C   <-- develop (HEAD)
           \
            D   <-- master
             \
              E   <-- ???
    
    A--B--C--D   <-- master
              \
               E   <-- develop (HEAD)
    
    A--B--C--D   <-- master
              \
               E   <-- develop, HEAD
    
    A--B--C   <-- HEAD
           \
            D   <-- master
             \
              E   <-- develop