前言
工作中经常有需要将一个项目作为其他项目的一部分的需求,这种情况是非常常见的,比如一些项目作为库或者框架供实际项目使用。通常情况下这不同的部分间虽然在一个项目中,但又需要分别管理。
现代的很多语言大多都有一些包管理方式可以来处理这个问题,但也有很多语言并没有包管理工具。这时候可以使用Git自带的 subtree
或者 submodule
来处理,甚至很多时候使用这个还更为方便。
这篇文章将介绍 subtree
相关内容。
操作方法
首先准备基础项目并进行一次提交:
mkdir MainProject # 创建项目目录
cd MainProject # 进入项目目录
touch README.md # 创建说明文档
git init # 初始化本地仓库
git add README.md # 暂存文档
git commit -m "first commit" # 进行初次提交
add
进行一次提交后就可以使用 subtree
将模板工程添加到项目中了:
git subtree add --prefix=<prefix> <repository> <ref>
下面是我的添加示例:
# --prefix=后面是子项目相对于主项目的目录
# --squash表示不拉取子项目历史信息,而只生成一条commit信息
git subtree add --prefix=subproject http://.../SubProject.git master --squash
添加的子项目内容会被拉取到所指定的相对主项目的目录中,接下来开发可以完全当作一个普通项目进行。在主项目推送到远程仓库的时候,所有内容也会被完整推送上去;在克隆主项目的时候所有内容也会一起克隆下来。
pull
如果有需要可以使用下面方式更新主项目中的子项目:
git subtree pull --prefix=<prefix> <repository> <ref>
# 比如下面这样
# git subtree pull --prefix=subproject http://.../SubProject.git master --squash
拉取时合并可能会出现冲突,按常规的手动处理即可:
push
主项目也可以直接修改子项目,并推送到子项目的远程仓库:
git subtree push --prefix=<prefix> <repository> <refspec>
split
上面介绍的都是在一个项目中使用已有的其它项目作为子项目, subtree
还可以将现有项目中部分目录分离为子项目:
git subtree split --prefix=<prefix> [<commit>]
后记
subtree
的一些基础使用就是上面哪些内容了,更多内容可以使用 git subtree -h
和 git subtree --help
进行查看。
Git中和 subtree
相似的有一个 submodule
,两者功能上有些相似,操作上有所区别,难说哪个好或者哪个不好。简单来说两者最大的区别是:
- 使用
subtree
时,子项目文件都会在包含在主项目中,主项目推送到远程仓库时子项目的文件也会被推送到远程仓库,因此克隆主项目时也会完整的克隆下来。这对于主项目的开发者来说可以完全当作平时一样操作就行。 - 使用
submodule
时,子项目的内容在主项目中只有一个引用的记录,主项目推送到远程仓库子项目的文件不会被推送到远程仓库,因此克隆主项目时还需要额外去拉取子项目。