Skip to main content

子模块

开始使用子模块

将一个已存在的 Git 仓库添加为正在工作的仓库的子模块

git submodule add <子模块仓库地址>

克隆含有子模块的项目 普通的git clone命令默认会包含子模块的目录,但其中还没有任何文件,需要执行 2 个命令:

# 初始化本地配置文件
git submodule init
# 从该项目中抓取所有数据并检出父项目中列出的合适的提交
git submodule update

更简单的方式:

1 2

会自动初始化并更新仓库中的每一个子模块

$ git clone --recursive <包含子模块的仓库地址> 在包含子模块的项目上工作 拉取上游修改 进入子模块目录执行:git fetch与git merge 直接在主项目目录下执行: 1 2

Git 默认会尝试更新所有子模块,所以如果有很多子模块的话,你可以传递想要更新的子模块的名字

$ git submodule update --remote <--rebase><--merge> 如果你忘记 –rebase 或 –merge,Git 会将子模块更新为服务器上的状态。并且会将项目重置为一个游离的 HEAD 状态 ​ 即便这真的发生了也不要紧,你只需回到目录中再次检出你的分支(即还包含着你的工作的分支)然后手动地合并或变基 origin/stable(或任何一个你想要的远程分支)就行了。

修改子模块的默认分支 1 2

例如要修改子模块的默认分支到develop上

$ git config -f .gitmodules submodule.子模块名.branch develop 其实就是修改了.gitmodule这个文件。提交以后,当其他人执行git submodule update --remote后,就会从子模块拉取 develop 这个新分支(但是还得手动进入子模块目录后切到 develop 分支- -)

发布子模块改动 如果我们在主项目中提交并推送但并不推送子模块上的改动,其他尝试检出我们修改的人会遇到麻烦,因为他们无法得到依赖的子模块改动。 那些改动只存在于我们本地的拷贝中。

所以我们可以:

  1. 让 Git 在推送到主项目前检查所有子模块是否已推送,如果任何提交的子模块改动没有推送那么 “check” 选项会直接使 push 操作失败:

1 $ git push --recurse-submodules=check 2. 让 Git 进入到每个子模块中然后在推送主项目前推送。如果那个子模块因为某些原因推送失败,主项目也会推送失败。

1 $ git push --recurse-submodules=on-demand 合并子模块改动 子模块技巧 子模块遍历 有一个 foreach 子模块命令,它能在每一个子模块中运行任意命令。 如果项目中包含了大量子模块,这会非常有用。

1 $ git submodule foreach 'git pull' 子模块的问题 问题一 在有子模块的项目中切换分支可能会造成麻烦。 如果你创建一个新分支,在其中添加一个子模块,之后切换到没有该子模块的分支上时,你仍然会有一个还未跟踪的子模块目录。

解决方案 如果你移除它然后切换回有那个子模块的分支,需要运行 submodule update –init 来重新建立和填充。

1 2 3 4 5 6 7 8 9 10 11 12 13 $ 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/ Makefileincludesscriptssrc 问题二 如果你在项目中已经跟踪了一些文件,然后想要将它们移动到一个子模块中,那么请务必小心,否则 Git 会对你发脾气。 假设项目内有一些文件在子目录中,你想要将其转换为一个子模块。 如果删除子目录然后运行 submodule add,Git 会朝你大喊:

1 2 3 $ rm -Rf CryptoLibrary/ $ git submodule add https://github.com/chaconinc/CryptoLibrary 'CryptoLibrary' already exists in the index 解决方案 你必须要先取消暂存 CryptoLibrary 目录。 然后才可以添加子模块:

1 2 3 4 5 6 7 8 $ git rm -r CryptoLibrary $ git submodule add https://github.com/chaconinc/CryptoLibrary Cloning into 'CryptoLibrary'... remote: Counting objects: 11, done. remote: Compressing objects: 100% (10/10), done. remote: Total 11 (delta 0), reused 11 (delta 0) Unpacking objects: 100% (11/11), done. Checking connectivity... done.