git submodule

允许其他的仓库指定一个 commit 嵌入到仓库的子目录。

常见的使用场景:把仓库 B 作为 仓库 A 的子模块,放到仓库 A 的 modules/B 文件夹下,执行命令:

  1. git submodule add xxxB.git modules/B

此时生成一个文件 .gitmodule,内容如下:

  1. [submodule "modules/B"]
  2. path = modules/B
  3. url = xxx/B.git

将 .gitmodule 文件提交到远程仓库,然后其他人拷贝 A 仓库到本地,会发现 modules/B 文件是空的,此时需要执行如下命令,将子模块拷贝到本地:

  1. git submodule init
  2. git submodule update


需要注意的是,更新后每个子模块并非在指定分支上,而是关联最近一次 master 上的 commit id**
如果切换到 master 分支,执行如下命令,然后其余所有 git 操作可单独在各个模块上执行。

  1. git submodule foreach git checkout master

如果要将子模块强制同步到 master 的最新提交,执行命令:

  1. git submodule update --init --recursive --remote

git subtree

把仓库 B 的 dev 分支作为 仓库 A 的子模块,放到仓库 A 的 tree/B 文件夹下,执行命令:

  1. git subtree add --prefix=tree/B xxxB.git dev --squash

查看 git subtree 帮助,执行命令:

  1. git subtree -h

可以看到 —squash: merge subtree changes as a single commit ,加上 —squash 会多一次 commit 提交。
拉取仓库 B 的 dev 最新代码,执行命令:

  1. git subtree pull --prefix=tree/B xxxB.git dev --squash

提交代码到仓库 B 的 br_fix 分支,执行命令:

  1. git subtree push --prefix=tree/B xxxB.git br_fix

常见的使用场景:推送 master 分支的打包出来的文件到 github 的 gh-pages 分支:

  1. git subtree push --prefix=build origin gh-pages

区别

git submodule 类似于引用,而 git subtree 类似于拷贝。

目前官方推荐使用 git subtree,其优势是:由 git subtree 来维护的子项目代码,对于父项目来说是透明的,所有的开发人员看到的就是一个普通的目录,原来怎么做现在依旧那么做,只需要维护这个 subtree 的人在合适的时候去做同步代码的操作。


文章写于2018年8月