“Git:子模块”的版本间差异
无编辑摘要 |
(→拉取) |
||
第31行: | 第31行: | ||
每添加一个子模块就会新增一条记录,如果是第一次添加Git子模块会自动生成。 | 每添加一个子模块就会新增一条记录,如果是第一次添加Git子模块会自动生成。 | ||
== | == 克隆 == | ||
当一个 git 项目包含子模块(submodule) 时,克隆这样的项目时,默认会包含该子模块目录,但子模块目录里面是空的。有两种方法解决: | 当一个 git 项目包含子模块(submodule) 时,克隆这样的项目时,默认会包含该子模块目录,但子模块目录里面是空的。有两种方法解决: | ||
# 如果项目已经克隆到了本地,执行下面的步骤: | # 如果项目已经克隆到了本地,执行下面的步骤: | ||
第49行: | 第49行: | ||
Note: | Note: | ||
* “--recursive”,用于的嵌套(项目中的子模块,子模块中的子模块)。 | * “--recursive”,用于的嵌套(项目中的子模块,子模块中的子模块)。 | ||
# | * <syntaxhighlight lang="bash" inline>git submodule init</syntaxhighlight> 和 <syntaxhighlight lang="bash" inline>git submodule update</syntaxhighlight> 可以合并成一步: | ||
*: <syntaxhighlight lang="bash"> | |||
git submodule update --init | |||
# 当有子模块嵌套时: | |||
git submodule update --init --recursive | |||
</syntaxhighlight> | |||
== 更新 == | |||
同时在主项目和子模块项目上与队员协作开发时: | |||
=== 从子模块的远端拉取上游修改 === | |||
在项目中使用子模块的最简模型,就是只使用子项目并不时地获取更新,而并不在你的检出中进行任何更改。<br/> | |||
# 如果想要在子模块中查看新工作,可以进入到目录中运行 git fetch 与 git merge,合并上游分支来更新本地代码: | |||
#: <syntaxhighlight lang="bash"> | #: <syntaxhighlight lang="bash"> | ||
git | # 进入子模块目录 | ||
cd modules/suba | |||
# 拉取更新 | |||
git fetch | |||
# 合并分支 | |||
git merge origin/master | |||
</syntaxhighlight> | </syntaxhighlight> | ||
# | # 如果不想在子目录中手动抓取与合并,那么可以采取另一种方式进行抓取和更新: | ||
#: <syntaxhighlight lang="bash"> | #: <syntaxhighlight lang="bash"> | ||
git submodule update --remote <submodule_name> | |||
git submodule update --remote | |||
</syntaxhighlight> | </syntaxhighlight> | ||
#: | #: 此命令默认更新并检出子模块仓库的 master 分支,如果需要操作其他分支: | ||
#: 需要修改分支配置【既可以在 .gitmodules 文件中设置 (这样其他人也可以跟踪它),也可以只在本地的 .git/config 文件中设置(本地有效)】。 | |||
#: <syntaxhighlight lang="bash"> | #: <syntaxhighlight lang="bash"> | ||
# 在.gitmodules 文件中设置,使用DbConnector模块的stable分支 | |||
$ git config -f .gitmodules submodule.DbConnector.branch stable | |||
# 拉取子模块更新 | |||
$ git submodule update --remote | |||
</syntaxhighlight> | |||
=== 从项目远端拉取上游更改 === | |||
作为主项目协作开发者来说,一般情况下会使用 git pull 来拉取项目更新,但是:'''默认情况下,git pull 命令会递归地抓取子模块的更改,然而,它不会更新子模块!'''这点可通过 git status 命令看到,它会显示子模块“已修改”,且“有新的提交”。<br/> | |||
为了完成更新,需要运行 git submodule update: | |||
<syntaxhighlight lang="bash"> | |||
# 拉取项目更新 | |||
git pull | |||
# 更新子模块代码 | |||
git submodule update --init --recursive | |||
</syntaxhighlight> | |||
# “--init”:是为了防止 提交中有新的子模块,未初始化而不能更新 的情况; | |||
# “--recursive”:是为了 子模块中有嵌套子模块 的情况; | |||
如果想要自动化以上过程: | |||
<syntaxhighlight lang="bash"> | |||
git pull --recurse-submodules | git pull --recurse-submodules | ||
</syntaxhighlight> | </syntaxhighlight> | ||
# | # 这会让 Git 在拉取后运行 git submodule update,将子模块置为正确的状态; | ||
# 如果要让 Git 总是以 --recurse-submodules 拉取,可以将配置选项 submodule.recurse 设置为 true; | |||
在为父级项目拉取更新时,还会出现一种特殊的情况:可能 .gitmodules 文件中记录的子模块的 URL 发生了改变(如,子模块项目改变了它的托管平台),此时,若父级项目引用的子模块提交不在仓库中本地配置的子模块远端上,那么执行 <code>git pull --recurse-submodules</code> 或 <code>git submodule update</code> 就会失败。 | |||
此时需要: | |||
<syntaxhighlight lang="bash"> | |||
# 将新的 URL 复制到本地配置中 | # 将新的 URL 复制到本地配置中 | ||
$ git submodule sync --recursive | $ git submodule sync --recursive |
2020年10月14日 (三) 18:56的版本
关于
有种情况我们经常会遇到:某个工作中的项目需要包含并使用另一个项目。 也许是第三方库,或者你独立开发的,用于多个父项目的库。 现在问题来了:你想要把它们当做两个独立的项目,同时又想在一个项目中使用另一个。
Git 通过子模块来解决这个问题。 子模块允许你将一个 Git 仓库作为另一个 Git 仓库的子目录。 它能让你将另一个仓库克隆到自己的项目中,同时还保持提交的独立。
可以使用 git submodule --help
查看所有相关命令。
git clone <repository> --recursive //递归的方式克隆整个项目
git submodule add <repository> <path> //添加子模块
git submodule init //初始化子模块
git submodule update //更新子模块
git submodule foreach git pull //拉取所有子模块
添加
关联项目子模块:
git submodule add https://github.com/test/subb.git modules/subb
- 默认情况下,子模块会将子项目放到一个与仓库同名的目录中,果你想要放到其他地方,那么可以在命令结尾添加一个不同的路径(如:modules/subb)。
项目根目录下有一个.gitmodules文件,即子模块关联文件,如:
[submodule "modules/suba"]
path = modules/suba
url = https://github.com/test/suba.git
每添加一个子模块就会新增一条记录,如果是第一次添加Git子模块会自动生成。
克隆
当一个 git 项目包含子模块(submodule) 时,克隆这样的项目时,默认会包含该子模块目录,但子模块目录里面是空的。有两种方法解决:
- 如果项目已经克隆到了本地,执行下面的步骤:
- 初始化本地子模块配置文件:
git submodule init
- 更新项目,抓取子模块内容:
git submodule update
- 初始化本地子模块配置文件:
- 对于未克隆项目,使用“--recursive”参数,可以自动初始化并更新每一个子模块。
git clone --recursive 仓库地址 # 或者 git clone --recurse-submodules 仓库地址
Note:
- “--recursive”,用于的嵌套(项目中的子模块,子模块中的子模块)。
git submodule init
和git submodule update
可以合并成一步:git submodule update --init # 当有子模块嵌套时: git submodule update --init --recursive
更新
同时在主项目和子模块项目上与队员协作开发时:
从子模块的远端拉取上游修改
在项目中使用子模块的最简模型,就是只使用子项目并不时地获取更新,而并不在你的检出中进行任何更改。
- 如果想要在子模块中查看新工作,可以进入到目录中运行 git fetch 与 git merge,合并上游分支来更新本地代码:
# 进入子模块目录 cd modules/suba # 拉取更新 git fetch # 合并分支 git merge origin/master
- 如果不想在子目录中手动抓取与合并,那么可以采取另一种方式进行抓取和更新:
git submodule update --remote <submodule_name>
- 此命令默认更新并检出子模块仓库的 master 分支,如果需要操作其他分支:
- 需要修改分支配置【既可以在 .gitmodules 文件中设置 (这样其他人也可以跟踪它),也可以只在本地的 .git/config 文件中设置(本地有效)】。
# 在.gitmodules 文件中设置,使用DbConnector模块的stable分支 $ git config -f .gitmodules submodule.DbConnector.branch stable # 拉取子模块更新 $ git submodule update --remote
从项目远端拉取上游更改
作为主项目协作开发者来说,一般情况下会使用 git pull 来拉取项目更新,但是:默认情况下,git pull 命令会递归地抓取子模块的更改,然而,它不会更新子模块!这点可通过 git status 命令看到,它会显示子模块“已修改”,且“有新的提交”。
为了完成更新,需要运行 git submodule update:
# 拉取项目更新
git pull
# 更新子模块代码
git submodule update --init --recursive
- “--init”:是为了防止 提交中有新的子模块,未初始化而不能更新 的情况;
- “--recursive”:是为了 子模块中有嵌套子模块 的情况;
如果想要自动化以上过程:
git pull --recurse-submodules
- 这会让 Git 在拉取后运行 git submodule update,将子模块置为正确的状态;
- 如果要让 Git 总是以 --recurse-submodules 拉取,可以将配置选项 submodule.recurse 设置为 true;
在为父级项目拉取更新时,还会出现一种特殊的情况:可能 .gitmodules 文件中记录的子模块的 URL 发生了改变(如,子模块项目改变了它的托管平台),此时,若父级项目引用的子模块提交不在仓库中本地配置的子模块远端上,那么执行 git pull --recurse-submodules
或 git submodule update
就会失败。
此时需要:
# 将新的 URL 复制到本地配置中
$ git submodule sync --recursive
# 从新 URL 更新子模块
$ git submodule update --init --recursive
编辑
切换子模块到开发分支,如:
cd modules/subb/
git checkout -b feature/some-change origin/dev
进行修改
推送
推送子模块修改到远程,如:
git commit -am 'test commit submodule'
git checkout dev
git merge feature/some-change
git push origin dev
git branch -d feature/some-change
提交子模块修改之后,主项目会有一些修改:
cd ../../
git diff
> diff --git a/subb b/subb
index 433859c..b78179a 160000
--- a/subb
+++ b/subb
@@ -1 +1 @@
-Subproject commit 433859c90e539d2a1b9fda27b32bef0d0acae9e6
+Subproject commit b78179adab252a524ff2a41d6407a7daa6dad34f
此时需要提交主项目该修改,才能在其他用户使用git submodule update时拉取新的代码:
git commit -am "test commit submodule"
git push origin dev
删除
git没有直接删除子模块的命令,所以只能逐步删除相关文件。
- 在版本控制中删除子模块:
git rm -r modules/subb
- 在编辑器中删除如下相关内容,也可以使用命令“vi .gitmodules”在vim中删除:
[submodule "modules/subb"] path = modules/subb url = https://github.com/test/subb.git branch = dev
- 在编辑器中删除如下相关内容,也可以使用命令“vim .git/config”在vim中删除:
[submodule "modules/subb"] path = modules/subb url = https://github.com/test/subb.git active = true
- 删除.git下的缓存模块:
rm -rf .git/modules/subb
- 提交修改:
git commit -am "delete subb" git push origin dev