[TOC]
# 使用場景
基于公司的項目會越來越多,常常需要提取一個公共的類庫提供給多個項目使用,但是這個`library`怎么和`git`在一起方便管理呢?
我們需要解決下面幾個問題:
* 如何在 git 項目中導入`library`庫?
* `library`庫在其他的項目中被修改了可以更新到遠程的代碼庫中?
* 其他項目如何獲取到`library`庫最新的提交?
* 如何在 clone 的時候能夠自動導入`library`庫?
解決以上問題,可以考慮使用 git 的`Submodule`來解決。
# 什么是 Submodule?
submodule 是一個多項目管理工具,可以在當前 repo 中包含其它 repos、作為當前 repo 的子目錄使用,同時能夠保持 repos 之間的獨立。
子項目擁有自己的 獨立的`commit`,`push`,`pull`,而與主項目互不干擾。
主項目只需要記錄子項目的地址和所需要的 `commit id`,通過地址和 `commit id` 就能夠得到對應的子項目。
# 使用 Submodule
使用 git 命令可以直接添加 Submodule:
```shell
# 在當前 repo 添加一個子模塊,使用 git status 命令可以看到。
$ git submodule add git@github.com:xxx/xxx.git path/to/xxx
```
命令執行完成,會在當前工程根路徑下生成一個名為“.gitmodules”的文件,其中記錄了子模塊的信息。添加完成以后,再將子模塊所在的文件夾添加到工程中即可。
修改子模塊文件后,在當前 repo 執行`git status`只會看到有模塊的 changes,而不是具體子模塊文件:
```
diff --git a/path/to/submodule b/path/to/submodule
--- a/path/to/submodule
+++ b/path/to/submodule
@@ -1 +1 @@
-Subproject commit xxxxxxx
+Subproject commit xxxxxxx-dirty
```
# 克隆 Submodule
有兩種方式:
* 采用遞歸的方式(`--recursive-submodules`)克隆整個項目
* 克隆父項目,再更新子項目(`--recursive-submodules`)
1. 采用遞歸參數`--recurse-submodules` (With version 2.13 of Git and later,`--recurse-submodules`can be used instead of`--recursive`)
```shell
$ git clone --recurse-submodules https://github.com/xi-editor/xi-mac
```
2. 第二種方法先 clone 父項目,再初始化子項目
```shell
$ git clone https://github.com/xi-editor/xi-mac
$ cd xi-mac
$ git submodule update --init --recursive
```
# 其他
Just to clarify for everyone.`git submodule update --recursive`looks to see which revision the parent repository has stored for each submodule, then checks out that revision in each submodule. It does**NOT**pull the latest commits for each submodule.`git submodule foreach git pull origin master`or`git pull origin master --recurse-submodules`is what you want if you intend to update each submodule to the latest from their origin repositories. Only then will you get pending changes in the parent repo with updated revision hashes for submodules. Check those in and you're good.
Note that neither`git pull --recurse-submodules`nor`git submodule update --recursive`does**not**initialize newly added submodules. To initialize them you need run`git submodule update --recursive --init`. Quote from[manual](https://git-scm.com/docs/git-submodule):*If the submodule is not yet initialized, and you just want to use the setting as stored in .gitmodules, you can automatically initialize the submodule with the --init option.*
# `.gitattributes`
也可以為所有Git庫設置統一的gitattributes文件:
~~~html
git config --get core.attributesFile
git config --global --get core.attributesFile
~~~
# Reference
[How to “git clone” including submodules?](https://stackoverflow.com/questions/3796927/how-to-git-clone-including-submodules)
[Easy way to pull latest of all git submodules](https://stackoverflow.com/questions/1030169/easy-way-to-pull-latest-of-all-git-submodules)
[使用 Git Submodule 管理子模塊](https://segmentfault.com/a/1190000003076028)
[Git - 子模塊](https://git-scm.com/book/zh/v2/Git-%E5%B7%A5%E5%85%B7-%E5%AD%90%E6%A8%A1%E5%9D%97)
`man git-submodule`
[git submodules - Git diff says subproject is dirty - Stack Overflow](https://stackoverflow.com/questions/4873980/git-diff-says-subproject-is-dirty)
- 介紹
- 1. Get Git - 安裝并且設置Git
- 2. Repository - 建立一個本地的repository
- 3. Commit to it - 檢查狀態、新增或修改commits
- 4. GitHubbin - 注冊GitHub帳號
- 5. Remote Control - 將repository做本地和遠程的連接
- 6. Forks and Clones - Fork和clone一個開源的計劃
- 7. Branches aren't just for Birds - 建立一個feature branch
- Git分支開發模型
- 8. It's a Small World - 邀請并和別人合作
- 9. Pull, Never Out of Date - 利用Push和pull來和GitHub.com同步
- 10. Requesting You Pull Please - 建立一個pull request
- 11. Merge Tada - Merge和刪除branches
- 學會 GitHub
- GitHub 使用指南
- git 與 github 模板配置
- GitHub Actions
- 實用技巧
- Git Flow
- Submodule子模塊
- 工作記錄
- 常用命令
- 幫助
- 資源
- 解疑答惑