创建测试项目 准备环境 1 2 3 4 5 6 7 8 9 10 11 12 13 14 # 创建测试目录 mkdir git_submodule cd git_submodule # 创建本地裸仓库 mkdir repos cd repos git init --bare lib1.git git init --bare lib2.git git init --bare project1.git git init --bare project2.git # 创建工作区目录 cd .. mkdir ws cd ws
初始化测试项目 project1 和 project2 1 2 3 4 5 6 7 8 9 10 11 12 13 # 初始化 project1 git clone ../repos/project1.git cd project1 echo "project1" > project_infos.txt git add . git ci -m "init project1" # 初始化 project2 cd .. git clone ../repos/project2.git cd project2 echo "project2" > project_infos.txt git add . git ci -m "init project2"
初始化公共类库 lib1 和 lib2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # 初始化公共类库 lib1 cd .. git clone ../repos/lib1.git cd lib1 echo "This is lib1" > lib1_features git add . git ci -m "init lib1" git push origin master # 初始化公共类库 lib2 cd .. git clone ../repos/lib2.git cd lib2 echo "This is lib2" > lib2_features git add . git ci -m "init lib2" git push origin master
为 project1 添加 submodules ( lib1 和 lib2 ) 1 2 3 cd ../project1 git submodule add ../../repos/lib1.git libs/lib1 git submodule add ../../repos/lib2.git libs/lib2
此时,执行ls
命令,会发现多了个libs
目录
接着,查看状态,会发现lib1
、lib2
和另外一个新文件.gitmodules
都已经被加入了暂存区
先看一下lib1
和lib2
里面的文件的内容,跟公共类库内容一致
接着看一下.gitmodules
的内容,会发现 .gitmodules
记录了每个 Submodules 的引用信息(在当前项目的位置以及引用仓库的URL)
最后,执行如下命令,将更改提交并推送到远程仓库
1 2 git ci -a -m "add submodules[lib1,lib2] to project1" git push origin master
模拟开发人员 B 对 submodules 的修改 开发人员 B 克隆测试项目 project1 1 2 3 cd .. git clone ../repos/project1.git project1-b cd project1-b
执行git submodule
命令,会发现列出了所有子模块(Submodules),但是,hash 码前面有一个-
号,表明该子模块还没有检出
接下来,检出 project1-b 的所有子模块,执行git submodule init
命令
上一步,仅完成了子模块在当前项目的注册,想检出子模块的内容,还需要执行git submodule update
命令
开发人员 B 修改子模块 lib1 首先,进入lib1
所在的目录,并查看状态
要修改lib1
的文件,首先需要切换到相应的分支
修改、提交、推送
1 2 3 4 echo 'added by developer B' >> lib1_features git add . git ci -m "update lib1_features by developer B" git push origin master
开发人员 B 在项目(project1-b)目录中,提交更新并推送 回到project1-b
所在的目录,会发现project1-b
的状态发生了变化,很好理解,因为我们更改了子模块里面的文件,子模块也属于项目project1-b
本身
最后一步,在project1-b
项目中提交更新,并推送
1 2 3 git add . git ci -m "update libs/lib1 by developer B" git push origin master
在 project1 中同步开发人员 B 对 submodules 做的修改 1 2 cd ../project1 git pull origin master
查看状态,会发现libs/lib1
处于modified
很好理解,我们需要手动更新 submodules 的更新
至此,我们就在 project1 中成功同步了开发人员 B 对 submodules 所做的修改了
为 project2 添加 submodules ( lib1 和 lib2 ) 1 2 3 4 5 6 cd ../project2 git submodule add ../../repos/lib1.git libs/lib1 git submodule add ../../repos/lib2.git libs/lib2 git add . git ci -m "add submodules[lib1,lib2] to project2" git push origin master
在 project2 中修改 lib1 和 lib2 并同步到 project1 中 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 # 在 lib1 中添加一个文件 README cd libs/lib1 echo "This is lib1 readme contents" > README git add . git commit -m "add README for lib1" git push origin master cd .. git add . git commit -m "update lib1 - add README" # 修改 lib2 中的 lib2-features 文件 cd libs/lib2 echo "some new feature" >> lib2_features git add . git ci -m "add some new feature into lib2_features" git push origin master cd ../../ git add . git commit -m "update lib2 - add some new features" # 推送 project2 的修改 git push origin master # 在 project1 中更新 lib1 和 lib2 的最新修改,并推送 cd ../project1 git pull origin master cd libs/lib1 git co master git pull origin master cd ../lib2 git pull cd ../../ git ci -a -m "update lib1 and lib2 to new version" git push
更新 project1-b 项目的子模块 根据以上的操作,我们总结出来了修改并更新子模块的基本流程
切换到子模块的某个分支
修改子模块
提交子模块的修改
推送子模块的修改
在项目目录提交子模块的修改
在项目目录推送子模块的修改
在其他项目的项目目录新(pull)子模块的修改
在其他项目的子模块目录中依次更新(pull)
在其他项目的项目目录中提交并推送修改
事实上,修改子模块、提交和推送的操作确实需要一步步细致地进行,不过在其他项目中,更新对子模块的修改,步骤太繁琐。幸运的是我们可以使用git submodule foreach git pull
命令,一步到位完成各子模块的同步更新。
最后,在项目目录中提交并推送
1 2 3 4 5 cd ../project1-b git pull git submodule foreach git pull git ci -a -m "update libs1 and libs2 to new version" git push origin master
新成员加入团队,一次性克隆项目和 submodules 根据已有知识,我们可以这样操作
1 2 3 git clone /path/to/repos/foo.git git submodule init git submodule update
幸运的是,我们可以一行命令搞定
1 git clone --recursive ../repos/foo.git
–recursive
参数的含义:可以在克隆项目时同时克隆关联的submodules
移除 submodules 1 2 3 4 git submodule deinit libs/lib1 git rm libs/lib1 git ci -m "remove libs/lib1" git push origin master