Repo介绍

随之移动终端设备的普及,各企业越来越重视Android市场,而研究Android系统的底层驱动开发,首先需要做的便是建立一套Android版本库管理机制。Android使用Git进行代码管理,而Repo命令行工具对Git命令进行了封装,可以管理多个git项目,从而更好地对代码进行集中式管理。
Repo是Google用Python脚本写的调用Git的脚本(可以在Google Group 上找到相关文档资料),用于下载、管理Android项目的软件仓库。Repo主要包含Repo配置信息以及Repo锁管理的Git项目集合。

Repo用法

安装Repo

注:下载Repo只针对第一次使用。
首先,确认主目录下存在 bin/ 目录并已包含在路径中:

  1. mkdir ~/bin
  2. PATH=~/bin:$PATH

下载Repo工具并设置可执行的权限:

  1. curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
  2. chmod a+x ~/bin/repo

注:在Repo设置成功后,会出现下列提示,说明可以进行初始化了。

error: repo is not installed. Use “repo init” to install it here.

Repo初始化 (init)

首先创建目录用于存放工程文件:

  1. mkdir WORKSPACE
  2. cd WORKSPACE

之后,使用命令进行初始化:

  1. repo init -u URL [OPTIONS]

具体操作有:
-u:指定一个URL,其连接到一个manifest仓库。
-m:在manifest仓库中选择一个 NAME.xml 文件。
-b:选择一个manifest仓库中一个特殊的分支。
注:
· 如果不提供 -b REVISION 或者 –manifest-branch=REVISION参数,则检出 manifest Git 库的 master 分支。
· 如果不提供 -m NAME.xml 或者 –manifest-name=NAME.xml 参数,则使用缺省值 default.xml。
在初始化完成后,输入ls命令:

  1. ls repo

可以看到相关文件:manifests/ manifests.git/ manifest.xml repo/
() .repo:Repo目录,可用于提取相应项目工作目录到外面的repo工作目录。
(
) .repo/manifests.git:Repo配置信息的Git库,不同版本包含不同配置信息。
() .repo/manifests:Repo配置信息的工作目录(将配置信息的工作目录和相应的实际Git目录分离管理,并且配置信息中的.git目录实际只是指向实际Git库的软连接),其中可能包含一个或多个xml文件描述的配置。每个xml文件是独立的一套配置,配置内容包括当前Repo工作目录包含哪些Git项目、所有Git项目所处的默认公共分支、以及远端地址等。
(
) .repo/manifest.xml:Repo工作目录中的内容同一时刻只能采用manifests中的一个xml文件做为其配置,该文件就是其软连接,通过init的-m选项指定采用哪个文件;另外,同一xml文件也可能处于manifests库的不同版本或者不同分支,通过init的-b选项指定使用manifests中的哪个分支,每次init命令都会从服务器更新最新的配置。
(*) .repo/repo:Repo脚本集的Git库,这里包含Repo命令所需的所有子命令脚本实现,由Python完成,这个目录本身又由Git来管理。

Repo同步 (sync)

下载当前repo配置的所有项目,并生成对应的repo工作目录:

  1. repo sync

如果想生成特定项目的代码,则使用下列语句:

  1. repo sync [<project>...]

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

  1. git clone

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

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

已有工程同步代码常用:

  1. $ repo sync -d -c --no-tags

同步涉及到的参数有:

-j:开启多线程同步操作,会加快sync命令的执行速度。默认情况下,使用4个线程并发进行sync。
-c, –current-branch:只同步指定的远程分支。默认情况下,sync会同步所有的远程分支,当远程分支比较多的时候,下载的代码量就大。使用该参数,可以缩减下载时间,节省本地磁盘空间。
-d, –detach:脱离当前的本地分支,切换到manifest.xml中设定的分支。在实际操作中这个参数很有用,当我们第一次sync完代码后,往往会切换到dev分支进行开发。如果不带该参数使用sync, 则会触发本地的dev分支与manifest设定的远程分支进行合并,这会很可能会导致sync失败。
-f, –force-broken:当有git库sync失败了,不中断整个同步操作,继续同步其他的git库。
–no-clone-bundle:在向服务器发起请求时,为了做到尽快的响应速度,会用到内容分发网络(CDN, Content Delivery Network)。同步操作也会通过CDN与就近的服务器建立连接, 使用HTTP/HTTPS的$URL/clone.bundle来初始化本地的git库,clone.bundle实际上是远程git库的镜像,通过HTTP直接下载,这会更好的利用网络带宽,加快下载速度。
同步完成后,.repo下多了projects目录,,原工作目录下也多了目录:
() .repo/projects:Repo所管理的所有Git项目集,包含Repo当前配置所指定的所有Git项目对应的Git目录。
(
) .repo/../ :Repo的工作区。在Repo目录(即.repo)之外,根据Repo配置(即.repo/manifest.xml文件),从.repo/projects下提取出指定分支的各个Git项目(即.repo/projects中Git项目的子集)的工作目录,形成Repo工作目录,可供开发使用。

常用命令

减小下载量

  1. repo init --depth=1 -u URL
  2. repo sync -f -c --no-clone-bundle --no-tags -j$(nproc --all)

repo update[ project-list ]
上传修改的代码 ,如果你本地的代码有所修改,那么在运行 repo sync 的时候,会提示你上传修改的代码,所有修改的代码分支会上传到 Gerrit (基于web 的代码review 系统), Gerrit 受到上传的代码,会转换为一个个变更,从而可以让人们来review 修改的代码。
repo diff [ project-list ]
显示提交的代码和当前工作目录代码之间的差异。
repo download target revision
下载特定的修改版本到本地, 例如: repo download pltform/frameworks/base 1241 下载修改版本为 1241 的代码
repo start newbranchname .
创建新的branch分支。 “.” 代表当前工作的branch 分支。
repo prune [project list]
删除已经merge 的 project
repo forall -c
这个命令会遍历所有的git仓库,并在每个仓库执行-c所指定的命令(这个被执行的命令就不限于仅仅是git命令了,而是任何被系统支持的命令,比如:ls 、 pwd 、cp 等等的 )
当我想通过这个命令遍历所有的仓库并在每个仓库执行”git checkout . “用以将每个仓库的改动都清除的时候,我这么输入命令:
repo执行的时候加上-p参数就可以在遍历到每个仓库的时候先打印出当前的pwd,然后再继续执行-c所指定的命令。举例如下:
repo forall -p -c git branch
该命令会遍历所有仓库并打印每个仓库的分支情况,由于有了-p参数,这样便会打印出每个仓库的路径!
repo status
显示 project 中每个仓库的状态,并打印仓库名称
repo forall -c git reset --hard HEAD
repo撤销本地修改
repo --trace sync
打印更多信息便于分析问题
清理本地tag
repo forall -c "git tag -l | xargs git tag -d"
repo forall -c git reflog expire --expire=now --all
repo forall -c git gc --prune=now

repo sync同步时出错

自动重复

用repo sync 在抓去 android source code 的时候,会经常出现一些错误导致 repo sync 中断,每次都要手动开始。 可以用如下的命令,来自动重复

  1. $?=1;
  2. while [ $? -ne 0 ] ;
  3. do repo sync -j8 ;
  4. done

error: .repo/manifests/: contains uncommitted changes

  1. cd .repo/manifests
  2. git stash
  3. git clean -f -d
  4. repo sync -c -j4 --no-clone-bundle

或者

  1. git config core.filemode false

或者

  1. cd ./repo/manifests
  2. git reset --hard
  3. repo sync

fatal: not a git repository

repo stores projects in

  1. .repo/projects

but these are only soft links to actual git data, which is stored in

  1. .repo/project-objects

follow the links in ‘projects’ and remove both the repositories and run sync again. It worked for me.
Sample for platform/frameworks/support:

  1. rm -fr .repo/projects/frameworks/support.git/ .repo/project-objects/platform/frameworks/support.git/

Sync only this project:

  1. repo sync -j4 platform/frameworks/support

error: Exited sync due to fetch errors

  1. repo sync -f -j8