添加子模块
git submodule add https://github.com/chaconinc/DbConnector [可填具体目录]
此时 会多出 .gitmodules
文件 ,记录子模块
DbConnector是工作目录中的一个子目录,但 Git 还是会将它视作一个子模块。当你不在那个目录中时,Git 并不会跟踪它的内容, 而是将它看作子模块仓库中的某个具体的提交
git diff –cached –submodule 查看子模块变动
克隆含有子模块的项目
当你在克隆这样的项目时,默认会包含该子模块目录,但其中还没有任何文件
你必须运行两个命令:git submodule init
用来初始化本地配置文件,而 git submodule update
则从该项目中抓取所有数据并检出父项目中列出的合适的提交。
如果给 git clone
命令传递 --recurse-submodules
选项,它就会自动初始化并更新仓库中的每一个子模块
你已经克隆了项目但忘记了 --recurse-submodules
,那么可以运行 git submodule update --init
将 git submodule init
和 git submodule update
合并成一步。
如果还要初始化、抓取并检出任何嵌套的子模块, 请使用简明的 git submodule update --init --recursive
。
在包含子模块的项目上工作
从子模块的远端拉取上游修改
如果想要在子模块中查看新工作,可以进入到子目录中运行 git fetch
与 git merge
origin/master ,合并上游分支来更新本地代码。
git diff –submodule 查看新添加提交的列表
git config --global diff.submodule log //把--submdule 设置为默认行为,下次可以直接用git diff
git submodule update –remote // 自动从远程抓取合并,但是默认合并的是master 分支
如果你想跟踪其他分支比如dev分支:
git config -f .gitmodules submodule.DbConnector.branch dev // -f .gitmodules 选项 写入 .gitmodules, 其他人也能更新到这个配置
更新子模块后,运行 git status
,Git 会显示子模块中有“新提交”, 然后再提交主git,把这次更新体检
git config status.submodulesummary 1 // 设置这个后,git status 会显示子模块修改摘要
git pull
命令会递归地抓取子模块的更改,如上面第一个命令的输出所示。 然而,它不会 更新 子模块
git pull
命令添加 --recurse-submodules
自动化拉起合并所有子模块
# 将新的 URL 复制到本地配置中
$ git submodule sync --recursive
# 从新 URL 更新子模块
$ git submodule update --init --recursive
在子模块上工作
说明: 子模块是没有本地分支的,修改时都是在游离的HEAD 上更改,下次运行 git submodule update
时就会丢失
为了方便的在本地修改子模块,需要做以下几步:
先更新
$ cd DbConnector/ //进入子模块
$ git checkout stable // 切出版本
Switched to branch 'stable'
$ cd .. // 返回根目录
$ git submodule update --remote --merge //子模块合并远程
修改子模块
$ cd DbConnector/
$ vim src/db.c
$ git commit -am 'unicode support'
[stable f906e16] unicode support
1 file changed, 1 insertion(+)
此时我们发下远程子模块也有一个更改,就要去合并远程分支
$ cd ..
$ git submodule update --remote --rebase
First, rewinding head to replay your work on top of it...
Applying: unicode support
Submodule path 'DbConnector': rebased into '5d60ef9bbebf5a0c1c1050f242ceeb54ad58da94'
注意:1如果你忘记 --rebase
或 --merge
,Git 会将子模块更新为服务器上的状态。并且会将项目重置为一个游离的 HEAD 状态。 如果真的发生了也不要紧,你只需回到目录中再次检出你的分支(即还包含着你的工作的分支)然后手动地合并或变基 origin/stable
(或任何一个你想要的远程分支)就行了
2. 如果你没有提交子模块的改动,那么运行一个子模块更新也不会出现问题,此时 Git 会只抓取更改而并不会覆盖子模块目录中未保存的工作
3. 如果你做了一些与上游改动冲突的改动, 你可以进入子模块目录中然后就像平时那样修复冲突
发布子模块改动
说明: 主项目中提交并推送但并不推送子模块上的改动,其他尝试检出我们修改的人会遇到麻烦, 因为他们无法得到依赖的子模块改动。那些改动只存在于我们本地中。为了确保这不会发生,你可以让 Git 在推送到主项目前检查所有子模块是否已推送。 git push
命令接受可以设置为 “check” 或 “on-demand” 的 --recurse-submodules
参数。 如果任何提交的子模块改动没有推送那么 “check” 选项会直接使 push
操作失败。
$ git push --recurse-submodules=check
git config push.recurseSubmodules check
//让它成为默认行为
on-demand,它会使Git 会进入到 子模块中,然后在推送主项目前,推送了子模块。 如果那个子模块因为某些原因推送失败,主项目也会推送失败
合并子模块改动
子模块的问题
git checkout --recurse-submodules master //主项目切换分支时,使用这个可以使子模块目录处于正确的状态。 幸运的是,你可以通过 git config submodule.recurse true 设置 submodule.recurse 选项,是所有命令都带上这个默认配置,除了git clone
从子目录切换到子模块
假设项目内有一些文件在子目录中,你想要将其转换为一个子模块。 如果删除子目录然后运行 submodule add
,Git 会朝你大喊:
$ rm -Rf CryptoLibrary/
$ git submodule add https://github.com/chaconinc/CryptoLibrary
'CryptoLibrary' already exists in the index
你必须要先取消暂存 CryptoLibrary
目录。 然后才可以添加子模块:
$ git rm -r CryptoLibrary
$ git submodule add https://github.com/chaconinc/CryptoLibrary