Repo實踐指南


同步發布平台

未經允許,謝絕轉載

Repo簡介

Android使用Git作為代碼管理工具,開發了Gerrit進行代碼審核以便更好的對代碼進行集中式管理,還開發了Repo命令行工具,對Git命令進行封裝,將幾百個Git庫有效的進行組織。Repo並不是用來取代Git,而是用Python對Git進行了一定的封裝,簡化了對多個Git版本庫的管理。對應Repo管理的任何一個版本庫,都需要使用Git命令進行操作。

Repo工作流

下圖是Repo工作流,大體分為如下幾個核心步驟:

  1. 運行repo init,克隆Android的一個清單庫。這個清單庫是通過XML技術建立的版本庫清單。清單庫中的manifest.xml文件,列出了幾百個版本庫的克隆方式。包括版本庫的地址和工作區地址的對應關系,以及分支的對應關系。
  2. 運行repo sync,分別克隆這幾百個版本庫到本地的工作區。
  3. 運行repo start創建並切換到本地工作分支。
  4. 本地修改代碼,通過Git相關命令在某些項目中進行操作。
  5. 通過repo upload命令將代碼修改發布到代碼審核服務器。

Repo工作流

Repo引導腳本下載

在使用Repo前我們需要下載一個Repo引導腳本,Repo的核心功能不在其中,該引導腳本只是下載並加載完整Repo程序的工具。

mkdir ~/bin
PATH=~/bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo

這里需要提到一點的是早期的Repo引導腳本是一個Shell腳本,第一行就是#!/bin/sh,然后通過以下代碼完成Shell向Python的轉換,不過在較新版本中都是直接使用Python,第一行變成了#!/usr/bin/env python。現在網絡上的很多介紹都過時了。

magic='--calling-python-from-/bin/sh--'
"""exec" python -E "$0" "$@" """#$magic"

Repo清單庫介紹

一個清單庫可以包含多個清單文件和多個分支,每個清單文件和分支都有對應的版本。清單文件以XML格式組織。舉個例子:

repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest -b android-11.0.0_r27
<?xml version="1.0" encoding="UTF-8"?>
<manifest>

  <remote  name="aosp"
           fetch=".."
           review="https://android-review.googlesource.com/" />
  <default revision="refs/tags/android-11.0.0_r27"
           remote="aosp"
           sync-j="4" />

  <project path="build/make" name="platform/build" groups="pdk" >
    <copyfile src="core/root.mk" dest="Makefile" />
    <linkfile src="CleanSpec.mk" dest="build/CleanSpec.mk" />
    <linkfile src="buildspec.mk.default" dest="build/buildspec.mk.default" />
    <linkfile src="core" dest="build/core" />
    <linkfile src="envsetup.sh" dest="build/envsetup.sh" />
    <linkfile src="target" dest="build/target" />
    <linkfile src="tools" dest="build/tools" />
  </project>
  <project path="build/blueprint" name="platform/build/blueprint" groups="pdk,tradefed" />
  ...
</manifest>
  • remote元素,定義了名為aosp的遠程版本庫,其庫的基址為https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform,還定義了代碼審核服務器的地址https://android-review.googlesource.com/。當然,還可以定義更多的remote元素。
  • default元素,設置各個項目默認遠程版本庫為aosp,默認的的分支為refs/tags/android-11.0.0_r27。當然各個project元素還可以定義自己的remote和revision覆蓋默認的配置。
  • project元素,用於定義一個項目,path屬性表示在工作區克隆的位置,name屬性表示該項目的遠程版本庫的相對路徑。
  • project元素的子元素copyfile,定義了項目克隆后的一個附件動作,從src拷貝文件到dest。

通過Repo下載AOSP系統源碼

現在你可以通過Repo下載AOSP源碼了,但是由於牆的原因,我們沒有辦法直接下載,需要通過一些AOSP鏡像,其中使用比較多的是清華的鏡像,具體下載方式請參考官方介紹:https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/

Repo下載AOSP過程中可能遇到的問題

  1. 某些project找不到:
...
Checking out projects:  58% (432/733) platform/frameworks/hardware/interfaceserror: Cannot checkout platform/frameworks/layoutlib: ManifestInvalidRevisionError: revision refs/tags/android-10.0.0_r47 in platform/frameworks/layoutlib not found
error: in `sync -c -j4`: revision refs/tags/android-10.0.0_r47 in platform/frameworks/layoutlib not found

這個問題我一直沒有找到根因,可能是鏡像的問題,也可能是網絡的問題。解決方式發現哪個project找不到就單獨同步該項目,然后再整體同步。

repo sync -c platform/frameworks/layoutlib
repo sync -c -j4

Repo常用指令

Repo子命令實際上是Git命令的封裝。每一個Repo子命令都對應於repo源碼樹中subcmds目錄下的一個同名的Python文件。每一個repo子命令都可以通過下面的命令獲得幫助。

repo help <command>

當然你也可以參考Repo官方的介紹:https://source.android.com/setup/develop/repo

repo init

repo init –u URL [OPTIONS]

常用參數如下,其它參數通過repo help init查詢:

  • -u(--manifest-url):設定清單庫的Git服務器地址
  • -m(--manifest-name):當有多個清單文件時,指定清單庫中的某個清單為有效的清單文件。默認為default.xml
  • -b(--manifest-branch):選擇一個maniest倉庫中的一個特殊的分支

命令repo init 要完成如下操作:

  • 完成repo工具的完整下載,執行的Repo腳本只是引導程序
  • 克隆清單庫manifest.git (地址來自於-u 參數)
  • 克隆的清單庫位於manifest.git中,克隆到本地.repo/manifests。在之前的Repo版本中清單.repo/manifest.xml只是符號鏈接,它指向.repo/manifests/default.xml。在目前的repo版本中清單.repo/manifest.xml是一個實際的文件,通過include的方式引用.repo/manifests/default.xml
  • 如果.repo/manifests中有多個xml文件,repo init可以任意選擇其中一個,默認選擇是default.xml
  • .repo/manifests中執行git branch -a | cut -d / -f 3可以查看本地存放的已有的所有分支信息,但是該信息只是同步到你上次下載時的信息,如果需要最新信息需要先在該目錄中執行git pull操作。
repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest -b android-11.0.0_r27 # 在當前目錄出現了.repo文件夾
repo init -u git://192.168.0.125/manifest.git –m android.xml # 選擇的是android.xml里面的配置,.repo/manifest.xml便指向.repo/manifests/android.xml

repo sync

repo sync [<project>…]

用於參照清單文件.repo/manifest.xml克隆並同步版本庫。如果某個項目版本庫尚不存在,則執行repo sync 命令相當於執行git clone,如果項目版本庫已經存在,則相當於執行下面的兩條指令:

git remote update # 相當於對每一個remote源執行了fetch操作
git rebase origin/branch # 針對當前分支的跟蹤分支執行rebase操作

如果直接執行repo sync會同步所有project,如果后面指定project則只會同步指定的project。如repo sync platform/build

repo rebase

repo smartsync

可以通過一些選項設置同步的方式,比如是否在遇到第一個錯誤的時候就停止,是否強制刪除含有未提交修改的項目等等。

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

repo checkout <branchname>  [<project>…]

實際上是對git checkout命令的封裝,檢出之前由repo start創建的分支。但不能帶-b參數,所以不能用此命令來創建特性分支。

repo checkout aosp-dev 
repo checkout aosp-dev  platform/build  platform/bionic

repo branches

讀取各個項目的分支列表並匯總顯示。該命令實際上通過直接讀取.git/refs目錄下的引用來獲取分支列表,以及分支的發布狀態等。

repo branches [<project>…]
repo branches 
repo branches platform/build platform/bionic

repo diff

repo diff [<project>…]

實際是對git diff 命令的封裝,用於分別顯示各個項目工作區下的文件差異。

repo diff # 查看所有項目
repo diff platform/build platform/bionic # 只查看其中兩個項目

repo stage

實際是對git add --interactive命令的封裝、用於挑選各個項目工作區中的改動以加入暫存區。

repo stage -i [<project>…]

-i代表git add --interactive命令中的--interactive,給出個界面供用戶選擇。

repo prune

實際上是對git branch –d命令的封裝,該命令用於掃面項目的各個分支,並刪除已經合並的分支,用法如下:

repo prune [<project>…]

repo abandon

實際上是對git branch –D命令的封裝,用法如下:

repo abandon <branchname> [<project>…]

repo status

實際上是對git diff-indexgit diff-filse命令的封裝,同時顯示暫存區的狀態和本地文件修改的狀態

repo status platform/bionic

以上的實例輸出顯示了platform/bionic項目分支的修改狀態

  • 每個小節的首行顯示羡慕名稱,以及所在分支的名稱
  • 第一個字母表示暫存區的文件修改狀態
    • -:沒有改變
    • 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 origin_1 ssh://192.168.0.125/git_repo # 這個指令是根據xml文件添加的遠程分支,方便於向服務器提交代碼,執行之后的build目錄下看到新的遠程分支org
repo remote rm origin_1 # 刪除遠程倉庫

repo push

repo push <remotename> [--all |<project>…]

這是新添加的指令,用於向服務器提交代碼,repo會自己查詢需要向服務器提交的項目並提示用戶。

repo push org

repo forall

repo forall [<project>…] –c <command>

迭代器,可以在所有指定的項目中執行同一個shell指令

  • -c:后面所帶的參數着是shell指令
  • -p:在shell指令輸出之前列出項目名稱
  • -v:列出執行shell指令輸出的錯誤信息

額外的環境變量:

  • REPO_PROJECT:指定項目的名稱
  • REPO_PATH:指定項目在工作區的相對路徑
  • REPO_REMOTE:指定項目遠程倉庫的名稱
  • REPO_LREV:指定項目最后一次提交服務器倉庫對應的哈希值
  • REPO_RREV:指定項目在克隆時的指定分支,manifest里的revision屬性

另外,如果-c后面所帶的shell指令中有上述環境變量,則需要用單引號把shell指令括起來。

repo forall -c 'echo $REPO_PROJECT' # 輸出項目的名稱
repo forall -p -c git merge aosp-my-dev # 把所有項目多切換到master分支,該指令將會把aosp-my-dev分支合並到master分支
repo forall -c git tag aosp-mytag-1.0 # 在所有項目下打標簽
repo forall -c 'git remote add origin_1 ssh://jiangxin@192.168.0.125/$REPO_PROJECT.git' # 引用環境變量REPO_PROJECT添加遠程倉庫
repo forall -c git remote add origin_1 # 刪除遠程倉庫
repo forall –c git branch aosp-dev # 切換分支
repo forall –c git checkout –b aosp-dev # 創建分支
repo forall -c git reset --hard # 當repo sync時如果提示discarding xx commits時可以通過該命令廢棄所有提交,然后繼續repo sync

repo grep

相當於對git grep 的封裝,用於在項目文件中進行內容查找。

repo manifest

顯示manifest文件內容,可以通過-o參數輸出到指定的文件中。

repo manifest –o android.xml

repo version

顯示Repo的版本號,還會同時顯示Git/Python等依賴的應用版本。

repo upload

repo upload相當於git push,但是又有很大的不同。它不是將版本庫改動推送到克隆時的遠程服務器,而是推送到代碼審核服務器(Gerrit軟件架設)的特殊引用上,使用SSH協議。代碼審核服務器會對推送的提交進行特殊處理,將新的提交顯示為一個待審核的修改集,並進入代碼審查流程,只有當審核通過后,才會合並到官方正式的版本庫中。

repo upload [--re --cc] {[<project>]… | --replace <project>}
  • -h, --help:顯示幫助信息
  • -t:發送本地分支名稱到Gerrit代碼審核服務器
  • --replace:發送此分支的更新補丁集
  • --re=REVIEWERS:要求指定的人員進行審核
  • --cc=CC:同時發送通知到如下郵件地址

repo download

主要用於代碼審核者下載和評估貢獻者提交的修訂。

repo download {project change [patchset]}…

repo selfupdate

用於repo自身的更新


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM