git-submodule

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Git Submodule

Git Submodule

When to use this skill

何时使用该技能

  • Including external Git repositories within your main project
  • Managing shared libraries or modules across multiple projects
  • Locking external dependencies to specific versions
  • Working with monorepo-style architectures with independent components
  • Cloning repositories that contain submodules
  • Updating submodules to newer versions
  • Removing submodules from a project
  • 在主项目中引入外部Git仓库
  • 在多个项目间管理共享库或模块
  • 将外部依赖锁定到特定版本
  • 处理包含独立组件的单体仓库风格架构
  • 克隆包含子模块的仓库
  • 将子模块更新到新版本
  • 从项目中移除子模块

Instructions

操作指南

Step 1: Understanding submodules

步骤1:理解子模块

Git submodule은 메인 Git 저장소 내에 다른 Git 저장소를 포함시키는 기능입니다.
Key concepts:
  • 서브모듈은 특정 커밋을 참조하여 버전을 고정합니다
  • .gitmodules
    파일에 서브모듈 경로와 URL이 기록됩니다
  • 서브모듈 내 변경은 별도 커밋으로 관리됩니다
Git submodule是一种可以在主Git仓库中包含其他Git仓库的功能。
核心概念:
  • 子模块通过引用特定提交来固定版本
  • 子模块的路径和URL会记录在
    .gitmodules
    文件中
  • 子模块内的变更会作为独立提交进行管理

Step 2: Adding submodules

步骤2:添加子模块

기본 추가:
bash
undefined
基础添加:
bash
undefined

서브모듈 추가

子模块添加

git submodule add <repository-url> <path>
git submodule add <repository-url> <path>

예: libs/lib 경로에 라이브러리 추가

示例: 在libs/lib路径下添加库

git submodule add https://github.com/example/lib.git libs/lib

**특정 브랜치 추적**:
```bash
git submodule add https://github.com/example/lib.git libs/lib

**跟踪特定分支**:
```bash

특정 브랜치를 추적하도록 추가

添加时设置跟踪特定分支

git submodule add -b main https://github.com/example/lib.git libs/lib

**추가 후 커밋**:
```bash
git add .gitmodules libs/lib
git commit -m "feat: add lib as submodule"
git submodule add -b main https://github.com/example/lib.git libs/lib

**添加后提交**:
```bash
git add .gitmodules libs/lib
git commit -m "feat: add lib as submodule"

Step 3: Cloning with submodules

步骤3:克隆包含子模块的仓库

신규 클론 시:
bash
undefined
首次克隆时:
bash
undefined

방법 1: 클론 시 --recursive 옵션

方法1:克隆时使用--recursive选项

git clone --recursive <repository-url>
git clone --recursive <repository-url>

방법 2: 클론 후 초기화

方法2:克隆后初始化

git clone <repository-url> cd <repository> git submodule init git submodule update

**한 줄로 초기화 및 업데이트**:
```bash
git submodule update --init --recursive
git clone <repository-url> cd <repository> git submodule init git submodule update

**一键完成初始化和更新**:
```bash
git submodule update --init --recursive

Step 4: Updating submodules

步骤4:更新子模块

원격 최신 버전으로 업데이트:
bash
undefined
更新到远程最新版本:
bash
undefined

모든 서브모듈을 원격 최신으로 업데이트

将所有子模块更新到远程最新版本

git submodule update --remote
git submodule update --remote

특정 서브모듈만 업데이트

仅更新特定子模块

git submodule update --remote libs/lib
git submodule update --remote libs/lib

업데이트 + 머지

更新并合并

git submodule update --remote --merge
git submodule update --remote --merge

업데이트 + 리베이스

更新并变基

git submodule update --remote --rebase

**서브모듈 참조 커밋으로 체크아웃**:
```bash
git submodule update --remote --rebase

**切换到子模块引用的提交**:
```bash

메인 저장소가 참조하는 커밋으로 서브모듈 체크아웃

将子模块切换到主仓库引用的提交

git submodule update
undefined
git submodule update
undefined

Step 5: Working inside submodules

步骤5:在子模块内工作

서브모듈 내에서 작업:
bash
undefined
在子模块目录内操作:
bash
undefined

서브모듈 디렉토리로 이동

进入子模块目录

cd libs/lib
cd libs/lib

브랜치 체크아웃 (detached HEAD 해제)

切换分支(脱离分离头指针状态)

git checkout main
git checkout main

변경사항 작업

进行变更操作

... make changes ...

... make changes ...

서브모듈 내에서 커밋 및 푸시

在子模块内提交并推送

git add . git commit -m "feat: update library" git push origin main

**메인 저장소에서 서브모듈 변경 반영**:
```bash
git add . git commit -m "feat: update library" git push origin main

**在主仓库中同步子模块变更**:
```bash

메인 저장소로 이동

返回主仓库

cd ..
cd ..

서브모듈 참조 업데이트

更新子模块引用

git add libs/lib git commit -m "chore: update lib submodule reference" git push
undefined
git add libs/lib git commit -m "chore: update lib submodule reference" git push
undefined

Step 6: Batch operations

步骤6:批量操作

모든 서브모듈에 명령 실행:
bash
undefined
对所有子模块执行命令:
bash
undefined

모든 서브모듈에서 pull

在所有子模块中执行pull操作

git submodule foreach 'git pull origin main'
git submodule foreach 'git pull origin main'

모든 서브모듈에서 상태 확인

查看所有子模块的状态

git submodule foreach 'git status'
git submodule foreach 'git status'

모든 서브모듈에서 브랜치 체크아웃

在所有子模块中切换分支

git submodule foreach 'git checkout main'
git submodule foreach 'git checkout main'

중첩된 서브모듈에도 명령 실행

对嵌套子模块也执行命令

git submodule foreach --recursive 'git fetch origin'
undefined
git submodule foreach --recursive 'git fetch origin'
undefined

Step 7: Removing submodules

步骤7:移除子模块

서브모듈 완전 제거:
bash
undefined
完全移除子模块:
bash
undefined

1. 서브모듈 등록 해제

1. 取消子模块注册

git submodule deinit <path>
git submodule deinit <path>

2. Git에서 제거

2. 从Git中移除

git rm <path>
git rm <path>

3. .git/modules에서 캐시 제거

3. 从.git/modules中删除缓存

rm -rf .git/modules/<path>
rm -rf .git/modules/<path>

4. 변경사항 커밋

4. 提交变更

git commit -m "chore: remove submodule"

**예시: libs/lib 제거**:
```bash
git submodule deinit libs/lib
git rm libs/lib
rm -rf .git/modules/libs/lib
git commit -m "chore: remove lib submodule"
git push
git commit -m "chore: remove submodule"

**示例:移除libs/lib**:
```bash
git submodule deinit libs/lib
git rm libs/lib
rm -rf .git/modules/libs/lib
git commit -m "chore: remove lib submodule"
git push

Step 8: Checking submodule status

步骤8:查看子模块状态

상태 확인:
bash
undefined
查看状态:
bash
undefined

서브모듈 상태 확인

查看子模块状态

git submodule status
git submodule status

상세 상태 (재귀적)

查看详细状态(递归)

git submodule status --recursive
git submodule status --recursive

요약 정보

查看摘要信息

git submodule summary

**출력 해석**:
44d7d1... libs/lib (v1.0.0) # 정상 (참조 커밋과 일치) +44d7d1... libs/lib (v1.0.0-1-g...) # 로컬 변경 있음 -44d7d1... libs/lib # 초기화 안 됨
undefined
git submodule summary

**输出说明**:
44d7d1... libs/lib (v1.0.0) # 正常(与引用提交一致) +44d7d1... libs/lib (v1.0.0-1-g...) # 存在本地变更 -44d7d1... libs/lib # 未初始化
undefined

Examples

示例

Example 1: 프로젝트에 외부 라이브러리 추가

示例1:向项目中添加外部库

bash
undefined
bash
undefined

1. 서브모듈 추가

1. 添加子模块

git submodule add https://github.com/lodash/lodash.git vendor/lodash
git submodule add https://github.com/lodash/lodash.git vendor/lodash

2. 특정 버전(태그)으로 고정

2. 固定到特定版本(标签)

cd vendor/lodash git checkout v4.17.21 cd ../..
cd vendor/lodash git checkout v4.17.21 cd ../..

3. 변경사항 커밋

3. 提交变更

git add . git commit -m "feat: add lodash v4.17.21 as submodule"
git add . git commit -m "feat: add lodash v4.17.21 as submodule"

4. 푸시

4. 推送

git push origin main
undefined
git push origin main
undefined

Example 2: 서브모듈 포함 저장소 클론 후 설정

示例2:克隆包含子模块的仓库后进行配置

bash
undefined
bash
undefined

1. 저장소 클론

1. 克隆仓库

2. 서브모듈 초기화 및 업데이트

2. 初始化并更新子模块

git submodule update --init --recursive
git submodule update --init --recursive

3. 서브모듈 상태 확인

3. 查看子模块状态

git submodule status
git submodule status

4. 서브모듈 브랜치 체크아웃 (개발 시)

4. 切换子模块分支(开发时)

git submodule foreach 'git checkout main || git checkout master'
undefined
git submodule foreach 'git checkout main || git checkout master'
undefined

Example 3: 서브모듈을 최신 버전으로 업데이트

示例3:将子模块更新到最新版本

bash
undefined
bash
undefined

1. 모든 서브모듈을 원격 최신으로 업데이트

1. 将所有子模块更新到远程最新版本

git submodule update --remote --merge
git submodule update --remote --merge

2. 변경사항 확인

2. 查看变更

git diff --submodule
git diff --submodule

3. 변경사항 커밋

3. 提交变更

git add . git commit -m "chore: update all submodules to latest"
git add . git commit -m "chore: update all submodules to latest"

4. 푸시

4. 推送

git push origin main
undefined
git push origin main
undefined

Example 4: 공유 컴포넌트를 여러 프로젝트에서 사용

示例4:在多个项目中使用共享组件

bash
undefined
bash
undefined

프로젝트 A에서

在项目A中

프로젝트 B에서

在项目B中

공유 컴포넌트 업데이트 시 (각 프로젝트에서)

共享组件更新时(在每个项目中执行)

git submodule update --remote src/shared git add src/shared git commit -m "chore: update shared-components"
undefined
git submodule update --remote src/shared git add src/shared git commit -m "chore: update shared-components"
undefined

Example 5: CI/CD에서 서브모듈 처리

示例5:在CI/CD中处理子模块

yaml
undefined
yaml
undefined

GitHub Actions

GitHub Actions

jobs: build: steps: - uses: actions/checkout@v4 with: submodules: recursive # 또는 'true'
jobs: build: steps: - uses: actions/checkout@v4 with: submodules: recursive # 或 'true'

GitLab CI

GitLab CI

variables: GIT_SUBMODULE_STRATEGY: recursive
variables: GIT_SUBMODULE_STRATEGY: recursive

Jenkins

Jenkins

checkout scm: [ $class: 'SubmoduleOption', recursiveSubmodules: true ]
undefined
checkout scm: [ $class: 'SubmoduleOption', recursiveSubmodules: true ]
undefined

Advanced workflows

高级工作流

중첩 서브모듈 (Nested submodules)

嵌套子模块(Nested submodules)

bash
undefined
bash
undefined

중첩된 모든 서브모듈 초기화

初始化所有嵌套子模块

git submodule update --init --recursive
git submodule update --init --recursive

중첩된 모든 서브모듈 업데이트

更新所有嵌套子模块

git submodule update --remote --recursive
undefined
git submodule update --remote --recursive
undefined

서브모듈 URL 변경

修改子模块URL

bash
undefined
bash
undefined

.gitmodules 파일 수정

修改.gitmodules文件

git config -f .gitmodules submodule.libs/lib.url https://new-url.git
git config -f .gitmodules submodule.libs/lib.url https://new-url.git

로컬 설정 동기화

同步本地配置

git submodule sync
git submodule sync

서브모듈 업데이트

更新子模块

git submodule update --init --recursive
undefined
git submodule update --init --recursive
undefined

서브모듈을 일반 디렉토리로 변환

将子模块转换为普通目录

bash
undefined
bash
undefined

1. 서브모듈 내용 백업

1. 备份子模块内容

cp -r libs/lib libs/lib-backup
cp -r libs/lib libs/lib-backup

2. 서브모듈 제거

2. 移除子模块

git submodule deinit libs/lib git rm libs/lib rm -rf .git/modules/libs/lib
git submodule deinit libs/lib git rm libs/lib rm -rf .git/modules/libs/lib

3. 백업 복원 (.git 제외)

3. 恢复备份(排除.git目录)

rm -rf libs/lib-backup/.git mv libs/lib-backup libs/lib
rm -rf libs/lib-backup/.git mv libs/lib-backup libs/lib

4. 일반 파일로 추가

4. 作为普通文件添加

git add libs/lib git commit -m "chore: convert submodule to regular directory"
undefined
git add libs/lib git commit -m "chore: convert submodule to regular directory"
undefined

shallow 클론으로 공간 절약

使用浅克隆节省空间

bash
undefined
bash
undefined

얕은 클론으로 서브모듈 추가

通过浅克隆添加子模块

git submodule add --depth 1 https://github.com/large/repo.git libs/large
git submodule add --depth 1 https://github.com/large/repo.git libs/large

기존 서브모듈을 얕은 클론으로 업데이트

将现有子模块更新为浅克隆

git submodule update --init --depth 1
undefined
git submodule update --init --depth 1
undefined

Best practices

最佳实践

  1. 버전 고정: 서브모듈은 항상 특정 커밋/태그로 고정하여 재현 가능성 확보
  2. 문서화: README에 서브모듈 초기화 방법 명시
  3. CI 설정: CI/CD 파이프라인에서
    --recursive
    옵션 사용
  4. 정기 업데이트: 보안 패치 등을 위해 정기적으로 서브모듈 업데이트
  5. 브랜치 추적: 개발 중에는 브랜치 추적 설정으로 편의성 확보
  6. 권한 관리: 서브모듈 저장소 접근 권한 확인
  7. 얕은 클론: 대용량 저장소는
    --depth
    옵션으로 공간 절약
  8. 상태 확인: 커밋 전
    git submodule status
    로 상태 확인
  1. 版本固定: 子模块应始终固定到特定提交/标签,确保可复现性
  2. 文档说明: 在README中明确子模块的初始化方法
  3. CI配置: 在CI/CD流水线中使用
    --recursive
    选项
  4. 定期更新: 为了获取安全补丁等,定期更新子模块
  5. 分支跟踪: 开发期间设置分支跟踪以提升便利性
  6. 权限管理: 确认子模块仓库的访问权限
  7. 浅克隆: 对于大容量仓库,使用
    --depth
    选项节省空间
  8. 状态检查: 提交前使用
    git submodule status
    检查状态

Common pitfalls

常见陷阱

  • detached HEAD: 서브모듈은 기본적으로 detached HEAD 상태. 작업 시 브랜치 체크아웃 필요
  • 초기화 누락: 클론 후
    git submodule update --init
    필수
  • 참조 불일치: 서브모듈 변경 후 메인 저장소에서 참조 업데이트 필요
  • 권한 문제: 비공개 서브모듈은 SSH 키 또는 토큰 설정 필요
  • 상대 경로:
    .gitmodules
    의 상대 경로 사용 시 포크에서 문제 발생 가능
  • 삭제 불완전: 서브모듈 제거 시
    .git/modules
    캐시도 삭제 필요
  • 分离头指针: 子模块默认处于分离头指针状态,工作时需要切换到分支
  • 初始化遗漏: 克隆后必须执行
    git submodule update --init
  • 引用不一致: 子模块变更后,需要在主仓库中更新引用
  • 权限问题: 私有子模块需要配置SSH密钥或令牌
  • 相对路径: 在
    .gitmodules
    中使用相对路径可能会在复刻仓库时引发问题
  • 移除不彻底: 移除子模块时,还需要删除
    .git/modules
    中的缓存

Troubleshooting

故障排除

서브모듈이 초기화되지 않음

子模块未初始化

bash
undefined
bash
undefined

강제 초기화

强制初始化

git submodule update --init --force
undefined
git submodule update --init --force
undefined

서브모듈 충돌

子模块冲突

bash
undefined
bash
undefined

서브모듈 상태 확인

查看子模块状态

git submodule status
git submodule status

충돌 해결 후 원하는 커밋으로 체크아웃

解决冲突后切换到目标提交

cd libs/lib git checkout <desired-commit> cd .. git add libs/lib git commit -m "fix: resolve submodule conflict"
undefined
cd libs/lib git checkout <desired-commit> cd .. git add libs/lib git commit -m "fix: resolve submodule conflict"
undefined

권한 오류 (private repository)

权限错误(私有仓库)

bash
undefined
bash
undefined

SSH URL 사용

使用SSH URL

git config -f .gitmodules submodule.libs/lib.url git@github.com:org/private-lib.git git submodule sync git submodule update --init
undefined
git config -f .gitmodules submodule.libs/lib.url git@github.com:org/private-lib.git git submodule sync git submodule update --init
undefined

서브모듈 dirty 상태

子模块处于脏状态

bash
undefined
bash
undefined

서브모듈 내 변경사항 확인

查看子模块内的变更

cd libs/lib git status git diff
cd libs/lib git status git diff

변경사항 버리기

丢弃变更

git checkout . git clean -fd
git checkout . git clean -fd

또는 커밋하기

或提交变更

git add . git commit -m "fix: resolve changes" git push
undefined
git add . git commit -m "fix: resolve changes" git push
undefined

Configuration

配置

유용한 설정

实用配置

bash
undefined
bash
undefined

diff에서 서브모듈 변경 표시

在diff中显示子模块变更

git config --global diff.submodule log
git config --global diff.submodule log

status에서 서브모듈 요약 표시

在status中显示子模块摘要

git config --global status.submoduleSummary true
git config --global status.submoduleSummary true

push 시 서브모듈 변경 확인

推送时检查子模块变更

git config --global push.recurseSubmodules check
git config --global push.recurseSubmodules check

fetch 시 서브모듈도 함께 fetch

fetch时同时获取子模块内容

git config --global fetch.recurseSubmodules on-demand
undefined
git config --global fetch.recurseSubmodules on-demand
undefined

.gitmodules 예시

.gitmodules示例

ini
[submodule "libs/lib"]
    path = libs/lib
    url = https://github.com/example/lib.git
    branch = main

[submodule "vendor/tool"]
    path = vendor/tool
    url = git@github.com:example/tool.git
    shallow = true
ini
[submodule "libs/lib"]
    path = libs/lib
    url = https://github.com/example/lib.git
    branch = main

[submodule "vendor/tool"]
    path = vendor/tool
    url = git@github.com:example/tool.git
    shallow = true

References

参考资料