全部 / 工具 / 技术 · 2022年3月25日 0

Git 子模块问题

分支切换问题

正常情况下,切换分支命令:

git checkout branch-name

当你在含有子仓库下运行的时候会遇到如下问题:

也就是从一个有子仓库的分支切换到一个没有子仓库的分支,子仓库目录被带过去。注意:虽然目录被带过去了,但是与 submodule 相关的配置却没有带过去:

Git 2.13 以前的版本会比较麻烦:

$ git --version
git version 2.12.2

$ git checkout -b add-crypto
Switched to a new branch 'add-crypto'

$ git submodule add https://github.com/chaconinc/CryptoLibrary
Cloning into 'CryptoLibrary'...
...

$ git commit -am 'adding crypto library'
[add-crypto 4445836] adding crypto library
 2 files changed, 4 insertions(+)
 create mode 160000 CryptoLibrary

$ git checkout master
warning: unable to rmdir CryptoLibrary: Directory not empty
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	CryptoLibrary/

nothing added to commit but untracked files present (use "git add" to track)

移除那个目录并不困难,但是有一个目录在那儿会让人有一点困惑。 如果你移除它然后切换回有那个子模块的分支,需要运行 submodule update –init 来重新建立和填充。

$ git clean -fdx
Removing CryptoLibrary/

$ git checkout add-crypto
Switched to branch 'add-crypto'

$ ls CryptoLibrary/

$ git submodule update --init
Submodule path 'CryptoLibrary': checked out 'b8dda6aa182ea4464f3f3264b11e0268545172af'

$ ls CryptoLibrary/
Makefile	includes	scripts		src

新版的 Git(>= 2.13)通过为 git checkout 命令添加 –recurse-submodules 选项简化了所有这些步骤, 它能为了我们要切换到的分支让子模块处于的正确状态。

$ git --version
git version 2.13.3

$ git checkout -b add-crypto
Switched to a new branch 'add-crypto'

$ git submodule add https://github.com/chaconinc/CryptoLibrary
Cloning into 'CryptoLibrary'...
...

$ git commit -am 'adding crypto library'
[add-crypto 4445836] adding crypto library
 2 files changed, 4 insertions(+)
 create mode 160000 CryptoLibrary

$ git checkout --recurse-submodules master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

nothing to commit, working tree clean

更新问题

子模块更新

若子模块更新,则需要到所有的依赖子模块的主仓库去更新一遍,然后分别推送到远端仓库。

主仓库内更新

若你主仓库更新了子模块并提交到主仓库,然后构建系统自动构建并发布。若后面有开发伙伴没有更新子仓库,然后直接提交了代码,则会把你更新的子仓库还原为上一个版本。

好习惯避免类似问题:主仓库 git pull 后,接着 git status,子模块如有更新再 git submodule update 来同步一下主仓库中子模块的更新。

参考:

  1. https://git-scm.com/book/zh/v2/Git-%E5%B7%A5%E5%85%B7-%E5%AD%90%E6%A8%A1%E5%9D%97 (多看几遍)
  2. https://blog.devtang.com/2013/05/08/git-submodule-issues/
  3. https://juejin.cn/post/6844903920645455879
  4. https://liqiang.io/post/usage-and-tips-for-git-submodule
  5. https://www.jianshu.com/p/2393b6d53e42