Google Git-Repo (Android)多仓库项目管理

简介: 前言项目模块化/组件化之后各模块也作为独立的 Git 仓库从主项目里剥离了出去,各模块各自管理自己的版本。正常 Android 项目,各剥离出去的子模块仓库则通过 Maven 仓库 来管理,然后和引入第三方库一样依赖到主项目里。

前言

项目模块化/组件化之后各模块也作为独立的 Git 仓库从主项目里剥离了出去,各模块各自管理自己的版本。正常 Android 项目,各剥离出去的子模块仓库则通过 Maven 仓库 来管理,然后和引入第三方库一样依赖到主项目里。这种状态下的项目迭代带来的问题会是:需要频繁发布子模块的 版本并需要把修改的版本提交 Merge Request 到主模块里,尤其像我们一周一版的快速迭代的情况下,问题尤为凸显。此外还有个问题就是 Debug/断点 会变得不太方便,因为可能子模块的源码并未发到 Maven 上。

在上面所说的状态下工作了一段时间后,需要找到个方案来解决这个问题。遂尝试在多仓库管理的方向上尝试。支持 Git 多仓库的管理工具也有好几个:git-repogit-submodulegitslavegit-subtree,看了一番,除了 git-repo 外的几个要么 子模块需要手动指定本地仓库路径、要么 主仓库与子仓库会产生污染 且操作不够简便化。所以最终就采用了 Google 的 Git-repo(Repo)

Git-repo

Repo 是对 Git 构成补充的多(可以巨多的那种)代码库管理工具,简单说就是使用 Python 在 Git 基础上开发的一系列脚本命令。当前整个 Android 项目(AOSP)就是通过 repo 来管理,最新版本的仓库大约 七百多个,可见 Repo 在多仓库的代码管理和版本管理上是可以支撑现有我们的项目的。接下来描述分析下迁移使用 Repo 的过程和一些解释。

环境准备

准备好梯子,把 repo 装到系统里:

 

1

2

3

4

5

6

7

 

mkdir ~/bin

PATH=~/bin:$PATH # 自己加到 ~/.zshrc or ~/.bashrc or /etc/profile 里

curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo

chmod a+x ~/bin/repo

# 最后 source 下环境变量

然后就可以操作项目了,如初始化 AOSP 项目:

 

1

 

repo init -u https://android.googlesource.com/platform/manifest -b android-4.0.1_r1

Manifest

Repo 管理的核心就在于 Manifest,每个采用 repo 管理的复杂多仓库项目都需要一个对应的 manifest 仓库,如 AOSP 的 manifest ,此仓库用来存储所有子仓库的配置信息,repo 也是读取此仓库的配置文件来进行管理操作。里面的配置就是 xml 定义的结构,一般有两个主要的配置:子仓库用到的仓库地址(remote)、子仓库详细配置信息(project)。举例如下:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

 

<?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>

解释下常用的各节点:

remote

远程仓库地址配置,可以多个。

  • name: 名字,也用于子仓库的 git remote 名称(.git/config 里的 remote)
  • alias: 别名,可省略,建议设为 origin, 设置了那么子仓库的 git remote 即为此名,方便不同的 name 下可以最终设置生成相同的 remote 名称
  • fetch: 仓库地址前缀,即 project 的仓库地址为: remote.fetch + project.name
  • pushurl: 一般可省略,省略了则直接用 fetch
  • review: Gerrit code review 的地址,如果没有用 Gerrit 则不需要配置(也就不能用 repo upload 命令了)
  • revision: 使用此 remote 的默认分支

这里的 fetch 遇到个坑git@github.com:group2/ 这样 git scheme 开头的地址会有问题(ssh/https 的正常),最终子仓库在本地的 remote 地址一直是 manifest 的地址拼上 fetch 再加 project 的 name (manifest.git_path + remote.fetch + project.name)。最终发现是 git-repo 里的代码 manifest_xml.py 有问题,需要 fix 下,简单的把 78 行注释掉,然后推到自己的仓库,指定下系统环境变量:

 

1

2

 

REPO_URL=your_fix_git-repo_git_url

# repo 脚本会使用此变量的地址

 

project

子项目仓库配置,可以多个。

  • path: repo sync 同步时,相对于根目录的子仓库文件夹路径
  • name: 子仓库的 git 仓库名称
  • group: 分组
  • revision: 使用的分支名
  • clone-depth: 仓库同步 Git 的 depth

copyfile

project 的子节点属性.

  • src: project 下的相对路径
  • dest: 整个仓库根路径下的相对路径

linkfile

project 的子节点属性,类似 copyfile,只是把复制文件变为创建链接文件。

default

project 没有设置属性时会使用的默认配置,常用的是 remote 和 revision。

其他

其他现在暂时用的较少,详细完整的 manifest 格式说明请看官方文档
了解了 Repo 下的 Manifest 配置仓库的概念后就可以根据自己的项目来创建了,Just do it!

local_manifest

local_manifest 简单说就是一个比 repo init 时设置的 manifest 有更高优先级的本地配置,一般用在不改动远程 manifest 配置又想设置到本地的专属配置时用得到。版本高一点的 repo 下,在工作根目录新建配置文件即可: .repo/local_manifests/local_manifest.xml

有一点需要注意的是如果需要覆盖主 manifest 文件已有 project 的配置那么需要先 remove-project才行,不然会报错:

 

1

 

fatal: duplicate path project_name in .repo/manifest.xml

fix :

 

1

2

3

 

<remove-project name="project_name" />

<!-- 再重写 project 配置 -->

<project path="xxx" name="xxx" revision="xxxx" remote="xxxx" />

Repo 命令

repo init -u yout_manifest_git_url 初始化了你的项目 repo 工作区后,repo sync,你就可以进入正常的特性开发状态了。那么我们以开发一个 feature 为例,顺序说明下需要使用到的常用命令,也是我现在尝试使用的 repo workflow 了。

repo init

初始化。

 

1

 

repo init -u your_project_git_url

其他常用可选参数:

  • -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 工作目录后下一步就是把代码同步下来了:

 

1

 

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 配置文件中指定的分支里,创建一个新的分支进行开发,如:

 

1

 

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

Other

其他更详细的参考可以查看 Repo 命令参考资料

Workflow

上面一节介绍的 repo 命令的顺序过程可以说就是一个常用的 repo 工作流程,AOSP 给的开发流程可以先看下:
开发

Git 和 Repo 快速参考表

Git 和 Repo 快速参考表

那么根据上一节的介绍,给出下当前尝试使用的 repo-workflow 的图示:

Git-repo workflow

Git-repo workflow

具体到每个仓库来说,主仓库位置原有的 git workflow 不用变,各子仓库新增 devbuild 分支,那么对应的合版打包与发版打包对应 Manifest 固定的分支配置就行,如果没有项目删减,那么合版与发版时的子模块仓库版本也是不用动的。避免了频繁的合版时,各模块版本频繁/繁琐的修改合并。

Jenkins

使用 Jenkins 的需要使用 repo 插件,也还算挺方便的,稍微由原来的 git 迁移到 repo 的配置就行。
配合 Jenkins 的自动化打包,加一些自动化的打包配置,如远程参数化构建、自定义的 Gradle 打包插件等,如果需要在 Jenkins 上打 Feature 包的,那么在 Manifest 项目里可以不需要再新建 Feature 分支了。所以综合来看,合版时的工作量减轻了不少~

End

现在加Android高级开发群;701740775,可免费领取一份最新Android高级架构技术体系大纲和进阶视频资料,以及这些年年积累整理的所有面试资源笔记。加群请备注csdn领取xx资料

相关文章
|
4月前
|
敏捷开发 测试技术 持续交付
阿里云云效产品使用合集之如何将个人账号下的Git仓库转移到企业账号下
云效作为一款全面覆盖研发全生命周期管理的云端效能平台,致力于帮助企业实现高效协同、敏捷研发和持续交付。本合集收集整理了用户在使用云效过程中遇到的常见问题,问题涉及项目创建与管理、需求规划与迭代、代码托管与版本控制、自动化测试、持续集成与发布等方面。
|
4月前
|
IDE 网络安全 开发工具
【Azure App Service】Local Git App Service的仓库代码遇见卡住不Clone代码的问题
【Azure App Service】Local Git App Service的仓库代码遇见卡住不Clone代码的问题
【Azure App Service】Local Git App Service的仓库代码遇见卡住不Clone代码的问题
|
1月前
|
Ubuntu Shell 开发工具
ubuntu/debian shell 脚本自动配置 gitea git 仓库
这是一个自动配置 Gitea Git 仓库的 Shell 脚本,支持 Ubuntu 20+ 和 Debian 12+ 系统。脚本会创建必要的目录、下载并安装 Gitea,创建 Gitea 用户和服务,确保 Gitea 在系统启动时自动运行。用户可以选择从官方或小绿叶技术博客下载安装包。
50 2
|
2月前
|
Shell 开发工具 git
git学习三:git使用:删除仓库,删除仓库内文件
通过GitHub的设置页面删除仓库,以及如何使用Git命令行删除仓库中的文件或文件夹。
179 1
git学习三:git使用:删除仓库,删除仓库内文件
|
2月前
|
开发工具 git 索引
git上面中新建gitignore文件,并且去除已经在仓库版本管理中的文件夹
git上面中新建gitignore文件,并且去除已经在仓库版本管理中的文件夹
93 4
|
2月前
|
存储 开发工具 git
Git 远程仓库地址管理:添加、修改和验证
Git 远程仓库地址管理:添加、修改和验证
113 4
|
2月前
|
编译器 开发工具 数据安全/隐私保护
Git——多人协作/版本控制,在一个gitee仓库下开发(Gitee版教程)手把手教学,包好用的!
本文提供了一个关于如何在Gitee上进行多人协作和版本控制的详细教程,包括新建和初始化仓库、克隆仓库、邀请好友共同管理仓库以及注意事项,旨在帮助用户顺利进行代码协作开发。
355 0
Git——多人协作/版本控制,在一个gitee仓库下开发(Gitee版教程)手把手教学,包好用的!
|
3月前
|
开发工具 git
IDEA更改远程git仓库地址
【9月更文挑战第27天】本文介绍了两种在IntelliJ IDEA中更改远程Git仓库地址的方法:一是通过图形界面,在VCS设置中直接修改;二是通过IDEA内置的命令行工具使用`git`命令进行更改。具体步骤包括从版本控制菜单进入项目设置、修改远程仓库URL,以及使用`git remote set-url`命令更新仓库地址,并验证修改结果。这些方法适用于项目迁移或更换仓库地址的情况。
712 6
|
3月前
|
Linux 开发工具 git
linux自建仓库git之钩子不生效
linux自建仓库git之钩子不生效
|
3月前
|
Shell 网络安全 开发工具
git与gitee结合使用,提交代码,文件到远程仓库
本文介绍了如何将Git与Gitee结合使用来提交代码文件到远程仓库。内容涵盖了Git的安装和环境变量配置、SSH公钥的生成和配置、在Gitee上创建仓库、设置Git的全局用户信息、初始化本地仓库、添加远程仓库地址、提交文件和推送到远程仓库的步骤。此外,还提供了如何克隆远程仓库到本地的命令。
git与gitee结合使用,提交代码,文件到远程仓库

相关实验场景

更多