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>…]