repo简介
Repo 是我们以 Git 为基础构建的代码库管理工具,可以组织多个仓库的上传和下载。它是由一系列的Python脚本组成,封装了一系列的Git命令,用来统一管理多个Git仓库
一个大型的项目可能由很多小的仓库组合而成的,为了方便统一管理各个子项目的Git仓库,需要一个上层工具批量进行处理,因此repo诞生。
repo也会建立一个Git仓库,用来记录当前版本下各个子项目的Git仓库分别处于哪一个分支,这个仓库通常叫做:manifest仓库。
安装repo引导器
在安装 Repo 时,必须先要确保已经安装了 Git 工具,以及 Python2.7 + 的环境,下面是在linux下安装的流程:
Downloading and installing Git and Python
sudo apt-get install git-core
sudo apt-get install python
Download and install Repo
$ mkdir ~/bin
$ PATH=~/bin:$PATH
$ curl https://raw.githubusercontent.com/esrlabs/git-repo/stable/repo > ~/bin/repo
$ chmod a+x ~/bin/repo
使用流程
- 查看repo引导器文件的内容
REPO_URL = 'https://github.com/esrlabs/git-repo’
REPO_REV = ‘stable’
分别是repo.git仓库的url和检出的branch,即下载repo工具的git仓库
- repo init,这一步可以省略,第三步操作会自动执行这个
repo init会从1中指定的REPO_URL中拉出repo工具(在当前目录会生成.repo/repo)
此时我们只是有了repo工具,但是要想管理多个git,还需要一个清单,来说明要管理那些git,从哪里拉去等等. 这个任务要依赖manifest.git了,正如之前提到的,在repo init的时候,要通过-u url来指定manifest.git的位置.
- repo init -u https://gitee.com/angerial/repo-test.git
注意:这里url指向的git仓库需要有default.xml,即我们需要提前创建一个仓库。
#就会初始化repo成功.
#但是我们要管理自己的仓库(其实就是一个仓库存放default.xml)
#这个仓库的内容最简单时是一个default.xml.
#default.xml内容如下:<?xml version="1.0" encoding="UTF-8" ?>
<manifest><remote fetch="https://gitee.com/openharmony/" name="origin" review="https://openharmony.gitee.com/openharmony/"/><default remote="origin" revision="master" sync-j="4" /><project name="graphic_utils" path="foundation/graphic/utils" />
</manifest>#可以看到,根元素manifest,里边定义了remote,default,project.
#remote可以多个,每个定义了一个远程拉取仓库, fetch是仓库的url, 可以使用”..”表示使用repo init -u url里的url
#default则设置每个项目的默认仓库和默认分支
#project定义了一个项目,它指明一个远程仓库,和clone到本地来后的目录名称. name为项目的远程仓库名,以上代码拉取的项目是git://localhost/helo
- 参考repo组成,修改相关文件,即拉取哪些仓库
- 拉代码到本地
repo sync -c
repo组成
Repo 主要包括两部分:Repo 引导器(Google 称之为 Repo launcher)和 Repo 命令的主体部分。那么 Repo 仓库究竟有些什么东西呢,在我们初始化 Repo 仓库之后,会出现一个. repo 的文件夹,里面有如下内容:
root@l-virtual-machine:~/test/repo/.repo# tree -L 1
├── manifests
├── manifests.git
├── manifest.xml -> manifests/default.xml
└── repo
3 directories, 1 file
当执行 repo init 命令来初始化仓库的时候首先执行的就是 Repo 的引导脚本,该脚本会到我们指定的地方去下载 Manifest 仓库,以及 Repo 命令主体部分。下载好之后就放在当前目录下面的**.repo**目录下,其中:
文件夹 | 用途 |
---|---|
manifests | 清单文件的仓库 |
manifests.git | 清单文件的 Git 裸仓库,不带工作区 |
manifest.xml | 这是一个链接文件,指向你的用于初始化工作区的清单文件,即manifests/default.xml |
project.list | 一个文本文件,里面包含所有项目名字的列表 |
projects | 该文件夹下包含所有 git project 的裸仓库,文件夹的层次结构跟工作区的布局一样 |
repo | 这是 repo 命令的主体,其中也包含最新的 repo 命令,推荐使用这里面的 repo 命令 |
<?xml version="1.0" encoding="UTF-8" ?><manifest>
<remote fetch="https://gitee.com/openharmony/" name=“origin” review="https://openharmony.gitee.com/openharmony/"/>
<default remote=“origin” revision=“master” sync-j=“4” />
<project name=“graphic_utils” path=“foundation/graphic/utils” />
</manifest>
manifest 元素
xml 文件的根元素
remote 元素
可以存在一个或者多个 remote 元素,remote 元素指定了使用 repo upload 命令的时候,会将改变提交到哪个服务器。
name: 远程git服务器的名字,直接用于git fetch, git remote 等操作
alias: 远程git服务器的别名,如果指定了,则会覆盖name的设定。在一个manifest(可以理解为default.xml)中, name不能重名,但alias可以重名。
fetch: 所有projects的git URL 前缀
review: 指定Gerrit的服务器名,用于repo upload操作。如果没有指定,则repo upload没有效果。
default 元素
default 元素中指定的属性都是一些缺省的属性。即如果 project 元素中不存在该属性,则使用在 default 元素中指定的属性。
revision:Git 分支的名字。如果 project 元素没有指定 revision 属性,那么就使用 default 元素的该属性。revision 属性的值可以是一个 git branch,git tag,也可以是一个 commit id。
sync-j:sync 的时候,并行工作的任务数。
sync-c:如果设置为 true,则在同步代码的时候,将只会同步 project 元素中 revision 属性中指定的分支。如果 project 元素没有指定 revision 属性,则使用 default 元素的 revision 属性。
sync_s: 如果设置为true,则会同步git的子项目
remote: 之前定义的某一个remote元素中name属性值,用于指定使用哪一个远程git服务器。
project 元素
xml 文件中可以指定一个或者多个 project 元素。 每一个 project 元素都描述了一个需要 pull 到本地的 git 仓库。
project 元素中有很多可以使用的属性,在此只介绍几个我们经常使用的属性。
name: 唯一的名字标识project,同时也用于生成git仓库的URL。格式如下:
remotefetch/{remote_fetch}/remotefetch/{project_name}.git
path:可选的路径,该 指定git clone出来的代码存放在本地的子目录。如果没有指定,则以name作为子目录名。
remote: 指定之前在某个remote元素中的name。
revision:指定需要获取的git提交点,可以是master, refs/heads/master, tag或者SHA-1值。如果不设置的话,默认下载当前project,当前分支上的最新代码。
sync_c: 如果设置为true,则只同步指定的分支(revision 属性指定),而不是所有的ref内容。
sync_s: 如果设置为true,则会同步git的子项目。
groups: 列出project所属的组,以空格或者逗号分隔多个组名。
upstream: 在哪个git分支可以找到一个SHA1。用于同步revision锁定的manifest(-c 模式)。该模式可以避免同步整个ref空间。
annotation: 可以有多个annotation,格式为name-value pair。在repo forall 命令中这些值会导入到环境变量中。
remove-project: 从内部的manifest表中删除指定的project。经常用于本地的manifest文件,用户可以替换一个project的定义
Include元素
通过name属性可以引入另外一个manifest文件(路径相对与manifest repository’s root)。
常用命令
repo init
repo init -u manifest_git_path -m manifest_file_name -b branch_name --repo-url=repo_url --no-repo-verify
在当前目录下安装 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库是否需要更新。
repo sync
repo sync [project_name]
用于参照清单文件克隆并同步版本库。可以使用repo sync project_name的形式只克隆某个项目。
实现参照清单.repo/manifests.xml克隆并同步版本库,如果版本库不存在,则相当于执行
git clone
如果版本库已经存在,则相当于执行
#对每个remote源进行fetch操作
git remote update#针对当前分支的跟踪分支进行rebase操作
git rebase/origin/branch
选项:
-d:切换指定项目回到清单修正。如果该项目目前是一个主题分支那就有帮助,但清单修正是暂时需要。
-s:同步到一个已知的构建 manifest-server 在当前清单指定的元素。
-f:继续同步其他项目,即使有项目同步失败。
repo start
repo start <newbranchname> [--all|<project>...]
创建并切换分支。刚克隆下来的代码是没有分支的,repo start实际是对git checkout -b命令的封装。
为指定的项目或所有的项目(若使用-all),以清单文件中为设定的分支,创建特定的分支。
这条指令与git checkout -b 还是有很大区别的。
· git checkout -b 是在当前所在的分支的基础上创建特性分支。
· 而repo start 是在清单文件设定的分支的基础上创建特性分支。
repo start stable --all
假设清单文件中设定的分支是gingerbread-exdroid-stable,那么执行以上指令就是对所有项目,在gingerbread-exdroid-stable的基础上创建特性分支stable。
repo start stable platform/build platform/bionic
假设清单文件中设定的分支是gingerbread-exdroid-stable,那么执行以上指令就是对platform/build、platform/bionic项目,在gingerbread-exdroid-stable的基础上创建特性分支stable。
repo checkout
<branchname> [<rpoject>...]{{{repo checkout <branchname> [<project>...]}}}
切换分支。 实际上是对git checkout命令的封装,但不能带-b参数,所以不能用此命令来创建特性分支。
示例:
repo checkout liuq-dev
repo checkout liuq-dev skipper/build platform/bionic
repo branches
repo branches [<project>...]
查看分支。
示例:
repo branches
repo branches skipper/build skipper/release#查看可切换的分支
cd .repo/manifests
git branch -a | cut -d / -f 3
repo diff
repo diff [<project>...]
查看工作区文件差异。实际是对git diff命令的封装,用于分别显示各个项目工作区下的文件差异。在 commit 和工作目录之间使用 git diff 显示明显差异的更改。
示例:
#查看所有项目
repo diff#只查看其中的两个项目
repo diff skipper/build skipper/release
repo stage
repo stage -i [<project>...]
把文件添加到index表中。实际上是对git add –interactive命令的封装,用于挑选各个项目中的改动以加入暂存区。
-i表示git add –interactive命令中的–interactive,给出一个界面供用户选择。
repo prune
repo prune [<project>...]
删除已经合并分支。实际上是对git branch -d 命令的封装,该命令用于扫描项目的各个分支,并删除已经合并的分支。
repo abandon
repo abandon <branchname> [<rpoject>...]
删除指定分支。实际是对git brance -D命令的封装。
repo status
repo status [<project>...]
查看文件状态。
示例:
#输出skipper/build项目分支的修改状态repo status skipper/build
每个小节的首行显示项目名称,以及所在的分支的名称。
每个字母表示暂存区的文件修改状态。
字母 | 含义 | 描述 |
---|---|---|
- | 无变化 | 没有修改,在 HEAD 和在索引中是一样的 |
A | 添加 | 不在HEAD中,在暂存区中 |
M | 修改 | 在HEAD中, 在暂存区中,内容不同 |
D | 删除 | 在HEAD中,不在暂存区 |
R | 重命名 | 不在HEAD中,在暂存区中 |
C | 拷贝 | 不在HEAD中,在暂存区,从其他文件拷贝 |
T | 文件状态改变 | 在HEAD中,在暂存区,内容相同 |
U | 未合并 | 需要冲突解决 |
第二个字符表示工作区文件的更改状态。
字母 | 含义 | 描述 |
---|---|---|
- | 新/未知 | 不在暂存区,在工作区 |
m | 修改 | 在暂存区,在工作区,被修改 |
d | 删除 | 在暂存区,不在工作区 |
两个表示状态的字母后面,显示文件名信息。如果有文件重名还会显示改变前后的文件名及文件的相似度。
repo remote
repo remote add <remotename> <url> [<project>...]
repo remote rm <remotename> [<project>...]
设置远程仓库。
示例:
repo remote add org ssh://10.11.10.11/git_repo
这个指令根据xml文件添加的远程分支,方便于向服务器提交代码,执行之后的build目录下看到新的远程分支org。
#删除远程仓库
repo remote rm org
repo push
repo push <remotename> [--all|<project>...]
向服务器提交代码。repo会自己查询需要向服务器提交的项目并提示用户。
示例:
repo push org
repo forall
repo forall [<project>...] -c <command>
迭代器,可以在所有指定的项目中执行同一个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指令括起来。
添加环境变量
repo forall -c 'echo $REPO_PROJECT'
repo forall -c 'echo $REPO_PATH'
合并多个分支
repo forall -p -c git merge topic
把所有项目都切换到master分支,执行上述指令将topic分支合并到master分支。
打标签
repo forall -c git tag crane-stable-1.6
在所有项目下打标签。
设置远程仓库
repo forall -c 'git remote add korg ssh://xiong@172.16.31/$REPO_PROJECT.git'
引用环境变量REPO_PROJECT添加远程仓库。
#删除远程仓库。
repo forall -c git remote rm korg
创建特性分支
repo forall -c git branch crane-dev
repo forall -c git checkout -b crane-dev
repo grep
repo grep {pattern | -e pattern} [<project>...]
打印出符合某个模式的行。相当于对 git grep 的封装,用于在项目文件中进行内容查找。
示例:
#要找一行, 里面有#define, 并且有'MAX_PATH' 或者 'PATH_MAX':
repo grep -e '#define' --and -\( -e MAX_PATH -e PATH_MAX \)#查找一行, 里面有 'NODE'或'Unexpected', 并且在一个文件中这两个都有的.
repo grep --all-match -e NODE -e Unexpected
repo manifest
repo manifest [-o {-|NAME.xml} [-r]]
manifest检验工具,用于显示manifest文件内容。
选项:
-h, –help 显示这个帮助信息后退出
-r, –revision-as-HEAD 把某版次存为当前的HEAD
-o -|NAME.xml, –output-file=-|NAME.xml 把manifest存为NAME.xml
repo version
repo version
显示repo的版本号。
选项:
-h, –help 显示这个帮助信息后退出.
repo upload
repo upload [--re --cc] {[<project>]...|--replace <project>}
repo upload 相当于git push,但是又有很大的不同。它不是将版本库改动推送到代码审核服务器(Gerrit软件架设)的特殊引用上,使用SSH协议。代码审核服务器会对推送的提交进行特殊处理,将新的提交显示为一个待审核的修改集,并进入代码审核流程,只有当审核通过后,才会合并到官方正式的版本库中。
选项:
-h, –help 显示帮助信息
-t 发送本地分支名称到Gerrit代码审核服务器
–replace 发送此分支的更新补丁集
–re=REVIEWERS 要求指定的人员进行审核
–cc=CC 同时发送通知到如下邮件地址
repo download
repo download {project change[/patchset]}
repo download命令主要用于代码审核者下载和评估贡献者提交的修订。
贡献者的修订在Git版本库中refs/changes//引用方式命名(缺省的patchset为1),和其他Git引用一样,用git fetch获取,该引用所指向的最新的提交就是贡献者待审核的修订。
使用repo download命令实际上就是用git fetch获取到对应项目的refs/changes//patchset>引用,并自动切换到对应的引用上。
repo selfupdate
repo selfupdate
用于 repo 自身的更新。如果有新版本的repo存在, 这个命令会升级repo到最新版本。通常这个动作在repo sync时会自动去做, 所以不需要最终用户手动去执行。
选项:
-h, –help 显示这个帮助信息后退出.
–no-repo-verify 不要验证repo源码.
repo help
repo help [--all|command]
显示命令的详细帮助。
选项:
-h, –help 显示这个帮助信息后退出
-a, –all 显示完整的命令列表
总结
通过上面我们发现repo只是一个封装了git命令的工具,用来管理好多仓库的一个顶级目录。使用时:
- 先下载repo引导器
- 修改引导器的repo网址下载repo工具
- 创建存放default.xml的git仓库
- repo init初始化repo
- 拉取代码
本文章仅供学习交流用禁止用作商业用途,文中内容来水枂编辑,如需转载请告知,谢谢合作