25.7 repo的命令集

repo子命令实际上是Git命令的或简单或复杂的封装。每一个repo子命令都对应于repo源码树中subcmds目录下的一个同名的Python文件。每一个repo子命令都可以通过下面的命令获得帮助。


repo help<command>


通过阅读代码,可以更加深入地了解repo子命令的封装。

1.repo init命令

repo init子命令主要完成检出清单版本库(manifest.git),以及配置Git用户的用户名和邮件地址的工作。

实际上,完全可以进入到.repo/manifests目录,用Git命令操作清单库。对manifests的修改不会因为执行repo init而丢失,除非是处于未跟踪状态。

2.repo sync命令

repo sync子命令用于参照清单文件克隆或同步版本库。如果某个项目版本库尚不存在,则执行repo sync命令相当于执行git clone。如果项目版本库已经存在,则相当于执行下面的两个命令:

git remote update

相当于对每一个remote源执行fetch操作。

git rebase origin/branch

针对当前分支的跟踪分支执行rebase操作。不采用merge而是采用rebase,目的是减少提交数量、方便评审(Gerrit)。

3.repo start命令

repo start子命令实际上是对git checkout-b命令的封装。为指定的项目或所有项目(若使用—all参数),以清单文件中为项目设定的分支或里程碑为基础,创建特性分支。特性分支的名称由命令的第一个参数指定。相当于执行checkout-b。

用法如下:


repo start<newbranchname>[—all|<project>…]


4.repo status命令

repo status子命令实际上是对git diff-index、git diff-files命令的封装,同时显示暂存区的状态和本地文件修改的状态。

用法如下:


repo status[<project>…]


示例输出:


project repo/branch devwork

-m subcmds/status.py


上面的示例输出显示了repo项目的devwork分支的修改状态。

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

之后显示该项目中文件的变更状态。头两个字母显示变更状态,后面显示文件名或其他变更信息。

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

其实是git-diff-index命令输出中的状态标识,用大写显示。

〇-:没有改变

〇A:添加(不在HEAD中,在暂存区)

〇M:修改(在HEAD中,在暂存区,内容不同)

〇D:删除(在HEAD中,不在暂存区)

〇R:重命名(不在HEAD中,在暂存区,路径修改)

〇C:拷贝(不在HEAD中,在暂存区,从其他文件拷贝)

〇T:文件状态改变(在HEAD中,在暂存区,内容相同)

〇U:未合并,需要冲突解决

第二个字母表示工作区文件的更改状态。

其实是git-diff-files命令输出中的状态标识,用小写显示。

〇-:新/未知(不在暂存区,在工作区)

〇m:修改(在暂存区,在工作区,被修改)

〇d:删除(在暂存区,不在工作区)

两个表示状态的字母后面,显示文件名信息。如果有文件重命名还会显示改变前后的文件名及文件的相似度。

5.repo checkout命令

repo checkout子命令实际上是对git checkout命令的封装。检出之前由repo start创建的分支。

用法如下:


repo checkout<branchname>[<project>…]


6.repo branches命令

repo branches读取各个项目的分支列表并汇总显示。该命令实际上通过直接读取.git/refs目录下的引用来获取分支列表,以及分支的发布状态等。

用法如下:


repo branches[<project>…]


输出示例:


*P nocolor|in repo

repo2|


第一个字段显示分支的状态:是否当前分支,分支是否发布到代码审核服务器上?

第一个字母若显示星号(*),则含义是此分支为当前分支。

第二个字母若为大写字母P,则含义是分支的所有提交都发布到代码审核服务器上了。

第二个字母若为小写字母p,则含义是只有部分提交被发布到代码审核服务器上。

若不显示P或p,则表明分支尚未发布。

第二个字段为分支名。

第三个字段为以竖线(|)开始的字符串,表示该分支存在于哪些项目中。

〇in all projects

该分支处于所有项目中。

〇in project1 project2

该分支只在特定项目中定义。如:project1、project2。

〇not in project1

该分支不存在于这些项目中。即除了project1项目外,其他项目都包含此分支。

7.repo diff命令

repo diff子命令实际上是对git diff命令的封装,用于分别显示各个项目工作区下的文件差异。

用法如下:


repo diff[<project>…]


8.repo stage命令

repo stage子命令实际上是对git add—interactive命令的封装,用于挑选各个项目工作区中的改动(修改、添加等)以加入暂存区。

用法如下:


repo stage-i[<project>…]


9.repo upload命令

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

用法如下:


repo upload[—re—cc]{[<project>]…|—replace<project>}

参数:

-h,—help显示帮助信息。

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

—replace发送此分支的更新补丁集。注意使用该参数,只能指定一个项目。

—re=REVIEWERS,—reviewers=REVIEWERS

要求由指定的人员进行审核。

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


确定推送服务器的端口

分支改动的推送是发给代码审核服务器,而不是下载代码的服务器。使用的协议是SSH协议,但是使用的并非标准端口。如何确认代码审核服务器上提供的特殊SSH端口呢?

在执行repo upload命令时,repo会通过访问代码审核Web服务器的/ssh_info的Url获取SSH服务端口,默认为29418。这个端口,就是repo upload发起推送的服务器的SSH服务端口。

修订集修改后重新传送

只有已经通过repo upload命令在代码审查服务器上提交了一个修订集,才会得到一个修订号。关于此次修订的相关讨论会发送到提交者的邮箱中。如果修订集有误没有通过审核,可以重新修改代码,再次向代码审核服务器上传修订集。

一个修订集修改后再次上传,如果修订集的ID不变那将是非常有用的,因为这样相关的修订集都在代码审核服务器的同一个界面中显示。

在执行repo upload时会弹出一个编辑界面,提示在方括号中输入修订集编号,否则会在代码审查服务器上创建新的ID。有一个办法可以不用手工输入修订集,如下:


repo upload—replace project_name


当使用—replace参数后,repo会检查本地版本库名为refs/published/branch_name的特殊引用(上一次提交的修订),获得其对应的提交SHA1哈希值。然后在代码审核服务器的refs/changes/命名空间下的特殊引用中寻找和提交SHA1哈希值匹配的引用,找到的匹配引用其名称中就所包含有变更集ID,直接用此变更集ID作为新的变更集ID提交到代码审核服务器。

Gerrit服务器魔法

repo upload命令执行推送,实际上会以类似如下的命令行格式进行调用:


git push—receive-pack='gerrit receive-pack—reviewer charlie@example.com'\

ssh://review.example.com:29418/project HEAD:refs/for/master


Gerrit服务器接收到git push请求后,会自动将对分支的提交转换为修订集,显示于Gerrit的提交审核界面中。Gerrit的魔法破解的关键点就在于git push命令的—receive-pack参数。即交由gerrit-receive-pack命令执行提交,进入非标准的git处理流程,将提交转换为在refs/changes命名空间下的引用,而不在refs/for命名空间下创建引用。

10.repo download命令

repo download命令主要用于代码审核者下载和评估贡献者提交的修订。贡献者的修订在Git版本库中以refs/changes/<changeid>/<patchset>引用方式命名(默认的patchset为1),和其他Git引用一样,用git fetch获取,该引用所指向的最新的提交就是贡献者待审核的修订。使用repo download命令实际上就是用git fetch获取到对应项目的refs/changes/<changeid>/patchset>引用,并自动切换到对应的引用上。

用法如下:


repo download{project change[/patchset]}…


11.repo rebase命令

repo rebase子命令实际上是对git rebase命令的封装,该命令的参数也作为git rebase命令的参数,但-i参数仅当对一个项执行时才有效。

用法如下:


命令行:repo rebase{[<project>…]|-i<project>…}

参数:

-h,—help显示帮助并退出

-i,—interactive交互式的变基(仅对一个项目时有效)

-f,—force-rebase向git rebase命令传递—force-rebase参数

—no-ff向git rebase命令传递-no-ff参数

-q,—quiet向git rebase命令传递—quiet参数

—autosquash向git rebase命令传递—autosquash参数

—whitespace=WS向git rebase命令传递—whitespace参数


12.repo prune命令

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

用法如下:


repo prune[<project>…]


25.7 repo的命令集 - 图1