Git 试用 submodule 管理子项目

  • 1 准备事项
  • 1.1 安装git
  • 1.2 配置用户名和邮箱
  • 1.3 仓库位置
  • 2 主仓库引入子仓库
  • 2.1 初始化子仓库
  • 2.2 引入子仓库到主仓库中
  • 2.3 删除外部的项目
  • 3 修改子项目更新后本地主仓库
  • 3.1 更新子项目
  • 3.2 更新主仓库
  • 4 如何同步别人的更改
  • 4.1 当其他人更新了子项目(未更新主项目)
  • 4.2 当其他人更新了子项目(并更新了主项目)
  • 4.3 当其他人新增了子项目
  • 5 在新的电脑上克隆主仓库



这两天学习了一下git的submodule子项目管理功能,记录一下学习的东西。

以下示例都是在win的powershell中,linux下一样

1 准备事项

1.1 安装git

win: 下载安装官网的git
centos: yum install git
ubuntu: apt install git

1.2 配置用户名和邮箱

打开powershell

# 配置用户名
git config --global user.name "myname" 
# 配置邮箱
git config --global user.email "mymail@139.com"

1.3 仓库位置

仓库的初始化位置,我这里测试时都是全新建的空仓库。

  • 主仓库: git@git.myserver.cn:project_name
  • 子仓库1: git@git.myserver.cn:library1
  • 子仓库2: git@git.myserver.cn:library2

2 主仓库引入子仓库

只需要第一次运行一次即可。

2.1 初始化子仓库

这里的初始化不是git init命令这种初始化。由于将子仓库添加到主仓库中需要确保子仓库不是空仓库,所以需要在子仓库中随便添加一些东西,让他不为空。其实根本原因可能是git init的仓库没有分支,所以无法添加,这里生成一个文件并推送,以确保远程仓库上主分支存在。

所以,如果你的子仓库不是空的,就不需要这一步。

# 找一个位置来存放git仓库,比如我的电脑上为 E:\git 
# 进入git目录
cd E:\git 

# 克隆子仓库
git clone git@git.myserver.cn:library1 library1

# 进入子仓库目录
cd library1

# 随意生成一个名为 init 的文件
echo 'init' > init

# git 暂存文件
git add . 

# git 提交更改
git commit -m 'init'

# git 更新到远程服务器
git push

以上便实现了克隆library1仓库,添加了名为 init 的文件,并推送到远程服务器。然后需要做的是将library1仓库添加到主仓库中

2.2 引入子仓库到主仓库中

# 克隆主仓库
git clone git@git.myserver.cn:project_name project_name 

# 进入主仓库
cd project_name

# 将library1仓库引入主仓库
git submodule add git@git.myserver.cn:library1 library1
# 如果子项目为空, 会无法添加到索引, 需要更新子项目不为空, 然后在这里的子项目pull后, 再运行 submodule add 

# 更新主仓库
# 查看git状态
git status

# git 暂存变更信息
git add . 

# git 提交更改
git commit -m '添加子项目 library1'

# git 推送到远程服务器
git push

以上便实现了将子项目引入到主仓库中。

2.3 删除外部的项目

由于已经将项目添加进了主仓库中,之前克隆的子仓库(E:\git\library1)可以删除了。当然这个随便了。

3 修改子项目更新后本地主仓库

这里指的是直接在主项目中修改。

在主仓库中的子项目,也可以作为一个独立的仓库看待,所以一般的add、commit、push操作都正常进行。然后再在主仓库中进行更新操作。

3.1 更新子项目

子项目路径为 E:\git\project_name\library1,子项目的更新方法与常规的操作一致。

# 进入子项目
cd E:\git\project_name\library1 

# 查看当前分支状态 *号标明的为当前所在分支
git branch -v

# 确保当前不在一个 detached 的分支下 我这里切换到主分支 再在主分支下进行一系列操作
git checkout master

# 这里作演示随便生成一个文件
echo 'test' > test.txt 

# push三连
git add .
git commit -m '测试'
git push

这样完成了子项目的更新。

3.2 更新主仓库

# 返回主仓库目录
cd E:\git\project_name 

# 查看状态
git status

# 暂存仓库变化
git add . 

# 提交
git commit -m '更新子仓库引用' 

# 推送到远程
git push 

# 查看更新后的状态
git status

我这里提示信息如下

PS E:\git\project_name\library1> git commit -m 'update git submodule '
[master 1c4b134] update git submodule 
 1 file changed, 1 insertion(+)
 
PS E:\git\project_name\library1> git push
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 12 threads
Compressing objects: 100% (4/4), done.
To git.myserver.cn:project_name/library1
   7271e29..1c4b134  master -> master

PS E:\git\project_name\library1> cd ..

PS E:\git\project_name> git add .

PS E:\git\project_name> git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   library1

PS E:\git\project_name> git commit -m 'update submodule library1'
[master af2a40f] update submodule library1
 1 file changed, 1 insertion(+), 1 deletion(-)

PS E:\git\project_name> git push
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 12 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 252 bytes | 252.00 KiB/s, done.
Total 2 (delta 1), reused 0 (delta 0)
To git.myserver.cn:project_name
   27deb61..af2a40f  master -> master

4 如何同步别人的更改

当其他人更新了子项目后 或者 添加了新的子项目,如何同步自己这边的主仓库。

4.1 当其他人更新了子项目(未更新主项目)

使用git submodule foreach 命令。这个命令其实就是加在常规的git命令前面,表示是对每个子项目执行,所以一般git操作前面都可以加这个前缀

# 进入主仓库目录
cd E:\git\project_name

# 切换子项目的分支为 master
git submodule foreach git checkout master 

# 获取所有子项目的更新
git submodule foreach git pull 

# 查看主仓库状态
git status 

# 暂存主仓库变化
git add .

# 提交
git commit -m 'update sub repo'

# 推送主仓库的变化到远端
git push

4.2 当其他人更新了子项目(并更新了主项目)

# 进入主仓库目录
cd E:\git\project_name

# 获取主仓库的更新
git pull 

# 更新submodule引用
git submodule update

4.3 当其他人新增了子项目

比如有人新增了子项目 library2

# 进入主仓库目录
cd E:\git\project_name

# 拉取主仓库的更新信息,主项目不会同步子项目的内容,所以目录 library2 为空
git pull 

# 同步library2的内容
git submodule update --init

运行提示信息如下

PS F:\git\project_name> git submodule update --init
Submodule 'library2' (git@git.myserver.cn:library2) registered for path 'library2'
Cloning into 'F:/git/project_name/library2'...
Submodule path 'library2': checked out '00f77e54a94c7a2803f6d36e2c7cdd7c29cf22a6'

5 在新的电脑上克隆主仓库

在新的电脑上使用,先确定一个仓库存放的位置,比如存放到 F:\git 中。

# 创建一个git目录
mkdir F:\git

# 进入git目录
cd F:\git 

# 克隆 main 主仓库到本地的 project_name 目录
git clone git@git.myserver.cn:project_name project_name 

# 进入主仓库
cd project_name 

# 初始化并更新子项目
git submodule update --init

我的提示信息如下

PS F:\git\project_name> git submodule update --init 
Submodule 'library1' (git@git.myserver.cn:project_name/library1) registered for path 'library1'
Submodule 'library2' (git@git.myserver.cn:project_name/library2) registered for path 'library2'
Cloning into 'F:/git/project_name/library1'...
Cloning into 'F:/git/project_name/library2'...
Submodule path 'library1': checked out 'a7fc9483a7b982e8f6529fc12b69dba5479508ae'
Submodule path 'library2': checked out '00f77e54a94c7a2803f6d36e2c7cdd7c29cf22a6'

目前能想到的场景就这么多。以后如果遇到新的再来更新。

子项目只需要添加一次,后面的日常更新主要参考3 4 5这几部分。

完毕。