Repo Gerrit進階

本文須要有對git repo gerrit的基本使用,
這裏不說起過多的基本用法.html

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庫的名字/路徑。
注意,通常說來,一套安卓代碼都由好幾百個庫組成,上面只截取了一部分。app

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

這裏只說下revision,ide

  • 你能夠在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. git pushInsteadOf

試想一下這樣一個場景, 您的代碼下載自A服務器, 如今要往B服務器push代碼,該咋辦?
固然, 您可用git remote添加遠程信息,而後再用git push 新添加的遠程名 ...
我這裏講另外一個方法,就是pushInsteadOf,
eg:

vi ~/.gitconfig
[url "testB_address"]
    pushInsteadOf = testA_address

即,咱們僅須要在gitconfig裏配置一下,
push的時候用B服務器的地址,替換A服務器的地址,
這樣咱們push的時候,代碼就提交到B服務器了.

同理,可用
pullInsteadOf 替換 pull時的地址
InsteadOfpush 替換 push和pull時的地址

BTW,對 ~/.gitconfig文件的修改,您也可用命令

eg:
git config --global url.testB_address.insteadOf testA_address

11. Debug

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

repo --trace sync -c

12. 建議

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

    repo start 本地分支名 --all

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

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

    git pull --rebase
相關文章
相關標籤/搜索