1.应用场景:
现在App Project 有多个Module,每个Module是各自团队自己维护编写的,每个Module都有自己的git地址。 Project Main = Module A + Module B + Module C。
2.问题:
如果团队A想编写并测试自己的Module A,必须要三个Module都clone下来,然后自建一个project引入 Module B 和 Module C然后才能修改运行,改代码的时候必须注意哪些文件不能加入git跟踪,不然不能提交。三个团队都要这样,非常麻烦。而且每个仓库还有对应的branch和tag需要切换。就比如团队A需要Module A、B、C的某个分支的某个版本,这时候在clone下来后还要进行切分支切tag的操作,非常不方便。假设仓库不止三个而是更多…
3.解决方案:
有没有这么一种工具它clone仓库时按照规则一次性clone了Module A B C仓库并将A B C仓库都切到对应的分支和tag?所以问题就回归到怎么定制这些规制上了。
Repo刚好能使用manifest.xml来制定这套规制。
那么manifest.xml长这样:
<?xml version="1.0" encoding="UTF-8"?><manifest>
<remote name="remote1"
alias="origin"
fetch=".."
review="https://android-review.googlesource.com/" />
<remote name="remote2"
alias="origin"
fetch="git@github.com:group2/"
review="https://android-review2.googlesource.com/" />
<default revision="master"
remote="remote1"
sync-j="4" />
<project path="build/make" name="platform/build" groups="pdk" >
<copyfile src="core/root.mk" dest="Makefile" />
<linkfile src="CleanSpec.mk" dest="build/CleanSpec.mk" />
</project>
<project path="build/blueprint" name="platform/build/blueprint" groups="pdk,tradefed" revision="other_branch" remote="remote1"/>
<!-- ... -->
</manifest>
4. Repo Manifest
Repo 管理的核心就在于 Manifest,每个采用 repo 管理的复杂多仓库项目都需要一个对应的 manifest 仓库,如 AOSP 的 manifest ,此仓库用来存储所有子仓库的配置信息,repo 也是读取此仓库的配置文件来进行管理操作。里面的配置就是 xml 定义的结构,一般有两个主要的配置:子仓库用到的仓库地址(remote)、子仓库详细配置信息(project)。
remote
远程仓库地址配置,可以多个。
- Name:是git在服务器上的相对路径git remote 名称
- alias: 远程仓库别名,可省略,建议设为 origin, 设置了那么子仓库的 git remote 即为此名,方便不同的 name 下可以最终设置生成相同的 remote 名称
- fetch: 仓库地址前缀,即 project 的仓库地址为: remote.fetch + project.name
- pushurl: 一般可省略,省略了则直接用 fetch
- review: Gerrit code review 的地址,如果没有用 Gerrit 则不需要配置(也就不能用 repo upload 命令了)
- revision: 使用此 remote 的默认分支可以是commit id、branch name、tag name,利用branch name的特性,revision写branch name的话,那总可以下载到并且checkout出该branch上最新的代码
通过自由组合project和revision,就可以做出各种搭配的项目代码了。
project
子项目仓库配置,可以多个。 - path: repo sync 同步时,相对于根目录的子仓库文件夹路径
- name: 子仓库的 git 仓库名称
- group: 分组
- revision: 使用的分支名
- clone-depth: 仓库同步 Git 的 depth
copyfile - project 的子节点属性.
- src: project 下的相对路径
- dest: 整个仓库根路径下的相对路径
linkfile - project 的子节点属性,类似 copyfile,只是把复制文件变为创建链接文件。
default - project 没有设置属性时会使用的默认配置,常用的是 remote 和 revision。
官方文档:
https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
5. Repo 命令
repo init -u yout_manifest_git_url 初始化了你的项目 repo 工作区后,repo sync,你就可以进入正常的特性开发状态了。那么我们以开发一个 feature 为例,顺序说明下需要使用到的常用命令,也是我现在尝试使用的 repo workflow 了。
repo init
初始化。
repo init -u your_project_git_url
例如:
repo init -u git://codeaurora.org/platform/manifest.git -b release -m LA.BR.1.2.3-11610-8x09.0.xml –repo-url=git://codeaurora.org/tools/repo.git
其他常用可选参数:
- -b 选取的 manifest 仓库分支,默认 master
- m 选取的默认配置文件,默认 default.xml
- –depth=1 git clone 的深度,一般如在 Jenkins 上打包时可用,加快代码 clone 速度
- –repo-url=URL 使用自定义的 git-repo 代码,如前面说到的 fix 了 bug 的 git-repo
- –no-repo-verify 不验证 repo 的源码,如果自定义了 repo url 那么这个一般也加上
- repo sync 初始化好一个 repo 工作目录后下一步就是把代码同步下来了:
repo sync
同步完成后就会在当前目录下生成 manifest 里配置的各仓库和其对应目录。其他常用可选参数: - -f 不阻断同步,即一个 project 失败会继续下一个 project 同步
- –force-sync 如果需要,强制覆盖现有的 git 目录指向不同的对象目录。此操作可能会导致数据丢失
- -d 把项目回退到 manifest 里配置的分支
- -m 手动指定当前操作使用哪个 manifest 文件
- -t 使用对应 tag 里的 manifest 文件
同步完后你就可以用你的 IDE 打开项目了。此时,你需要根据当前的子仓库目录配置,在项目里处理下子仓库的依赖问题,比如 Android 项目,在 settting.gradle 里就需要根据此 repo 仓库的项目目录把子仓库 include 进来。
repo start
从 manifest 配置文件中指定的分支里,创建一个新的分支进行开发,如:
repo start your_feature_branch_name --all | [project1 project2]
后续如果发现还改动到了其他模块仓库那么再 start 一个对应 project 的分支
Work in progress
开发过程中需要用到的常用命令: - repo status: 跟 git status 类似,会把当前 repo 工作区的状态信息列出来
- repo diff: 同理 git diff
- repo forall -c : 在(所有)子仓库下执行命令,比如 repo 没有类似 git stash 的命令,利用 forall 就可以实现:repo forall -c git stash
- repo prune: 删除已经合并分支
- repo stage: 把文件添加到 index 表(暂存区)中
- repo manifest: 显示当前使用的 manifest 信息内容
repo upload
提交代码到 Gerrit code review 中,如果没有使用 Gerrit,则可以跟之前那样手动操作单个仓库 push 或者使用 repo forall -c git push xxx
https://git-repo.info/zh_cn/docs/