repo簡介
Repo 是我們以 Git 為基礎構建的代碼庫管理工具,可以組織多個倉庫的上傳和下載。它是由一系列的Python腳本組成,封裝了一系列的Git命令,用來統一管理多個Git倉庫
一個大型的項目可能由很多小的倉庫組合而成的,為了方便統一管理各個子項目的Git倉庫,需要一個上層工具批量進行處理,因此repo誕生。
repo也會建立一個Git倉庫,用來記錄當前版本下各個子項目的Git倉庫分別處于哪一個分支,這個倉庫通常叫做:manifest倉庫。
安裝repo引導器
在安裝 Repo 時,必須先要確保已經安裝了 Git 工具,以及 Python2.7 + 的環境,下面是在linux下安裝的流程:
Downloading and installing Git and Python
sudo apt-get install git-core
sudo apt-get install python
Download and install Repo
$ mkdir ~/bin
$ PATH=~/bin:$PATH
$ curl https://raw.githubusercontent.com/esrlabs/git-repo/stable/repo > ~/bin/repo
$ chmod a+x ~/bin/repo
使用流程
- 查看repo引導器文件的內容
REPO_URL = 'https://github.com/esrlabs/git-repo’
REPO_REV = ‘stable’
分別是repo.git倉庫的url和檢出的branch,即下載repo工具的git倉庫
- repo init,這一步可以省略,第三步操作會自動執行這個
repo init會從1中指定的REPO_URL中拉出repo工具(在當前目錄會生成.repo/repo)
此時我們只是有了repo工具,但是要想管理多個git,還需要一個清單,來說明要管理那些git,從哪里拉去等等. 這個任務要依賴manifest.git了,正如之前提到的,在repo init的時候,要通過-u url來指定manifest.git的位置.
- repo init -u https://gitee.com/angerial/repo-test.git
注意:這里url指向的git倉庫需要有default.xml,即我們需要提前創建一個倉庫。
#就會初始化repo成功.
#但是我們要管理自己的倉庫(其實就是一個倉庫存放default.xml)
#這個倉庫的內容最簡單時是一個default.xml.
#default.xml內容如下:<?xml version="1.0" encoding="UTF-8" ?>
<manifest><remote fetch="https://gitee.com/openharmony/" name="origin" review="https://openharmony.gitee.com/openharmony/"/><default remote="origin" revision="master" sync-j="4" /><project name="graphic_utils" path="foundation/graphic/utils" />
</manifest>#可以看到,根元素manifest,里邊定義了remote,default,project.
#remote可以多個,每個定義了一個遠程拉取倉庫, fetch是倉庫的url, 可以使用”..”表示使用repo init -u url里的url
#default則設置每個項目的默認倉庫和默認分支
#project定義了一個項目,它指明一個遠程倉庫,和clone到本地來后的目錄名稱. name為項目的遠程倉庫名,以上代碼拉取的項目是git://localhost/helo
- 參考repo組成,修改相關文件,即拉取哪些倉庫
- 拉代碼到本地
repo sync -c
repo組成
Repo 主要包括兩部分:Repo 引導器(Google 稱之為 Repo launcher)和 Repo 命令的主體部分。那么 Repo 倉庫究竟有些什么東西呢,在我們初始化 Repo 倉庫之后,會出現一個. repo 的文件夾,里面有如下內容:
root@l-virtual-machine:~/test/repo/.repo# tree -L 1
├── manifests
├── manifests.git
├── manifest.xml -> manifests/default.xml
└── repo
3 directories, 1 file
當執行 repo init 命令來初始化倉庫的時候首先執行的就是 Repo 的引導腳本,該腳本會到我們指定的地方去下載 Manifest 倉庫,以及 Repo 命令主體部分。下載好之后就放在當前目錄下面的**.repo**目錄下,其中:
文件夾 | 用途 |
---|---|
manifests | 清單文件的倉庫 |
manifests.git | 清單文件的 Git 裸倉庫,不帶工作區 |
manifest.xml | 這是一個鏈接文件,指向你的用于初始化工作區的清單文件,即manifests/default.xml |
project.list | 一個文本文件,里面包含所有項目名字的列表 |
projects | 該文件夾下包含所有 git project 的裸倉庫,文件夾的層次結構跟工作區的布局一樣 |
repo | 這是 repo 命令的主體,其中也包含最新的 repo 命令,推薦使用這里面的 repo 命令 |
<?xml version="1.0" encoding="UTF-8" ?><manifest>
<remote fetch="https://gitee.com/openharmony/" name=“origin” review="https://openharmony.gitee.com/openharmony/"/>
<default remote=“origin” revision=“master” sync-j=“4” />
<project name=“graphic_utils” path=“foundation/graphic/utils” />
</manifest>
manifest 元素
xml 文件的根元素
remote 元素
可以存在一個或者多個 remote 元素,remote 元素指定了使用 repo upload 命令的時候,會將改變提交到哪個服務器。
name: 遠程git服務器的名字,直接用于git fetch, git remote 等操作
alias: 遠程git服務器的別名,如果指定了,則會覆蓋name的設定。在一個manifest(可以理解為default.xml)中, name不能重名,但alias可以重名。
fetch: 所有projects的git URL 前綴
review: 指定Gerrit的服務器名,用于repo upload操作。如果沒有指定,則repo upload沒有效果。
default 元素
default 元素中指定的屬性都是一些缺省的屬性。即如果 project 元素中不存在該屬性,則使用在 default 元素中指定的屬性。
revision:Git 分支的名字。如果 project 元素沒有指定 revision 屬性,那么就使用 default 元素的該屬性。revision 屬性的值可以是一個 git branch,git tag,也可以是一個 commit id。
sync-j:sync 的時候,并行工作的任務數。
sync-c:如果設置為 true,則在同步代碼的時候,將只會同步 project 元素中 revision 屬性中指定的分支。如果 project 元素沒有指定 revision 屬性,則使用 default 元素的 revision 屬性。
sync_s: 如果設置為true,則會同步git的子項目
remote: 之前定義的某一個remote元素中name屬性值,用于指定使用哪一個遠程git服務器。
project 元素
xml 文件中可以指定一個或者多個 project 元素。 每一個 project 元素都描述了一個需要 pull 到本地的 git 倉庫。
project 元素中有很多可以使用的屬性,在此只介紹幾個我們經常使用的屬性。
name: 唯一的名字標識project,同時也用于生成git倉庫的URL。格式如下:
remotefetch/{remote_fetch}/remotef?etch/{project_name}.git
path:可選的路徑,該 指定git clone出來的代碼存放在本地的子目錄。如果沒有指定,則以name作為子目錄名。
remote: 指定之前在某個remote元素中的name。
revision:指定需要獲取的git提交點,可以是master, refs/heads/master, tag或者SHA-1值。如果不設置的話,默認下載當前project,當前分支上的最新代碼。
sync_c: 如果設置為true,則只同步指定的分支(revision 屬性指定),而不是所有的ref內容。
sync_s: 如果設置為true,則會同步git的子項目。
groups: 列出project所屬的組,以空格或者逗號分隔多個組名。
upstream: 在哪個git分支可以找到一個SHA1。用于同步revision鎖定的manifest(-c 模式)。該模式可以避免同步整個ref空間。
annotation: 可以有多個annotation,格式為name-value pair。在repo forall 命令中這些值會導入到環境變量中。
remove-project: 從內部的manifest表中刪除指定的project。經常用于本地的manifest文件,用戶可以替換一個project的定義
Include元素
通過name屬性可以引入另外一個manifest文件(路徑相對與manifest repository’s root)。
常用命令
repo init
repo init -u manifest_git_path -m manifest_file_name -b branch_name --repo-url=repo_url --no-repo-verify
在當前目錄下安裝 Repo。這會產生一個 .repo/ 目錄,目錄包括裝 Repo 源代碼和標準 Android 清單文件的 Git 倉庫。.repo/ 目錄還包括 manifest.xml,是一個在 .repo/manifests/ 目錄選擇清單的符號鏈接。
選項:
-u: 指定Manifest庫的Git訪問路徑。
-m: 指定要使用的Manifest文件。
-b: 指定要使用Manifest倉庫中的某個特定分支。
–repo-url: 指定要檢查repo是否有更新的遠端repoGit庫的訪問路徑。
–no-repo-verify: 指定不檢查repo庫是否需要更新。
repo sync
repo sync [project_name]
用于參照清單文件克隆并同步版本庫。可以使用repo sync project_name的形式只克隆某個項目。
實現參照清單.repo/manifests.xml克隆并同步版本庫,如果版本庫不存在,則相當于執行
git clone
如果版本庫已經存在,則相當于執行
#對每個remote源進行fetch操作
git remote update#針對當前分支的跟蹤分支進行rebase操作
git rebase/origin/branch
選項:
-d:切換指定項目回到清單修正。如果該項目目前是一個主題分支那就有幫助,但清單修正是暫時需要。
-s:同步到一個已知的構建 manifest-server 在當前清單指定的元素。
-f:繼續同步其他項目,即使有項目同步失敗。
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
<branchname> [<rpoject>...]{{{repo checkout <branchname> [<project>...]}}}
切換分支。 實際上是對git checkout命令的封裝,但不能帶-b參數,所以不能用此命令來創建特性分支。
示例:
repo checkout liuq-dev
repo checkout liuq-dev skipper/build platform/bionic
repo branches
repo branches [<project>...]
查看分支。
示例:
repo branches
repo branches skipper/build skipper/release#查看可切換的分支
cd .repo/manifests
git branch -a | cut -d / -f 3
repo diff
repo diff [<project>...]
查看工作區文件差異。實際是對git diff命令的封裝,用于分別顯示各個項目工作區下的文件差異。在 commit 和工作目錄之間使用 git diff 顯示明顯差異的更改。
示例:
#查看所有項目
repo diff#只查看其中的兩個項目
repo diff skipper/build skipper/release
repo stage
repo stage -i [<project>...]
把文件添加到index表中。實際上是對git add –interactive命令的封裝,用于挑選各個項目中的改動以加入暫存區。
-i表示git add –interactive命令中的–interactive,給出一個界面供用戶選擇。
repo prune
repo prune [<project>...]
刪除已經合并分支。實際上是對git branch -d 命令的封裝,該命令用于掃描項目的各個分支,并刪除已經合并的分支。
repo abandon
repo abandon <branchname> [<rpoject>...]
刪除指定分支。實際是對git brance -D命令的封裝。
repo status
repo status [<project>...]
查看文件狀態。
示例:
#輸出skipper/build項目分支的修改狀態repo status skipper/build
每個小節的首行顯示項目名稱,以及所在的分支的名稱。
每個字母表示暫存區的文件修改狀態。
字母 | 含義 | 描述 |
---|---|---|
- | 無變化 | 沒有修改,在 HEAD 和在索引中是一樣的 |
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 org ssh://10.11.10.11/git_repo
這個指令根據xml文件添加的遠程分支,方便于向服務器提交代碼,執行之后的build目錄下看到新的遠程分支org。
#刪除遠程倉庫
repo remote rm org
repo push
repo push <remotename> [--all|<project>...]
向服務器提交代碼。repo會自己查詢需要向服務器提交的項目并提示用戶。
示例:
repo push org
repo forall
repo forall [<project>...] -c <command>
迭代器,可以在所有指定的項目中執行同一個shell指令。
選項:
-c 后面所帶的參數是shell指令,即執行命令和參數。命令是通過 /bin/sh 評估的并且后面的任何參數就如 shell 位置的參數通過。
-p 在shell指令輸出之前列出項目名稱,即在指定命令的輸出前顯示項目標題。這是通過綁定管道到命令的stdin,stdout,和 sterr 流,并且用管道輸送所有輸出量到一個連續的流,顯示在一個單一的頁面調度會話中。
-v 列出執行shell指令輸出的錯誤信息,即顯示命令寫到 sterr 的信息。
附加環境變量:
REPO_PROJECT 指定項目的名稱
REPO_PATH 指定項目在工作區的相對路徑
REPO_REMOTE 指定項目遠程倉庫的名稱
REPO_LREV 指定項目最后一次提交服務器倉庫對應的哈希值
REPO_RREV 指定項目在克隆時的指定分支,manifest里的revision屬性
如果-c后面所帶的shell指令中有上述環境變量,則需要用單引號把shell指令括起來。
添加環境變量
repo forall -c 'echo $REPO_PROJECT'
repo forall -c 'echo $REPO_PATH'
合并多個分支
repo forall -p -c git merge topic
把所有項目都切換到master分支,執行上述指令將topic分支合并到master分支。
打標簽
repo forall -c git tag crane-stable-1.6
在所有項目下打標簽。
設置遠程倉庫
repo forall -c 'git remote add korg ssh://xiong@172.16.31/$REPO_PROJECT.git'
引用環境變量REPO_PROJECT添加遠程倉庫。
#刪除遠程倉庫。
repo forall -c git remote rm korg
創建特性分支
repo forall -c git branch crane-dev
repo forall -c git checkout -b crane-dev
repo grep
repo grep {pattern | -e pattern} [<project>...]
打印出符合某個模式的行。相當于對 git grep 的封裝,用于在項目文件中進行內容查找。
示例:
#要找一行, 里面有#define, 并且有'MAX_PATH' 或者 'PATH_MAX':
repo grep -e '#define' --and -\( -e MAX_PATH -e PATH_MAX \)#查找一行, 里面有 'NODE'或'Unexpected', 并且在一個文件中這兩個都有的.
repo grep --all-match -e NODE -e Unexpected
repo manifest
repo manifest [-o {-|NAME.xml} [-r]]
manifest檢驗工具,用于顯示manifest文件內容。
選項:
-h, –help 顯示這個幫助信息后退出
-r, –revision-as-HEAD 把某版次存為當前的HEAD
-o -|NAME.xml, –output-file=-|NAME.xml 把manifest存為NAME.xml
repo version
repo version
顯示repo的版本號。
選項:
-h, –help 顯示這個幫助信息后退出.
repo upload
repo upload [--re --cc] {[<project>]...|--replace <project>}
repo upload 相當于git push,但是又有很大的不同。它不是將版本庫改動推送到代碼審核服務器(Gerrit軟件架設)的特殊引用上,使用SSH協議。代碼審核服務器會對推送的提交進行特殊處理,將新的提交顯示為一個待審核的修改集,并進入代碼審核流程,只有當審核通過后,才會合并到官方正式的版本庫中。
選項:
-h, –help 顯示幫助信息
-t 發送本地分支名稱到Gerrit代碼審核服務器
–replace 發送此分支的更新補丁集
–re=REVIEWERS 要求指定的人員進行審核
–cc=CC 同時發送通知到如下郵件地址
repo download
repo download {project change[/patchset]}
repo download命令主要用于代碼審核者下載和評估貢獻者提交的修訂。
貢獻者的修訂在Git版本庫中refs/changes//引用方式命名(缺省的patchset為1),和其他Git引用一樣,用git fetch獲取,該引用所指向的最新的提交就是貢獻者待審核的修訂。
使用repo download命令實際上就是用git fetch獲取到對應項目的refs/changes//patchset>引用,并自動切換到對應的引用上。
repo selfupdate
repo selfupdate
用于 repo 自身的更新。如果有新版本的repo存在, 這個命令會升級repo到最新版本。通常這個動作在repo sync時會自動去做, 所以不需要最終用戶手動去執行。
選項:
-h, –help 顯示這個幫助信息后退出.
–no-repo-verify 不要驗證repo源碼.
repo help
repo help [--all|command]
顯示命令的詳細幫助。
選項:
-h, –help 顯示這個幫助信息后退出
-a, –all 顯示完整的命令列表
總結
通過上面我們發現repo只是一個封裝了git命令的工具,用來管理好多倉庫的一個頂級目錄。使用時:
- 先下載repo引導器
- 修改引導器的repo網址下載repo工具
- 創建存放default.xml的git倉庫
- repo init初始化repo
- 拉取代碼
本文章僅供學習交流用禁止用作商業用途,文中內容來水枂編輯,如需轉載請告知,謝謝合作