前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Git】:遇到 Detached HEAD 怎么办?

【Git】:遇到 Detached HEAD 怎么办?

作者头像
WEBJ2EE
发布2023-09-25 08:40:52
2.6K0
发布2023-09-25 08:40:52
举报
文章被收录于专栏:WebJ2EE

目标读者

哈啰。准备阅读本文的小伙伴。如果你在使用 Git 的过程中遇到“detatched HEAD”字样,发现代码不能正常向远程仓库推送,而且你又不知道该怎么办时,那么你应该仔细阅读本文后面的内容,相信会给你一个满意的解决方案😄 。

什么是 Git 的 ref 和 head?

在进入正题解释“什么是Detatched HEAD?”之前,让我们先来回顾一下 Git 的基础知识“什么是 Git 的 ref 和 head?”。这将有利于后续我们深刻认识“什么是Detatched HEAD?”。

commit ID:Git 仓库的记录是由一次次的 Commit 构成的,每次 commit 都由一个 commit ID 唯一标识。这种唯一标识是一个长度 40 位的哈希值(例如:f5946c1e5d45d811e40ac7d2bb862e4911fcb1a6)。显然,这种标识是为计算机服务的,不适合供人类阅读和记忆。

ref:Git 的 ref 是适合人类阅读和记忆的,指向某 commit ID 的指针。

  • 分支(branch)的名字(例如:master、dev)就是一种 ref。
  • 标签(tag)的名字(例如:v0.1、v0.2)也是一种 ref。
  • 远程仓库(remote)中的分支也是 ref。

注:Git 的 ref 存储在项目本地仓库中的 .git/refs/ 目录下,文件内容是 ref 所指向的 commit ID。

head:Git 的 head 也是一种 ref,并且它们就是代表我们本地分支(例如:master、dev等)的 ref。更重要的是,指代分支的 ref 命名为 head 也有它的内涵,即 head 永远指向它所指代分支的最“头部”的提交(即最新的一次提交)。换句话说,例如分支 mastermaster 这个名字是不变的,但它指向的 commit ID 会随着你工作过程中的提交而改变,永远指向你最新一次的提交。

注:Git 的 head 存储在 .git/refs/heads 目录下,内容是其所代表分支的最头部(最新的一次提交)提交的 commit ID。

什么是 Git 的 HEAD

注意前面说的 Git 的 head(注意是小写的 head)指代的是分支,而且指向其所指代分支的头部提交,即:.git/refs/heads/master 即指向 master 分支的头部提交;.git/refs/heads/dev即指向dev 分支的头部提交。

Git 的 HEAD(注意是大写的HEAD),在某 Git 仓库范围内只有一个,代表你当前所处的工作位置,即你的后续 commit 将从 HEAD 这里继续。

注:Git 的 head 可以有多个,所以它存储在 .git/refs/heads 目录中;Git 的 HEAD 只有一个,所以它存储在 .git/HEAD 文件中。

通常情况下,HEAD 是指向分支的,而分支又指向分支中的头部提交(最新一次提交),所以 HEAD 通常也是指向你当前所处分支的头部提交。

注:.git/HEAD 中并没有直接写某分支的头部提交的 commit ID,而是间接指向 heads 中的分支名。这种存储方式,实际是让Git知道,当前 HEAD 指向的是某一个分支。

Detatched HEAD 是什么意思?

前面讲到过,Git HEAD 通常指向的是你当前正在工作的分支,也即指向你当前正在工作分支的头部提交(最新一次的提交),这也意味着,你可继续工作(提交),即你后续的提交会在当前分支上继续下去。

可如果 Git HEAD 不在指向某分支,而是指向某次具体的提交(通常是历史中的某个位置),即处于 Detatched 状态,这意味着你后续的工作(提交)不会发生在当前分支上,即不会对当前分支产生影响。

我是怎么进入 Detatched HEAD 状态的?

当你 checkout 的不是一个分支时,即 HEAD 不再指向分支,而是指向历史中的一个位置时,即处于 Detatched HEAD 状态。

所以下面这些命令都会让你进入 Detatched HEAD 状态:

  • checkout HEAD^^
  • checkout <commit id>
  • checkout <tag>

处于 Detatched HEAD 状态有什么问题?

当你处于 Detatched HEAD 状态时,你所进行的所有后续提交不在隶属于某个特定的分支,所以当你切换到其他分支后,之前所做的修改有可能丢失(注:这里用“可能”是因为还可以通过使用 reflog 等命令尝试找回)。

Detatched HEAD 有什么用?

“Detatched HEAD” 这个名字虽然不太友好,但是它有大用途。

比如今天你发现,用户现场运行的程序有 BUG,不巧的是用户现场的程序还是你上个月发布的版本,更不巧的是你还不敢直接给用户现场升级现在的最新版本(因为这一个月已经对程序进行了大改)。所以唯一可靠的方案,就是在上个月发布到用户现场的程序版本基础上进行 BUG 修复,重新测试后,打包给用户升级。👀️

此时你就需要能跳回到代码仓库中历史上的某个状态,所以你执行了:

代码语言:javascript
复制
git checkout v2.13.16

OK,此时整个代码仓库都已经回退到了历史上的 v2.13.16 结点的状态,你也可以进行 BUG 修复和代码测试了。

显然此时你也进入了 Detatched HEAD 状态。😄

如何从 Detatched HEAD 状态中脱离?

场景1:意外进入 Detatched HEAD 状态

可能你也不是有意的,可能点了某个按钮,或者执行了某个命令,不小心进入了 Detatched HEAD 状态。此时可能你也没干什么,只是想从 Detatched HEAD 状态中脱离出来。

很简单,你只需要进行分支切换即可。

代码语言:javascript
复制
git checkout dev

此时 HEAD 将重新指向 dev分支,ok,你可以继续进行工作了。😕

场景2:做了实验性修改,但是不需要保留这些修改

可能你确实想将代码仓库退回到历史中的某个结点,并做一些验证性测试,但测试过程中对代码的修改不需要保留,可以直接丢弃。

那么做法也很简单,也直接进行分支切换即可。

代码语言:javascript
复制
git checkout v2.13.16

此时 HEAD 将重新指向 dev分支,ok,你可以继续进行工作了。😕

方式3:做了实验性修改,并且需要保留这些修改

如果你将代码仓库退回到历史中的某个结点,并做了修改和实验性的验证,而且在测试完成后希望把修改的内容保存下来,那么你需要做的就是,创建新的分支保存这些修改,未来可以考虑把这些修改重新合并回主分支。

代码语言:javascript
复制
git checkout -b my-new-branch

此时你所做的实验性修改,都会被保存在你新创建的分支中。

如果你需要,可以再将这些修改合并回主分支。

代码语言:javascript
复制
git checkout master
git merge my-new-branch

总结一下

Detatched HEAD 是指当前你的工作环境(HEAD)指向的并不是一个分支,而是指向历史中的某次 commit 或某个 tag。这可能是由于你 checkout 了一个历史中的一个 commit 或一个 tag 造成的。在Detatched HEAD 状态下进行的提交不隶属于任何分支。我们可以通过直接切换分支(注:丢弃我们在 Detatched HEAD 状态下所做的修改),或创建新分支(即:保留我们在 Detatched HEAD 状态下所做的修改),从 Detatched HEAD 状态中脱离。

参考:

https://initialcommit.com/blog/what-is-git-head https://git-school.github.io/visualizing-git/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-09-23 23:18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 WebJ2EE 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目标读者
  • 什么是 Git 的 ref 和 head?
  • 什么是 Git 的 HEAD
  • Detatched HEAD 是什么意思?
    • 我是怎么进入 Detatched HEAD 状态的?
      • 处于 Detatched HEAD 状态有什么问题?
        • Detatched HEAD 有什么用?
        • 如何从 Detatched HEAD 状态中脱离?
          • 场景1:意外进入 Detatched HEAD 状态
            • 场景2:做了实验性修改,但是不需要保留这些修改
              • 方式3:做了实验性修改,并且需要保留这些修改
              • 总结一下
              相关产品与服务
              对象存储
              对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档