GIT命令git-checkout的分离HEAD分析

访客 阅读:114 2021-09-05 18:30:37 评论:0
本文章主要介绍了GIT命令git-checkout的分离HEAD,具有不错的的参考价值,希望对您有所帮助,如解说有误或未考虑完全的地方,请您留言指出,谢谢!

DETACHED HEAD分离HEAD

HEAD通常指向的是一个命名分支(例如master)。 同时,每个分支都指向一个特定的提交。 让我们看一个具有三个提交的仓库,其中一个打标签v2.0,并且master分支已签出:

           HEAD (refers to branch 'master') 
            | 
            v 
a---b---c  branch 'master' (refers to commit 'c') 
    ^ 
    | 
  tag 'v2.0' (refers to commit 'b') 

在这种状态下创建提交后,分支将更新以引用新的提交。

具体来说,git commit创建一个新的commit d,其父节点为commit c,然后更新分支master来引用新的 commit d。

HEAD仍然是指分支master,因此现在间接指的是commit d:

$ edit; git add; git commit 
 
               HEAD (refers to branch 'master') 
                | 
                v 
a---b---c---d  branch 'master' (refers to commit 'd') 
    ^ 
    | 
  tag 'v2.0' (refers to commit 'b')

有时能够签出一个分支下的不在顶端(tip)的提交(如:git checkout b),或者甚至创建一个未被命名分支引用的新提交,这很有用。

让我们看一下签出commit b时发生的情况(这里显示了两种完成方法):

$ git checkout v2.0  # or 
$ git checkout master^^ 
 
   HEAD (refers to commit 'b') 
    | 
    v 
a---b---c---d  branch 'master' (refers to commit 'd') 
    ^ 
    | 
  tag 'v2.0' (refers to commit 'b') 

请注意,无论我们使用哪种checkout命令,HEAD现在都直接指向commit b,这被称为处于分离HEAD状态。

这表示HEAD指的是特定的提交,而不是指的是命名分支。

分离的 HEAD 就是让其指向了某个具体的提交记录而不是分支名!!!!

当我们在commit b上创建一个提交commit e

$ edit; git add; git commit 
 
     HEAD (refers to commit 'e') 
      | 
      v 
      e 
     / 
a---b---c---d  branch 'master' (refers to commit 'd') 
    ^ 
    | 
  tag 'v2.0' (refers to commit 'b') 

现在有一个新的提交,但仅由HEAD引用。 我们当然可以在这种状态下添加另一个提交:

$ edit; git add; git commit 
 
	     HEAD (refers to commit 'f') 
	      | 
	      v 
      e---f 
     / 
a---b---c---d  branch 'master' (refers to commit 'd') 
    ^ 
    | 
  tag 'v2.0' (refers to commit 'b') 

实际上,我们可以执行所有正常的Git操作。

但是,让我们来看看当我们签出master分支时会发生什么:

$ git checkout master 
 
               HEAD (refers to branch 'master') 
      e---f     | 
     /          v 
a---b---c---d  branch 'master' (refers to commit 'd') 
    ^ 
    | 
  tag 'v2.0' (refers to commit 'b')

需要意识到,此时没有任何的引用指向commit f 。

最终commit f(以及扩展的commit e)将被例行的Git垃圾收集进程删除掉,除非我们在离开commit f之前,创建一个指向commit f的引用。

如果我们尚未离开commit f,下面命令中的任何一个都将创建对它的引用:

$ git checkout -b foo   (1) 
$ git branch foo        (2) 
$ git tag foo           (3)
  1. creates a new branch foo, which refers to commit f, and then updates HEAD to refer to branch foo

  2. similarly creates a new branch foo, which refers to commit f, but leaves HEAD detached.

  3. creates a new tag foo, which refers to commit f, leaving HEAD detached.

如果我们离开了commit f,那么我们必须首先恢复其对象名称(通常使用git reflog),然后才能创建对其的引用。

For example, to see the last two commits to which HEADreferred, we can use either of these commands:

$ git reflog -2 HEAD # or 
$ git log -g -2 HEAD 

 补充

提交树上移动HEAD

HEAD 是一个对当前检出记录的符号引用 —— 也就是指向你正在其基础上进行工作的提交记录。

HEAD 总是指向当前分支上最近一次提交记录。大多数修改提交树的 Git 命令都是从改变 HEAD 的指向开始的。

HEAD 通常情况下是指向分支名的(如 bugFix)。在你提交时,改变了 bugFix 的状态,这一变化通过 HEAD 变得可见。

如果想看 HEAD 指向,可以通过 cat .git/HEAD 查看

我们通过下面的例子看下HEAD的变化

在初始状态下:

HEAD -> master -> C2

HEAD 指向 master, master 指向 C2

步骤一、执行git checkout C1之后

HEAD -> C1


步骤二、执行git checkout master之后,又回到了初始状态

步骤三、再次执行git checkout C1分离HEAD之后,执行git commit

下面我们就通过分别执行下面三个语句,来看上面的文字中对他们的区别的讲解

步骤四(1)、执行git checkout -b foo

步骤四(2)、执行git branch foo 

步骤四(3)、执行git tag foo

参考IT虾米网


标签:java
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

发表评论
搜索
KIKK导航

KIKK导航

排行榜
关注我们

一个IT知识分享的公众号