天天看点

repo介绍

转自文章《Android内核开发:理解和掌握repo工具》和《Repo的理解和用法小结2》

1. repo是什么?

repo是一种代码版本管理工具,它是由一系列的Python脚本组成,封装了一系列的Git命令,用来统一管理多个Git仓库。

2. 为什么要用repo?

因为Android源码引用了很多开源项目,每一个子项目都是一个Git仓库,每个Git仓库都有很多分支版本,为了方便统一管理各个子项目的Git仓库,需要一个上层工具批量进行处理,因此repo诞生。

repo也会建立一个Git仓库,用来记录当前Android版本下各个子项目的Git仓库分别处于哪一个分支,这个仓库通常叫做:manifest仓库。

3. 怎么安装repo?

官方的repo脚本下载方法:

curl http://commondatastorage.googleapis.com/git-repo-downloads/repo >  ./repo      

由于官网被墙,目前可以使用的repo脚本下载方法如下(两者选一):

$ git clone git://git.omapzoom.org/git-repo.git
$ git clone git://aosp.tuna.tsinghua.edu.cn/android/git-repo.git/  
      

$ cp git-repo/repo  ./repo

或者修改手头已有的被墙的repo文件:

REPO_URL = ‘git://git.omapzoom.org/git-repo.git‘
REPO_URL = ‘git://aosp.tuna.tsinghua.edu.cn/android/git-repo‘ 
      

REPO_REV = ‘stable‘

当然,你也可以去我的GitHub下载这个repo文件,地址:

https://github.com/Jhuster/AOSP/blob/master/repo

4. 怎么下载源码?

上面说过,Android源码分支其实由一个叫manifest仓库来管理起来的,因此,下载源码首先要clone这个manifest仓库。这个仓库里面有一个XML文件,其实就是一个文件清单,列出了本代码仓库依赖哪些代码,该去哪下载,分支是什么。

一般用repo init命令来clone这个manifest仓库,例如,如果要下载Android源码,则方法如下:

$ repo init -u https://android.googlesource.com/platform/manifest      

当然,上面的官网被墙了,因此,推荐如下镜像(两者选一):

$ repo init -u git://git.omapzoom.org/platform/manifest.git
$ repo init -u git://aosp.tuna.tsinghua.edu.cn/android/platform/manifest      

初始化完毕后,你会在本地的.repo文件夹中看到manifest仓库的内容,这个文件夹中最重要的文件是manifest.xml(有的仓库用的是default.xml,然后指向具体的xml),它就是上面说到的文件清单。

如果要选择特定版本的Android源码,或者在已下载的源码基础上切换到其他版本,则可以使用-b选项:

$ repo init -u git://git.omapzoom.org/platform/manifest.git -b android-5.0.2_r1 
$ repo init -u git://aosp.tuna.tsinghua.edu.cn/android/platform/manifest -b android-5.0.2_r1      

然后使用 repo sync 命令进行同步即可下载好全部的Android源码了。

5. manifest.xml文件清单的组成

上面提到了repo init需要初始化一个manifest仓库,仓库中含有一个很重要的manifest.xml文件清单,其实这个manifest.xml并不复杂的,它就是用XML文件的格式记录了本项目依赖的各个Git仓库的名称、地址,以及分支等信息。常用的元素如下所示:

(1) manifest 最顶层的XML元素

(2) remote  设置远程git服务器的属性,如名称、根URL地址等

(3) project 需要clone的Git仓库,path表示本机路径,name表示远程版本库的相对路径

(4) copyfile 执行拷贝操作,把URL/$src地址的文件拷贝到./$dest

其实,如果不使用repo工具,也是可以对照manifest.xml文件清单直接使用“git clone”的方式一个project一个project的下载的,然后对每个project进行git checkout特定的分支。

7. 常用repo命令

这一块网上文章很多,我就不详细讲解了,只列出常用命令。

(1) repo init   // 初始化repo仓库

(2) repo sync   // 下载源码

(3) repo start  // 创建分支

(4) repo checkout //切换分支

(5) repo branches //查看分支

(6) repo status   //查看文件状态

下面对其中的命令进行详细介绍:

      • repo init
      • repo sync
      • repo start
      • repo checkout
      • repo branches
      • repo diff
      • repo stage
      • repo prune
      • repo abandon
      • repo status
      • repo remote
      • repo push
      • repo forall
        • 1 添加环境变量
        • 2 合并多个分支
        • 3 打标签
        • 4 设置远程仓库
        • 5 创建特性分支
      • repo grep
      • repo manifest
      • repo version
      • repo upload
      • repo download
      • repo selfupdate
      • repo help

1. repo init

repo init -u manifest_git_path -m manifest_file_name -b branch_name --repo-url=repo_url --no-repo-verify           
  • 1

  在当前目录下安装 Repo。这会产生一个 .repo/ 目录,目录包括装 Repo 源代码和标准 Android 清单文件的 Git 仓库。.repo/ 目录还包括 manifest.xml,是一个在 .repo/manifests/ 目录选择清单的符号链接。

  选项:

-u: 指定Manifest库的Git访问路径。 

-m: 指定要使用的Manifest文件。 

-b: 指定要使用Manifest仓库中的某个特定分支。 

–repo-url: 指定要检查repo是否有更新的远端repoGit库的访问路径。 

–no-repo-verify: 指定不检查repo库是否需要更新。

2. repo sync

repo sync [project_name]           
  • 1

  用于参照清单文件克隆并同步版本库。可以使用repo sync project_name的形式只克隆某个项目。。

  实现参照清单.repo/manifests.xml克隆并同步版本库,如果版本库不存在,则相当于执行

git clone           
  • 1

  如果版本库已经存在,则相当于执行

  1. #对每个remote源进行fetch操作
  2. git remote update
  3. #针对当前分支的跟踪分支进行rebase操作
  4. git rebase/origin/branch
  • 1
  • 2
  • 3
  • 4

  选项:

-d:切换指定项目回到清单修正。如果该项目目前是一个主题分支那就有帮助,但清单修正是暂时需要。 

-s:同步到一个已知的构建 manifest-server 在当前清单指定的元素。 

-f:继续同步其他项目,即使有项目同步失败。

3. repo start

repo start <newbranchname> [--all|<project>...]           
  • 1

  创建并切换分支。刚克隆下来的代码是没有分支的,repo start实际是对git checkout -b命令的封装。 

  为指定的项目或所有的项目(若使用-all),以清单文件中为设定的分支,创建特定的分支。 

  这条指令与git checkout -b 还是有很大区别的。 

  · git checkout -b 是在当前所在的分支的基础上创建特性分支。 

  · 而repo start 是在清单文件设定的分支的基础上创建特性分支。

repo start stable --all           
  • 1

  假设清单文件中设定的分支是gingerbread-exdroid-stable,那么执行以上指令就是对所有项目,在gingerbread-exdroid-stable的基础上创建特性分支stable。

repo start stable platform/build platform/bionic           
  • 1

  假设清单文件中设定的分支是gingerbread-exdroid-stable,那么执行以上指令就是对platform/build、platform/bionic项目,在gingerbread-exdroid-stable的基础上创建特性分支stable。

4. repo checkout

  1. <branchname> [ <rpoject> ...]{{{
  2. repo checkout <branchname> [ <project> ...]
  3. }}}
  • 1
  • 2
  • 3

  切换分支。 实际上是对git checkout命令的封装,但不能带-b参数,所以不能用此命令来创建特性分支。

  示例:

  1. repo checkout liuq -dev
  2. repo checkout liuq -dev skipper/build platform/bionic
  • 1
  • 2

5. repo branches

repo branches [<project>...]           
  • 1

  查看分支。 

  示例:

  1. repo branches
  2. repo branches skipper/build skipper/release
  3. #查看可切换的分支
  4. cd .repo/manifests
  5. git branch -a | cut -d / -f
  • 1
  • 2
  • 3
  • 4
  • 5

6. repo diff

repo diff [<project>...]           
  • 1

  查看工作区文件差异。实际是对git diff命令的封装,用于分别显示各个项目工作区下的文件差异。在 commit 和工作目录之间使用 git diff 显示明显差异的更改。 

  示例:

  1. #查看所有项目
  2. repo diff
  3. #只查看其中的两个项目
  4. repo diff skipper/build skipper/release
  • 1
  • 2
  • 3
  • 4

7. repo stage

repo stage -i [<project>...]           
  • 1

  把文件添加到index表中。实际上是对git add –interactive命令的封装,用于挑选各个项目中的改动以加入暂存区。 

  -i表示git add –interactive命令中的–interactive,给出一个界面供用户选择。

8. repo prune

repo prune [<project>...]           
  • 1

  删除已经合并分支。实际上是对git branch -d 命令的封装,该命令用于扫描项目的各个分支,并删除已经合并的分支。

9. repo abandon

repo abandon <branchname> [<rpoject>...]           
  • 1

  删除指定分支。实际是对git brance -D命令的封装。

10. repo status

repo status [<project>...]           
  • 1

  查看文件状态。 

  示例:

  1. #输出skipper/build项目分支的修改状态
  2. repo status skipper/build
  • 1
  • 2

每个小节的首行显示项目名称,以及所在的分支的名称。 

每个字母表示暂存区的文件修改状态。

字母 含义 描述
- 无变化 没有修改,在 HEAD 和在索引中是一样的
A 添加 不在HEAD中,在暂存区中
M 修改 在HEAD中, 在暂存区中,内容不同
D 删除 在HEAD中,不在暂存区
R 重命名 不在HEAD中,在暂存区中
C 拷贝 不在HEAD中,在暂存区,从其他文件拷贝
T 文件状态改变 在HEAD中,在暂存区,内容相同
U 未合并 需要冲突解决
第二个字符表示工作区文件的更改状态。
字母 含义 描述
- 新/未知 不在暂存区,在工作区
m 修改 在暂存区,在工作区,被修改
d 删除 在暂存区,不在工作区
两个表示状态的字母后面,显示文件名信息。如果有文件重名还会显示改变前后的文件名及文件的相似度。

11. repo remote

  1. repo remote add <remotename> <url> [ <project> ...]
  2. repo remote rm <remotename> [ <project> ...]
  • 1
  • 2

  设置远程仓库。 

  示例:

repo remote add org ssh://10.11.10.11/git_repo           
  • 1

  这个指令根据xml文件添加的远程分支,方便于向服务器提交代码,执行之后的build目录下看到新的远程分支org。

  1. #删除远程仓库
  2. repo remote rm org
  • 1
  • 2

12. repo push

repo push <remotename> [--all|<project>...]           
  • 1

  向服务器提交代码。repo会自己查询需要向服务器提交的项目并提示用户。 

  示例:

repo push org           
  • 1

13. repo forall

repo forall [<project>...] -c <command>           
  • 1

  迭代器,可以在所有指定的项目中执行同一个shell指令。 

  选项:

-c 后面所带的参数是shell指令,即执行命令和参数。命令是通过 /bin/sh 评估的并且后面的任何参数就如 shell 位置的参数通过。 

-p 在shell指令输出之前列出项目名称,即在指定命令的输出前显示项目标题。这是通过绑定管道到命令的stdin,stdout,和 sterr 流,并且用管道输送所有输出量到一个连续的流,显示在一个单一的页面调度会话中。 

-v 列出执行shell指令输出的错误信息,即显示命令写到 sterr 的信息。

  附加环境变量:

REPO_PROJECT 指定项目的名称 

REPO_PATH 指定项目在工作区的相对路径 

REPO_REMOTE 指定项目远程仓库的名称 

REPO_LREV 指定项目最后一次提交服务器仓库对应的哈希值 

REPO_RREV 指定项目在克隆时的指定分支,manifest里的revision属性

  如果-c后面所带的shell指令中有上述环境变量,则需要用单引号把shell指令括起来。

13.1. 添加环境变量

  1. repo forall -c 'echo $REPO_PROJECT'
  2. repo forall -c 'echo $REPO_PATH'
  • 1
  • 2

13.2. 合并多个分支

repo forall -p -c git merge topic           
  • 1

  把所有项目都切换到master分支,执行上述指令将topic分支合并到master分支。

13.3. 打标签

repo forall -c git tag crane-stable-.6           
  • 1

  在所有项目下打标签。

13.4. 设置远程仓库

repo forall -c 'git remote add korg ssh://[email protected]/$REPO_PROJECT.git'           
  • 1

  引用环境变量REPO_PROJECT添加远程仓库。

  1. #删除远程仓库。
  2. repo forall -c git remote rm korg
  • 1
  • 2

13.5. 创建特性分支

  1. repo forall -c git branch crane -dev
  2. repo forall -c git checkout -b crane -dev
  • 1
  • 2

14. repo grep

repo grep {pattern | -e pattern} [<project>...]           
  • 1

  打印出符合某个模式的行。相当于对 git grep 的封装,用于在项目文件中进行内容查找。 

  示例:

  1. #要找一行, 里面有#define, 并且有'MAX_PATH' 或者 'PATH_MAX':
  2. repo grep -e '#define' --and -\( -e MAX_PATH -e PATH_MAX \)
  3. #查找一行, 里面有 'NODE'或'Unexpected', 并且在一个文件中这两个都有的.
  4. repo grep --all-match -e NODE -e Unexpected
  • 1
  • 2
  • 3
  • 4

15. repo manifest

repo manifest [-o {-|NAME.xml} [-r]]           
  • 1

  manifest检验工具,用于显示manifest文件内容。 

  选项:

-h, –help 显示这个帮助信息后退出 

-r, –revision-as-HEAD 把某版次存为当前的HEAD 

-o -|NAME.xml, –output-file=-|NAME.xml 把manifest存为NAME.xml

16. repo version

repo version           
  • 1

  显示repo的版本号。 

  选项:

-h, –help 显示这个帮助信息后退出.

17. repo upload

repo upload [--re --cc] {[<project>]...|--replace <project>}           
  • 1

  repo upload 相当于git push,但是又有很大的不同。它不是将版本库改动推送到代码审核服务器(Gerrit软件架设)的特殊引用上,使用SSH协议。代码审核服务器会对推送的提交进行特殊处理,将新的提交显示为一个待审核的修改集,并进入代码审核流程,只有当审核通过后,才会合并到官方正式的版本库中。 

  选项:

-h, –help 显示帮助信息 

-t 发送本地分支名称到Gerrit代码审核服务器 

–replace 发送此分支的更新补丁集 

–re=REVIEWERS 要求指定的人员进行审核 

–cc=CC 同时发送通知到如下邮件地址

18. repo download

repo download {project change[/patchset]}...           
  • 1

  repo download命令主要用于代码审核者下载和评估贡献者提交的修订。 

  贡献者的修订在Git版本库中refs/changes//引用方式命名(缺省的patchset为1),和其他Git引用一样,用git fetch获取,该引用所指向的最新的提交就是贡献者待审核的修订。 

  使用repo download命令实际上就是用git fetch获取到对应项目的refs/changes//patchset>引用,并自动切换到对应的引用上。

19. repo selfupdate

repo selfupdate           
  • 1

  用于 repo 自身的更新。如果有新版本的repo存在, 这个命令会升级repo到最新版本。通常这个动作在repo sync时会自动去做, 所以不需要最终用户手动去执行。 

  选项:

-h, –help 显示这个帮助信息后退出. 

–no-repo-verify 不要验证repo源码.

20. repo help

repo help [--all|command]           
  • 1

  显示命令的详细帮助。 

  选项:

-h, –help 显示这个帮助信息后退出 

-a, –all 显示完整的命令列表