git submodule

Git Submodule 是什么?

git submodule 是 Git 内置功能:在一个主仓库(父项目)里,嵌入另一个独立 Git 仓库(子仓库)。

场景:项目需要复用公共组件、通用工具库、第三方模块,但是不想把源码直接复制进主仓库,方便单独维护、单独更新。

一、核心特点

  1. 子仓库是完成独立的 Git 仓库,拥有自己的提交、分支、远程地址;
  2. 主仓库不存子仓库源码,只记录子仓库的:远程地址 + 固定提交嘻哈;
  3. 主仓库更新不会影响子仓库,子仓库独立迭代。

二、使用场景

✅适合:

  1. 前端公共组件库、通用工具包(多个项目公用一套代码)
  2. 项目依赖第三方开源库,需要自定义修改源码
  3. 大型项目拆分多模块,各模块独立开发、单独发版

❌不适合: 单纯引入第三方依赖(优先 npm/yarn/pip 包管理器,比 submodule 简单)

三丶基础常用命令

1. 添加子模块

js 复制代码
// 格式:git submodule add 子仓库地址 本地存放路径
git submodule add https://gitee.com/xxx/common-ui src/components/common

执行后会生成:

  • .gitmodules 配置文件(记录所有子模块地址、路径)
  • 主仓库暂存该文件,提交到远程,其他人拉取后才能识别子模块

2. 首次拉取带 submodule 的项目

普通 git clone 只会拉下主仓库,子模块文件夹是空的,两种补全方式:

JS 复制代码
// 方式1:克隆时直接递归拉取子模块(推荐)
git clone --recursive https://xxx/main-project.git

// 方式2:已克隆完,手动初始化 + 拉取子模块
git submodule init
git submodule update

3. 更新子模块到最新代码 子仓库远端有新提交,同步到本地:

JS 复制代码
# 拉取所有子模块最新代码
git submodule update --remote

4. 子模块切换分支 默认 submodule 锁定在某一个 commit, 不绑定分支,如需跟踪分支:

JS 复制代码
// 添加时指定跟踪分支 
git submodule add -b main 仓库地址 路径 
// 已添加的模块修改跟踪分支 
git config -f .gitmodules submodule.模块名.branch main

5. 子模块提交、推送代码 子模块内部操作和普通 Git 完全一致:

  1. 进入子模块目录 cd src/components/common
  2. git add .git commit -m "修改组件"git push
  3. 返回主仓库,此时能看到子模块 commit 哈希变了,主仓库提交记录这个变更
JS 复制代码
git add src/components/common 
git commit -m "更新公共组件到最新版本" 
git push

6. 删除子模块(完整清理)

JS 复制代码
// 1. 删除配置 
git submodule deinit -f 子模块路径 
// 2. 删除仓库记录 
rm -rf .git/modules/子模块路径 
// 3. 删除本地文件夹 
git rm -rf 子模块路径 
// 4. 提交主仓库变更 
git commit -m "移除子模块"

四、关键机制:主仓库只锁定 commit

主仓库不会跟随子模块自动更新,只会固定绑定某一个提交哈希。 举个🌰:

  1. 你把子模块更新到新版本,主仓库必须单独提交一次,记录新哈希;
  2. 同事不拉取主仓库最新提交,他本地子模块依然停留在旧版本;
  3. 优势:项目版本稳定,不会因为子模块自动更新导致线上报错;
  4. 痛点:每次子模块升级,主仓库都要手动提交同步。

五丶常见坑与注意事项

  • 克隆后子模块为空
    • 忘记加 --recursive,执行 git submodule update --init --recursive 修复。
  • 子模块代码修改后,主仓库看不到变更
    • 子模块内必须先 push 到自己的远程,否则别人更新主仓库时拉不到你的修改。
  • 多人协作版本混乱
    • 禁止直接在主仓库随意 update --remote,子模块升级后一定要提交主仓库,同步给团队。
  • CI/ 打包部署遗漏子模块
    • 流水线克隆代码时必须加递归参数,否则打包缺失子模块代码。
相关推荐
摸着石头过河的石头1 小时前
从 Webpack 到 RSBuild:前端构建工具的进化之路
前端
疯狂的魔鬼1 小时前
告别 boolean 地狱:一个文件上传组件的状态机实践
前端·设计
竹林8181 小时前
Solana DApp 开发踩坑实录:从零用 @solana/web3.js 实现链上数据查询与交易签名
前端·javascript
狂师1 小时前
测试工程师的AI 技能库:推荐5个让你效率翻倍的Skills
前端·后端·测试
李明卫杭州1 小时前
Vue3 watch 与 watchEffect 深度解析
前端
CodeSheep1 小时前
DeepSeek正式官宣摇人,夯!
前端·后端·程序员
用户059540174461 小时前
Redis持久化踩坑实录:这个数据丢失Bug让我排查了6小时
前端·css
用户2136610035721 小时前
VueRouter进阶-动态路由与嵌套路由
前端·vue.js
梯度不陡1 小时前
Signal #17:Agent 开始进入组织系统
前端·javascript