git submodule

添加子模块

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

Leave a Reply

Your email address will not be published. Required fields are marked *