当前位置: 首页 > news >正文

超详细的Git submodule讲解以及出现分离头指针(detached HEAD)的解决方法

Git submodule 是对父仓库中的子仓库进行管理的命令

git submodule 命令用于管理包含其他 Git 仓库的项目。

git submodule 命令对于大型项目或需要将外部库集成到项目中的情况非常有用。 通过使用子模块,你可以将外部库作为你的项目的一部分来管理,而不必将其直接合并到主仓库中。

使用详解

一:拉取仓库及其子模块

1、初始化子模块

git submodule init

该命令会初始化配置文件中的所有子模块。它会根据 .gitmodules 文件中的信息设置子模块的 URL 和路径,但不会下载子模块的内容。

常见用法:在克隆了一个包含子模块的仓库后,运行此命令来初始化子模块,也就是将子仓库的内容也一克隆下来

git clone <repo-url>
cd <repo-dir>
git submodule init

2、更新子模块

git submodule update

该命令会从子模块的远程仓库中拉取子模块的内容,并将其更新到 .gitmodules 文件中指定的提交。

**常见用法:**在初始化子模块后,或当你需要更新子模块的内容时,运行此命令。

git submodule update
如果要直接拉取仓库的所有模块,可以直接用以下命令直接搞定
git submodule update --init --recursive
# --init:初始化未初始化的子模块(即首次拉取时,根据 .gitmodules 配置克隆子模块代码到指定路径)。
# --recursive:递归处理嵌套的子模块(如果子模块本身还包含其他子模块,也会一并初始化和更新)。

3、添加子模块

git submodule add <repo-url> [<path>]如果想要添加制定分支的子模块,使用git submodule add -b branch_name <repo-url> [<path>]

该命令会将指定的 Git 仓库作为子模块添加到当前仓库中。

<repo-url> 是子模块的仓库地址,<path> 是子模块在主仓库中的路径(可选,如果不指定,默认使用子模块仓库的名称作为路径)。

常见用法:将外部库作为子模块添加到项目中。

git submodule add https://github.com/example/test.git test1# 最后的test就是在你的仓库中对应的子仓库的名称,如果不写,将直接用子仓库的名称命名
# 比如,这里如果不写的最后的test1,子仓库的名称将直接用test命名

4、注意:

  1. .gitmodules本质上就是一个文本配置文件,他的内容是可以直接进行修改的,以下是其内容示例:

    [submodule "libs/utils"]path = libs/utilsurl = https://github.com/example/utils.gitbranch = dev
    

    其中包含了以下的内容:

    1. 子模块的名称(name):标识子模块的唯一名称(通常与路径一致)。
    2. 子模块的本地路径(path):子模块在主仓库中的存放目录。
    3. 子模块的远程仓库地址(url):子模块对应的远程代码仓库 URL(用于克隆或拉取更新)。使用http或者ssh方式都可以
    4. 子模块跟踪的分支(branch,可选):如果添加子模块时指定了 b 选项,这里会记录对应的分支名称。

二:更新子模块

由于 Git 子模块(submodule)在主仓库中记录的是一个特定的静态提交哈希(commit hash),而非分支引用,因此子模块的更新不会自动同步到主仓库,可能出现 “不及时更新” 的情况。简单来说,就是这是一个静态的commit,子仓库的更新不会同步到主仓库。因此就需要更新子模块,使得主仓库的内容保持最新。

如何让主仓库同步子模块的更新?

需要手动执行两步操作:

  1. 更新子模块到最新版本:在主仓库中,进入子模块目录拉取最新代码,或直接用命令拉取子模块跟踪分支的最新版本:

    git submodule update --remote <子模块路径>  # 拉取子模块跟踪分支的最新提交
    

    (如果子模块指定了跟踪分支,--remote 会拉取该分支的最新代码;否则默认拉取 master/main 分支)

  2. 提交主仓库对子模块的更新:子模块更新后,主仓库会检测到子模块的提交哈希发生了变化,此时需要提交这个变化到主仓库:

    git add <子模块路径>  # 暂存子模块的新提交哈希
    git commit -m "更新子模块 B 到最新版本"
    git push
    

这样,其他开发者拉取主仓库后,再执行 git submodule update 就能同步到子模块的最新版本了。

三:删除子模块

1. 查看子模块信息

git submodule

这个命令将直接列出当前仓库中的所有子模块,以及它们的提交哈希和路径。

示例:
setsuna@Shadow:~/RM/AutoAim/auto_aim_2026$ git submodule 13e2a7268a154053b1888c86c758bbbc5f453bd3 Orbit_tracker_general (heads/main)5bce0283751870f3763d50a3ed824ee3235ece59 aimer (heads/main)24080309cf53b9c08a9078590ddfce33b897cdd2 auto_aim_debugger (2408030)793089d4a2fb66ac75ed836ba1697100b02648b3 communicate_2025 (v2.0.0-alpha.1-3-g793089d)f571ed8202827d8fd4b156708342e31e154f2548 detector_26 (heads/dev-mao)4dffb5c53c032be137723f05883ddca08e2836e5 mindvision_camera (remotes/origin/dev)5e4a1667edef8f656ad3350382a5fb9512adc023 tracker_26 (remotes/tracker_26/main)

其中,前面的像13e2a7268a154053b1888c86c758bbbc5f453bd3 就是对应的提交哈希和路径

2.移除子模块

首先,你可以删除子模块的目录。在删除之前,你需要使用 git submodule deinit 命令将其标记为不再被 Git 追踪。例如,如果你想移除 submodule 子模块,你可以运行以下命令:

git submodule deinit submodule
# 这里后一个submodule是你实际的子模块的名称,这里用submodule作为示例

然后,你可以删除子模块的目录:

git rm submodule
# 同样这里submodule是你实际的子模块的名称

接着,你需要提交这些更改:

git commit -m "Remove submodule"

最后,将commit推送到远端

git push

其他命令

1.更新所有子模块

git submodule update --recursive --remote
  • --recursive:递归地更新所有子模块(包括子模块的子模块)。
  • --remote:从子模块的远程仓库拉取最新的更改。

注意:这里是根据.gitmodule中对应的分支进行拉取,如果其没有指定那么remote拉取的将会是main/master分支

2.检查子模块状态

git submodule status

显示子模块的当前状态,包括当前的提交哈希和路径,是否有未提交的更改。

常见用法:查看子模块的当前状态。

git submodule status

疑难杂症:

1.“分离头指针(detached HEAD)且有未跟踪提交”

示例:
setsuna@Shadow:~/RM/AutoAim/auto_aim_2026/tracker_26$ git checkout origin/main
警告:您正丢下 1 个提交,未和任何分支关联:51efa6b 在trackerinfo中添加发布的装甲板类型、数量和编号如果您想要通过创建新分支保存它,这可能是一个好时候。
如下操作:git branch <新分支名> 51efa6bHEAD 目前位于 5e4a166 add old tracker
  1. 出现原因:

    Git 的 HEAD 指针默认指向本地分支(如 maindev),而分支又指向具体的提交 —— 这是 “正常工作状态”。但当你做了以下操作时,HEAD 会直接指向某个提交哈希远程分支(如 origin/main,从而进入分离状态:

    • 直接 checkout 一个提交哈希:比如 git checkout 5e4a166(为了查看历史版本);
    • 直接 checkout 远程分支:比如你执行的 git checkout origin/mainorigin/main 是远程分支的本地镜像,不是本地分支);
    • 切换到标签(tag):标签本质是固定的提交,比如 git checkout v1.0

    简单说:只要你 checkout 的目标不是 “本地分支名”,就会进入分离头指针状态。

    这里我显然就是直接checkout这个提交哈希,因此我进入了分离头指针状态

  2. 如何解决

    1. 按提示创建一个新分支来跟踪它,避免丢失:

      git branch my_new_branch 51efa6b  # 创建新分支,指向 51efa6b
      git checkout my_new_branch       # 切换到新分支,此时提交被分支跟踪# 原来51efa6b这个提交哈希中的内容不会被修改,保持原样
      

      之后可以基于这个分支继续开发,或合并到其他分支(如 main

  3. 仓库拉取到本地后,git提交后,github远端仓库点击子仓库发现404(且不是网络原因和.gitmodule配置问题)

    建议:确认目前工作的分支是远程有的分支,主仓库中子模块的提交哈希为远程存在的版本

    排查步骤:

    1. 本地进入子模块目录,查看当前提交是否存在于远程:

      cd 子模块路径
      git fetch origin  # 拉取远程最新信息
      git log --oneline 你的提交哈希  # 检查本地提交是否在远程存在
      
      1. 假设你要检查的子模块提交哈希是 51efa6b(替换成你的实际哈希),执行:

        git log --oneline 51efa6b
        

        情况 1:提交存在于远程(正常)

        如果输出类似以下内容(显示该提交的信息),说明这个提交在远程仓库中存在:

        51efa6b 在trackerinfo中添加发布的装甲板类型、数量和编号
        # 前面的是提交哈希,后面是对应的commit消息
        

        (即使该提交不在 main 等默认分支,只要远程仓库的任何分支或历史中包含它,就会显示)

        情况 2:提交不存在于远程(异常)

        如果输出以下错误,说明这个提交仅存在于你的本地子模块仓库,远程仓库中没有(可能被删除或从未推送过):

        fatal: bad object 51efa6b

      若显示 “fatal: bad object”,说明该提交已从远程删除。

    2. 查看主仓库记录的子模块提交哈希:

      # 在主仓库根目录执行
      git submodule status  # 输出格式:<提交哈希> <子模块路径>
      

      若该哈希在子模块远程仓库中不存在,会导致 GitHub 404。

    解决办法:

    更新主仓库中子模块的提交哈希为远程存在的版本:

    1. 进入子模块目录,拉取远程最新代码并切换到有效分支:

      cd 子模块路径
      git checkout 有效的分支名  # 如 main、dev
      git pull origin 有效的分支名  # 拉取远程最新提交(确保该提交在远程存在)
      
    2. 返回主仓库,提交子模块的新哈希:

      cd ..
      git add 子模块路径
      git commit -m "更新子模块到远程存在的最新提交"
      git push origin 你的分支名
      

      现在应该可以解决404的问题了。

参考:

  1. 菜鸟教程git submodule命令
  2. 极客教程Git如何移除一个子模块
http://www.dtcms.com/a/517461.html

相关文章:

  • 西宁网站建设嘉荐君博l网页版游戏排行榜传奇
  • 如何联系网站管理员购买腾讯云 做网站
  • 我的家乡网站设计模板做网站时 404网页如何指向
  • 五合一建站网站怎么做可以合法让别人充钱
  • 网站搜索排名和什么有关系网站前端工资
  • 宁德市城乡住房建设厅网站北京网站设计优刻
  • dumpsys meminfo 中的 Lost RAM 怎样计算?
  • 长沙微网站网站建设策划书ol
  • Verilator 和 GTKwave联合仿真
  • 合肥网站建设久飞汽车门户网站源码
  • RHCE-时间服务
  • 海外短剧分销系统合规避坑:GDPR/PDPA数据存储与跨境分账税务处理
  • 问题排查 | 麒麟操作系统ntp服务报错Clock Unsynchronized
  • design网站海南科技网络有限公司
  • 做任务给佣金的网站有哪些网站设计导航栏高度
  • 移动网站建站做58同城这样的网站
  • 青岛建网站的公司有哪些建立学校网站
  • 网站建设所需费用明细直播网站怎么建设
  • 网站建设实践报告建站网站模板
  • 保险网站模板做网站的企划书
  • KVM 虚拟化环境
  • 天津平台网站建设推荐公司官网怎么弄
  • 国外建设短视频网站网站开发证书
  • 视频网站建设公司网站没有备案用什么cdn
  • web开发对于svg的简单应用
  • photoshop+做网站logo有谁认识做微网站的
  • xss-labs pass-09
  • 每日两题day20
  • 第二章的时间服务
  • 台州网站建设咨询做快三网站