App的Repo多仓库管理

背景

当项目做了组件化或模块化拆分后,为了方便管理,会分出很多的 git 仓库,这么多仓库的下载与上传的管理成本比较高,经常出现如下问题:

  1. 找不到对应aar的仓库地址
  2. 需要手动clone当前所有的git 仓库
  3. 历史版本的源码分支,有时需要通过aar的版本号反查才能知到

我们考虑了两种解决方案:Git submodulerepo。然而,git submodule的子模组需要固定在某个版本上,并且在多人修改子模块时,子模块的冲突不易解决。综合考虑之后,我们最终选择了 repo。

Repo 简介

Repo is a tool built on top of Git. Repo helps manage many Git repositories, does the uploads to revision control systems, and automates parts of the development workflow. Repo is not meant to replace Git, only to make it easier to work with Git. The repo command is an executable Python script that you can put anywhere in your path.

简单的理解:

  1. repo 建立在 git 之上的一个 python 脚本工具集
  2. 用于提升多创库管理效率

Repo 私域搭建

受网络影响,Repo 需要科学上网才能使用,为了减少使用的成本,有必要做私域镜像。

Repo的组成部分:

  1. Repo launcher (Repo 引导脚本)
  2. Repo 命令的主体部分

这样设计旨在使 Repo launcher只包含最基本的init、help两个命令,主体命令可实现自动更新,这将显著改善用户的使用体验。

私域镜像过程:

  1. 通过科学上网,从git-repo官网上,克隆最新代码到本地
    1
    2
    3
    4
    5
    6
    # git 设置代理
    git config --global http.proxy 'socks5://127.0.0.1:7890'
    git config --global https.proxy 'socks5://127.0.0.1:7890'

    # clone 仓库
    git clone https://gerrit.googlesource.com/git-repo
  2. 删除 .git 和 .github 文件夹(原因是私域限制了提交的邮箱后缀)
  3. 私域上创建git-repo项目,再提交到私域
  4. 修改 Repo 的部分代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    REPO_URL = os.environ.get('REPO_URL', None)
    if not REPO_URL:
    REPO_URL = 'https://gerrit.googlesource.com/git-repo'
    REPO_REV = os.environ.get('REPO_REV')
    if not REPO_REV:
    REPO_REV = 'stable'

    // 改为如下:
    REPO_URL = 'git@私域域名:git_mirror/git-repo.git'
    REPO_REV = 'master'

Repo 私域安装步骤

  1. 下载 Repo launcher(即repo文件):https://私域域名/git_mirror/git-repo/-/raw/master/repo?inline=false
  2. 修改 repo 的权限,配置环境变量
    1
    2
    3
    4
    chmod 777 xxx/repo

    # ~/.zshrc
    export PATH="xxx:$PATH"

Repo开发流

  1. 创建 manifest 仓库,并创建manifest清单文件
    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
    26
    27
    28
    29
    30
    31
    <?xml version="1.0"?>

    <manifest>
    <!-- git服务器配置 -->
    <remote
    name="private"
    fetch="ssh://git@私域域名/"/>

    <!-- 默认配置
    sync-j:指定并发下载数
    revision:分支名,指tag的方式“refs/tags/tag名称”
    remote:指定默认从哪个git服务下载
    -->
    <default
    revision="master"
    remote="private"
    sync-j="4"/>

    <!-- project配置
    clone-depth:用于加快clone速度
    name:groupname/projectname
    path: 本地目录路径
    groups:用于分类使用,可用于按group下载
    -->
    <project
    clone-depth="1"
    name="group/project1"
    path="project1"
    groups="main"/>

    </manifest>
  2. 初始化:repo init
    1
    2
    3
    4
    repo init -u git@私域域名:/manifest.git [-b 分支名] [-g group,group]

    -b 指定版本分支,可选,默认all
    -g 指定group名称,可选,默认是all
  3. 同步代码:repo sync
  4. 创建本地分支:repo start f-xxx --all
  5. IDE 开发及代码提交
  6. 同步代码:repo rebase
  7. 删除开发分支:repo abandon 分支名

使用场景

场景1:管理58App相关的所有Git仓库

58App相关的所有Git仓库,不仅仅代码仓库,还有很多的工具仓库,如doc文档、CodeTure、Python比对脚本等等

统一配置到manifest之后,可带来如下好处:

  1. 快速找到所有相关的仓库
  2. 实现全局搜索,按 Google 内部的调研,发现平均每位工程师每天会执行 12 个代码搜索请求
  3. 代码阅读笔记可实现快速共享

创建一个manifest仓库,依据58App的发版方式,创建对应的版本分支,每个分支下,配置相应的default.xml文件

场景2:管理各种厂商预装包的特殊要求

类似Flipper一样,不用去分散的写各种python脚本,解决工具查找的问题。

manifest的配置如上一样

场景3:管理各种有业务差异的马甲包,如早期的58同城与58本地

一体化项目之前,58本地fork了一些底层库,导致在下载相应源码库时,容易出现混淆。

感谢您的阅读,本文由 刘阳 版权所有。如若转载,请注明出处:刘阳(https://handsomeliuyang.github.io/2023/02/22/%E7%BB%8F%E9%AA%8C%E6%80%BB%E7%BB%93/App%E7%9A%84Repo%E5%A4%9A%E4%BB%93%E5%BA%93%E7%AE%A1%E7%90%86/
从开发者角度思考单元测试的价值
ASM 学习心得