Repo Gerrit進階

本文需要有對git repo gerrit的基本使用,
這裏不提及過多的基本用法.

00. Books

01. Repo 的產生

Android版本庫衆多的原因,主要原因是版本庫太大以及Git不能部分檢出。
如果所有的東西都放在一個庫中,而某個開發團隊感興趣的可能就是某個驅動,
或者是某個應用,卻要下載如此龐大的版本庫,是有些說不過去。

git也有submodule供多個庫下載,但這功能使用不方便,
其侷限性和麻煩可參看
http://www.worldhello.net/got...

如果是你,有什麼方案來管理這麼多的庫?

Repo是Google開發的用於管理Android版本庫的一個工具。
Repo並不是用於取代Git,是用Python對Git進行了一定的封裝,簡化了對多個Git版本庫的管理。
對於repo管理的任何一個版本庫,都還是需要使用Git命令進行操作

02 Repo 如何組織這麼多庫 --manifest文件?

<?xml version="1.0" encoding="UTF-8"?>
<manifest>

  <remote  name="aosp"
           fetch=".." />
  <default revision="refs/tags/android-7.1.0_r4"
           remote="aosp"
           sync-j="4" />

  <project path="build" name="platform/build" groups="pdk,tradefed" >
    <copyfile src="core/root.mk" dest="Makefile" />
  </project>
  <project path="build/blueprint" name="platform/build/blueprint" groups="pdk,tradefed" />
......

從上看出,repo用清單文件來管理, 其內容爲版本的地址,默認分支名,遠程庫和本地路徑對應關係。
一個project對應一個庫,path爲本地切出來的工作目錄的路徑,也就是我們看到的代碼路徑,
name爲對應的遠程git庫的名字/路徑。
注意,一般說來,一套安卓代碼都由好幾百個庫組成,上面只截取了一部分。

關於manifests更多的信息可查看你代碼根目錄的
.repo/repo/docs/manifest-format.txt

這裏只說下revision,

  • 你可以在project裏通過revision指定與清單文件default裏不一樣的分支,

revision的值可能是分支/tag/commitID等形式

  • 你也可以用repo manifest -r命令生成帶revision信息的清單文件,可用於代碼發佈

生成的一個例子:

<project name="device/qcom/common" revision="3a83da1dff148dd709caac602693d3295bd0a18b" upstream="refs/heads/省略">

03 repo init 在幹什麼?

$repo init --help
Usage: repo init [options]

Options:
......  Manifest options:
    -u URL, --manifest-url=URL
                        manifest repository location
    -b REVISION, --manifest-branch=REVISION
                        manifest branch or revision
    -m NAME.xml, --manifest-name=NAME.xml
                        initial manifest file
    --mirror            create a replica of the remote repositories rather
                        than a client working directory
    --reference=DIR     location of mirror directory
    --depth=DEPTH       create a shallow clone with given depth; see git clone
......  repo Version options:

    --repo-url=URL      repo repository location
    --repo-branch=REVISION

repo init用法如上, 我們一般下載code的方式爲

repo init -u xxx -b yyy -m zzz.xml
repo sync -c

注意

  • -m 當有多個清單文件,可以指定清單庫的某個清單文件爲有效的清單文件

repo init命令執行後主要乾了兩件事

  • 下載repo到.repo/repo裏
  • 下載並檢出-u所指定的manifest庫,並建立.repo/manifest.xml鏈接

對於第一步大家可能比較疑問,不是已經有個repo了嗎?爲什麼還在下載repo?
實際上,我們執行的repo命令只是相當於個當函數,真正的執行命令(如repo sync)
都是.repo/repo/subcmds裏的,
該子命令都用python寫的, 所以當有需要,或者執行出錯時想查看源碼的話可在此目錄下查看.

04 --mirror --reference作用

讓我們想個問題,假設你一套代碼有100G,

  • 你們是異地協作協作,如需要上海/北京兩地辦公,主服務器在北京,網絡很慢,
    如何爲上海的同事減少下代碼時間? 如何緩解主服務器的壓力?
  • 你們都在一個地辦公,多人公用一個服務器, 如何節省下載代碼時間? 節省服務器空間?
  • 你作爲SCM,每天都要完全clean編譯版本, 如何更快的構建?

當然我們這隻講repo本身提供的方法,

  • --mirror 建立和上游Android的版本庫一模一樣的鏡像
  • --reference 通過引用已下載的mirror或者代碼加快下載速度,常用使用場景:

    • DailyBuild
    • 一套代碼兼容多個機型
    • 一套代碼需要多個副本
    • 多個人共用服務器

具體操作爲
先通過

repo init .... --mirror

建立一個本地的鏡像,
然後下載代碼時引用這個鏡像

repo init .... --reference=鏡像路徑
repo sync -c

如果此時主服務器庫容量增加到120G,而你的鏡像沒更新,
那麼理論上新下載代碼只需要下載20G的數據,
N套代碼佔用的空間爲100G(鏡像的) + 20G*N (新代碼)
大家可用

du -sh .repo

命令統計.

注意:
不用擔心你用reference下的代碼和主服務器的不同步,
git會自動進行三方對比的,保證能獲取到-u 指定的地址裏的代碼是最新的.

05 Gerrit Change-Id

graph TD;
  title(repo gerrit簡單工作流程);
  init(repo init/sync) --> start(repo start xxx --all);
  start --> gitmodify(單個庫的修改和git流程一樣);
  gitmodify --> upload(上傳到Gerrit repo upload/git push);
  upload --> review(審覈 +1 +2);
  review-- 通過 --> submit(Gerrit submit);
  review-- 不通過 --> gitmodify;

Change-Id由git commit時調用.git/hooks/commit-msg鉤子生成的,
gerrit靠該id來區分同一分支下是否爲同一個提交,
事實上,只要gerrit未submit,可以在本地git commit XX --amend修正提交後,
可以再次提交,成爲新的patchset,但提交號不變.

06 repo upload時gerrit帳號名與郵箱前綴不一致

repo upload時默認是用配置的郵箱前綴做爲push的用戶名,
如果您的郵箱前綴和gerrit賬戶名不一致,需要做如下配置

$ cat ~/.gitconfig
[review "您的地址"]
    username = 您的帳號名

07 Gerrit command

該功能可能SCM用得多,用於實現批處理腳本.
此處只看下用法

$ ssh -p 端口號 用戶名@地址 gerrit
Available commands of gerrit are:

   apropos              Search in Gerrit documentation
   ban-commit           Ban a commit from a project's repository
   create-account       Create a new batch/role account
   create-branch        Create a new branch
   create-group         Create a new account group
   create-project       Create a new project and associated Git repository
   flush-caches         Flush some/all server caches from memory
   gc                   Run Git garbage collection
   gsql                 Administrative interface to active database
   ls-groups            List groups visible to the caller
   ls-members           List the members of a given group
   ls-projects          List projects visible to the caller
   ls-user-refs         List refs visible to a specific user
   plugin
   query                Query the change database
   receive-pack         Standard Git server side command for client side git push
   rename-group         Rename an account group
   review               Verify, approve and/or submit one or more patch sets
   set-account          Change an account's settings
   set-members          Modify members of specific group or number of groups
   set-project          Change a project's settings
   set-project-parent   Change the project permissions are inherited from
   set-reviewers        Add or remove reviewers on a change
   show-caches          Display current cache statistics
   show-connections     Display active client SSH connections
   show-queue           Display the background work queues
   stream-events        Monitor events occurring in real time
   test-submit
   version              Display gerrit version

See 'gerrit COMMAND --help' for more information.

08 cherry-pick rebase

這個可看下git書箱學習下,工作中也用得多,提高效率.

09 repo sync (-n -l)

-n -l參數解釋如下:

  -l, --local-only      only update working tree, don't fetch
  -n, --network-only    fetch only, don't update working tree

其實repo sync = repo sync -n + repo sync -l
如果你只想獲取更新到.repo庫裏, 不更新本地代碼, 可加上 -n參數
如果你之前已經獲取了更新,只有一兩個庫更新出錯,
而你重新repo sync -c一次都得半小時,
那可以先repo sync -l, 然後單獨的更新出錯的庫.

我一般更新都用命令

repo sync -c -f
repo sync -c -l

備註:
再運行次加-l主要是更新時可能信息很多,中間有些出錯,
而我有不想慢慢看終端找出錯信息,所以乾脆再讓他更新下
本地工作目錄,這樣方便查找出錯信息.

10 Debug

有時候有些運行命令出錯了,可加--trace參數查看更多信息
(git的調試方法請查看progit一書)
eg:

repo --trace sync -c

11 建議

  • 新下載代碼後,分支處於no branch狀態,建議下載代碼後用

    repo start 本地分支名 --all

    建個分支,該分支名爲本地分支名,可任意取名

  • 該分支僅用於和服務同步,更新代碼,要修改的話用repo start xx建立個新分支
    不然你本地在修改,服務器也修改,會造成歷史記錄很亂,
    有時導致編譯出來的代碼有啥隱含bug.
    當然,您也可用

    git pull --rebase
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章