主要内容:【Git 协同模型】
经典 Git 协同模型
集中式协同模型
可以像集中式版本控制系统那样使用 Git,在一个大家都可以访问到的服务器上架设 Git 服务器,每个人从该服务器克隆代码,本地提交推送到服务器上。
金字塔式协同模型
虽然理论上每个开发者的版本库都是平等的,但是会有一个公认的权威的版本库,这个版本库由一个或者多个核心开发者负责维护(具有推送的权限)。
开源社区逐渐发展出金字塔模型,而这也是必然之选。
Topgit 协同模型
笔者注:Topgit 是否已经过时?
卖主分支 Vendor Branch
是在版本库中专门创建一个和上游同步的分支,一旦有上游代码发布就捡入到卖主分支中。
子模组协同模型
创建子模组
git submodule add /path/to/repos/libA.git lib/lib_a |
.gitmodules
的内容:
cat .gitmodules |
克隆带子模组的版本库
git clone /path/to/repos/super.git /path/to/my/workspace/super-clone |
子模组的版本库并不会默认克隆,如果需要克隆出子模组型式引用的外部库,需要执行:
git submodule init |
在子模组中修改和子模组的更新
修改更新的方式和普通仓库一样。如果修改了子模块,要先推送子模块的修改,再推送主仓库,以防止其他人克隆 super 版本库、更新模组时因为找不到该子模组版本库相应的提交而导致出错。
查看子模组状态:
git submodule status |
子树合并
引入外部版本库
# 注册外部版本库 |
子目录方式合并外部版本库
# 在主分支,将分支 util-branch 读取到当前分支的一个子目录下 |
现在还不能忙着提交,因为如果现在进行提交就体现不出来两个分支的合并关系。需要使用 Git 底层的命令进行数据提交。
# 将暂存区的目录树保存下来 |
要手工创建一个合并提交,即新的提交要有两个父提交。这两个父提交分别是 master 分支和 util-branch 分支的最新提交。
echo "subtree merge" | \ |
需要把当前的 master 分支重置到此提交 ID:
git reset 62ae6cc3f9280418bdb0fcf6c1e678905b1fe690 |
操作繁琐,可使用下面 subtree
命令进行代替。
利用子树合并跟踪上游改动
git checkout util-branch |
Git Subtree
管理子项目
假设 P1 项目
、P2 项目
共用 S 项目
- 关联 S 项目
git subtree add --prefix=<S项目的相对路径> <S项目git地址> <分支> --squash |
--squash
意思是把 subtree
的改动合并成一次 commit
,这样就不用拉取子项目完整的历史记录。--prefix
之后的 =
等号也可以用空格。
- 更新代码
P1、P2 项目里各种提交 commit,其中有些 commit 会涉及到 S 目录
的更改,但是没关系。
- 提交更改到子项目
git subtree push --prefix=<S项目的相对路径> <S项目git地址> <分支> |
Git 会遍历 步骤 2
中所有的 commit
,从中找出针对 S 目录
的更改,然后把这些更改记录提交到 S 项目
的 Git 服务器上,并保留 步骤 2
中的相关 S 的提交
记录到 S仓库
中。
- 更新子目录
git subtree pull --prefix=<S项目的相对路径> <S 项目 git 地址> <分支> --squash |
拆分已有项目
需要从现有项目中抽取公共模块单独进行 Git 管理,假设已有 项目 P
抽取 项目 S
。
- 提交日志分离
git subtree split -P <S项目的相对路径> -b <临时branch> |
Git 会遍历所有的 commit,分离出与 S 项目的相对路径相关的 commit,并存入临时 branch 中。
- 创建子 repo
mkdir <S项目新路径> |
- 清理数据
cd P项目的路径 |
- 添加 subtree
git subtree add --prefix=<S项目的相对路径> <S项目git地址> <分支> --squash |
执行完第 2 步时,对应的目录已经剥离出来形成独立的项目了。第 3,4 步主要是把当前项目的对应的文件给删除,重新在 P 项目建立 Subtree。
tip:
推送到 GitHub Page:
git subtree push --prefix=dist origin gh-pages |
References
– EOF –