何时须要 Subtree ?
一、当多个项目共用同一坨代码,而这坨代码跟着项目在快速更新的时候
二、把一部分代码迁移出去独立为一个新的 git 仓库,但又但愿可以保留这部分代码的历史提交记录。php
有赞微商城曾经是一个很大的先后端代码都包含在里面的 Git 项目,为了方便管理咱们把先后端代码分离成2个 Git 仓库,进而再做分项目拆分红多个Git 仓库。前端
因而,就须要有好的方式同步各个项目共用的Css库、JS库、PHP库(他们都是以独立的 Git 仓库的形式存在)。并且因为开发节奏极快,咱们须要这些库是能够在不一样项目间双向同步的而不是单向同步。并且,最好能作到被迁移的这部分代码在新的git仓库里保留原有的历史提交记录。node
举个栗子:A项目须要在给某个子项目W里添加一个文件,最方便的方式天然是直接在A项目里改W子项目对应的目录里的代码,而后测试经过后,把这个更改提交到W子项目的 Git仓库里。若是这时候还要先单独更新W子项目的代码而后提交到 Git 服务器,再在A项目里把W子项目的代码更新过来,显然是很麻烦的,更麻烦的是若是发现代码有bug,还得再走一遍这个流程。git
虽然 npm、composer、maven 等更侧重于包的依赖管理,以上几个方案都是可以作到在不一样项目中同步同一块代码的,但无法双向同步,更适用于子项目代码比较稳定的情形。github
Git Submodule 和 Git Subtree 都是官方支持的功能,不具备依赖管理的功能,但能知足咱们的要求。Git Subtree相对来讲会更好一些 。npm
用一句话来描述 Git Subtree 的优点就是:后端
经由 Git Subtree 来维护的子项目代码,对于父项目来讲是透明的,全部的开发人员看到的就是一个普通的目录,原来怎么作如今依旧那么作,只须要维护这个 Subtree 的人在合适的时候去作同步代码的操做。浏览器
它是怎么作到的呢?简单说下原理bash
首先,你有两个伟大的项目——咱们叫他P1项目、P2项目,还有一个牛逼的要被多个项目共用的项目——咱们叫他S项目。咱们经过简要讲解使用Subtree来同步代码的过程来解释Subtree的原理服务器
经过
cd P1项目的路径
git subtree add --prefix=用来放S项目的相对路径 S项目git地址 xxx分支 12复制代码
这样的命令,把S项目(咱们姑且叫他S项目)的代码下载到--prefix所指定的目录——咱们姑且叫他S目录把,并在P1项目里自动产生一个commit(就是把S目录的内容提交到P1项目里)。
你们在P1项目里各类提交commit,其中有些commit会涉及到S目录的更改,正如前面提到的,这是没任何关系的,你们也不会感觉到有任何不同。
关键的地方来了: 当维护这个S项目 Subtree 的人但愿把最近这段时间对S目录的更改提交到S项目的 Git 服务器上时,他执行一段相似于这样的命令:
cd P1项目的路径
git subtree push --prefix=S项目的路径 S项目git地址 xxx分支 12复制代码
Git 会遍历全部的commit,从中找出针对S目录的更改,而后把这些更改记录提交到S项目的Git服务器上
OK,如今S项目有大量的新代码了,P2项目也想使用这些新代码,维护P2这个Subtree的人只要执行:
git subtree pull --prefix=S项目的路径 S项目git地址 xxx分支 1复制代码
这样就能够将P2项目里S项目目录里的内容更新为S项目xxx分支的最新代码了。
假设,你要在各个项目里的
这个目录对
这个项目作Subtree
1.首先必须确保各个项目已经添加zenjs 这个 remote(关于remote是什么能够看这里):
git remote add zenjs http://github.com/youzan/zenjs.git 1复制代码
2.将zenjs添加到各个项目里
git subtree add --prefix=components/zenjs zenjs master 1复制代码
3.各项目更新zenjs代码的方法:
git subtree pull --prefix=components/zenjs zenjs master 1复制代码
4.各项目提交zenjs代码的方法:
git subtree push --prefix=components/zenjs zenjs hotfix/zenjs_xxxx 1复制代码
这会在远程的zenjs的仓库里生成一个叫 hotfix/zenjs_xxxx 的的分支,包含了你过去对components/zenjs 全部的更改记录
这样其余工程就能够更新到你提交的代码了。
有人可能会问,只用master分支,无论版本,太有风险了。
对的,正如咱们前面说到的那样,subtree的方案适用的场景是:各个项目共用一个库,而这个库正在快速迭代更新的过程当中。若是追求稳定,只须要给库拉出一个如v0.1.0这样的版本号命名的稳定分支,subtree只用这个分支便可。
咱们如今使用的方式就是:A项目常常会对zenjs作更新,因此A项目用subtree来双向同步;B项目只是使用,因此用bower用来按版原本更新代码。
高阶功能: 从新split出一个新起点(这样,每次提交subtree的时候就不会从头遍历一遍了)
git subtree split --rejoin --prefix=components/zenjs --branch new_zenjs
git push zenjs new_zenjs:master 复制代码