1. 程式人生 > >Android下的配置管理之道之repo的使用

Android下的配置管理之道之repo的使用

谷歌對android的原始碼管理使用的是git。但是在git的基礎上,谷歌開發出來了一套新的工具,python寫的一套指令碼,名字是repo。

Android原始碼工程(AOSP)是非常多的git倉庫組成的。目前估計有上百個獨立的git倉庫。
怎麼管理這些倉庫呢?使用一個清單檔案(maniest.xml)來管理每個倉庫。
這個xml也需要個倉庫存放來管理,就是manifest.git 倉庫。
那怎麼來下載一套aosp的程式碼呢?就是使用repo工具,通過manifest.xml 來下載所有的倉庫,所有的程式碼。

到目前為止,我們提到了三種類型的Git倉庫,分別是Repo倉庫、Manifest倉庫和AOSP子專案倉庫。Repo倉庫通過Manifest倉庫可以獲得所有AOSP子專案倉庫的元資訊。有了這些元資訊之後,我們就可以通過Repo倉庫裡面的Python指令碼來操作AOSP的子專案。
repo是個工具倉庫,這個工具倉庫中有個一個檔案,名字是repo。這個是一個引導指令碼。我們一般會使用這個引導指令碼來把整個repo倉庫下載下來,整個倉庫有了才會有整個功能。一個單一的repo檔案裡面程式碼有限的,功能有限的。

manifest是一個管理xml的倉庫,每個xml裡面都是列的谷歌各個子專案git的相關資訊。

安裝Repo

一個repo檔案,python寫的。幾百行程式碼。

可以從清華aosp映象網站git clone下一個整個倉庫。然後把倉庫裡面的repo檔案複製到 /usr/local/bin 目錄下面。

https://aosp.tuna.tsinghua.edu.cn/tools/repo
$ git clone https://aosp.tuna.tsinghua.edu.cn/tools/repo                                                                               
Cloning into 'repo'
... remote: Counting objects: 3967, done. remote: Compressing objects: 100% (1798/1798), done. remote: Total 3967 (delta 2555), reused 3392 (delta 2108) Receiving objects: 100% (3967/3967), 1.97 MiB | 820.00 KiB/s, done. Resolving deltas: 100% (2555/2555), done.

我們可以看到repo倉庫裡面的所有的檔案,其中有一個repo檔案。

$ tree repo                                                                                                                            
repo
├── color.py
├── command.py ├── COPYING ├── docs │ └── manifest-format.txt ├── editor.py ├── error.py ├── event_log.py ├── git_command.py ├── git_config.py ├── gitc_utils.py ├── git_refs.py ├── git_ssh ├── hooks │ ├── commit-msg │ └── pre-auto-gc ├── main.py ├── manifest_xml.py ├── pager.py ├── platform_utils.py ├── platform_utils_win32.py ├── progress.py ├── project.py ├── pyversion.py ├── README.md ├── repoM ├── subcmds │ ├── abandon.py │ ├── branches.py │ ├── checkout.py │ ├── cherry_pick.py │ ├── diffmanifests.py │ ├── diff.py │ ├── download.py │ ├── forall.py │ ├── gitc_delete.py │ ├── gitc_init.py │ ├── grep.py │ ├── help.py │ ├── info.py │ ├── __init__.py │ ├── init.py │ ├── list.py │ ├── manifest.py │ ├── overview.py │ ├── prune.py │ ├── rebase.py │ ├── selfupdate.py │ ├── smartsync.py │ ├── stage.py │ ├── start.py │ ├── status.py │ ├── sync.py │ ├── upload.py │ └── version.py ├── SUBMITTING_PATCHES.md ├── tests │ ├── fixtures │ │ ├── gitc_config │ │ └── test.gitconfig │ ├── test_git_config.py │ └── test_wrapper.py ├── trace.py └── wrapper.py 5 directories, 59 files

安裝完成repo命令就可以執行一下。會輸出一些幫助資訊的。

$ repo                                                                                                                         
usage: repo COMMAND [ARGS]
The most commonly used repo commands are:
  abandon        Permanently abandon a development branch
  branch         View current topic branches
  branches       View current topic branches
  checkout       Checkout a branch for development
  cherry-pick    Cherry-pick a change.
  diff           Show changes between commit and working tree
  diffmanifests  Manifest diff utility
  download       Download and checkout a change
  grep           Print lines matching a pattern
  info           Get info on the manifest branch, current branch or unmerged branches
  init           Initialize repo in the current directory
  list           List projects and their associated directories
  overview       Display overview of unmerged project branches
  prune          Prune (delete) already merged topics
  rebase         Rebase local branches on upstream branch
  smartsync      Update working tree to the latest known good revision
  stage          Stage file(s) for commit
  start          Start a new branch for development
  status         Show the working tree status
  sync           Update working tree to the latest revision
  upload         Upload changes for code review
See 'repo help <command>' for more information on a specific command.
See 'repo help --all' for a complete list of recognized commands.

我們在一個已經repo init過的目錄下面執行會顯示幫助資訊的,每個列出來的都是一個repo的子命令。
和git類似,git clone,其中clone是git的一個子命令,每個子命令又有許多選項引數等。repo 也是類似的。

一般的我們常用的就是 repo init  和  repo sync 2個命令。

repo init

repo指令碼安裝好了我們就可以下載aosp程式碼。首先是新建個目錄,然後執行repo init命令。也就是對這個空目錄進行初始化。
在初始化過程中會把完整的repo倉庫下載下來,完整的repo倉庫會有更多其他功能,其他子命令,其他選項等。

$ repo                                                                                                                                 
error: repo is not installed.  Use "repo init" to install it here.
隨便一個目錄執行repo命令是會保持的,然後會提示你先 repo init 安裝,這個安裝就是會安裝到當前目錄,在當前目錄下面的.repo 目錄。一個隱藏目錄。
建立工作目錄:
mkdir aosp && cd aosp

初始化倉庫:
一般的是這樣一個簡單的命令:
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest
但是呢國內是不行的。這個命令中-u後面跟的就是一個manifest清單倉庫。一般叫manifest名。這個倉庫名可以是其他的,通常不會改。


repo init -u https://source.codeaurora.org/quic/la/platform/manifest.git \
-b release -m LA.UM.6.6.r1-02700-89xx.0.xml \
--repo-url=https://aosp.tuna.tsinghua.edu.cn/tools/repo \
--repo-branch=stable

repo init的選項

$ repo  init  -h

Usage: repo init -u url [options]

Options:
  -h, --help            show this help message and exit

  Logging options:
    -q, --quiet         be quiet

  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
    --archive           checkout an archive instead of a git repository for
                        each project. See git archive.
    -g GROUP, --groups=GROUP
                        restrict manifest projects to ones with specified
                        group(s) [default|all|G1,G2,G3|G4,-G5,-G6]
    -p PLATFORM, --platform=PLATFORM
                        restrict manifest projects to ones with a specified
                        platform group [auto|all|none|linux|darwin|...]
    --no-clone-bundle   disable use of /clone.bundle on HTTP/HTTPS

  repo Version options:
    --repo-url=URL      repo repository location
    --repo-branch=REVISION
                        repo branch or revision
    --no-repo-verify    do not verify repo source code

  Other options:
    --config-name       Always prompt for name/e-mail

我們還拿之前那個高通的下載程式碼的命令來講。基本上常用的選項都用上了。

repo init -u https://source.codeaurora.org/quic/la/platform/manifest.git \
-b release -m LA.UM.6.6.r1-02700-89xx.0.xml \
--repo-url=https://aosp.tuna.tsinghua.edu.cn/tools/repo \
--repo-branch=stable

-u選項,這個選項和 –manifest-url 這個長選項是一樣的,效果相同。在linux中命令有的有長選項,
有的有短選項,有的是符合posix標準的選項的等等。這個選項後面是要跟一個url的,這個url就是
manifest倉庫的url地址。這個倉庫要有許可權下載。

-b選項,這個是設定manifest倉庫的分支的,manifest.xml是放到git中管理,在git中就有可能有不同
的分支的。例如這裡高通就使用了一個release分支來存放manifest.xml檔案。當然這個分支名稱可以隨便
取的。

-m選項,這個是指定初始化的時候使用 哪個xml檔案。也就是-u決定manifest倉庫路徑地址,-b指定
manifest倉庫分支,-m指定這個分支下的哪個xml檔案。三個選項就決定了一個唯一的manifest.xml檔案

注意:有的公司是使用不同的manifest分支來管理整套安卓原始碼的。有的公司是使用幾個manifest分支,
每個分支下面使用不同的xml檔案來管理整個安卓原始碼的。這2中方式各有利弊吧。谷歌是通過不同分支來管理。
高通是通過不同的xml檔案來管理整套安卓原始碼的。這個明顯的區別就是有沒有使用-m選項。

#清華映象下載aosp的repo init命令:
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest \
-b android-4.0.1_r1 \
--repo-url=https://aosp.tuna.tsinghua.edu.cn/tools/repo \
--repo-branch=stable

–repo-url選項,這個指定repo工具倉庫的地址,在repo init的時候就會通過這個地址來把repo倉庫
下載下來。

–repo-branch選項,這個指定repo倉庫的分支,上面也說過,是個git倉庫就有可能有不同的分支的。

repo init的其他選項

-q選項,就是不列印很多log,就是使repo init命令執行時候列印的日誌少一些。

–depth=DEPTH選項,倉庫 git clone中的depth,就是下載git倉庫的時候歷史記錄個數可以指定。
就是下載的git歷史個數可以少一些,少的話下載速度就快了。不必拉取太多沒用的歷史提交記錄。

–archive選項,這個選項是在repo sync後不是把程式碼檢出,而是打包,打包壓縮。這個就是當你需要
下載程式碼然後 複製分享給誰的時候 最好打個包整體複製。

-g,-p選項,-g意思是group,-p意思是platform。在manifest.xml中可以對各個git倉庫進行分組,
分平臺,然後只下這個指定的goup中的倉庫,只下這個platform指定的倉庫。可以讓開發少下載程式碼。
這個分組到介紹manifest.xml 的時候在具體介紹。

這個幾個選項是無關痛癢的,想用就用上。水平高,瞭解的話就用上。如果真是小白上面的不用也沒關係的,
不用程式碼一樣下載。

建立本地mirror加快程式碼下載速度

安卓原始碼是幾百個倉庫組成的,程式碼量都是幾十GB的。一個kernel都要有1個GB大小。怎麼才能快速的下載
程式碼呢?那就是本地建個mirror。就是說你下載了好幾套程式碼,每個程式碼都放在了不同的目錄,這幾套程式碼
很多都是重複的,我們把重複的共享使用一個目錄,這個就是mirror。這個mirror主要是git裸倉庫。

上面介紹repo init選項的時候漏了2個選項一個就是–mirror。通過名稱我們就可以猜到這個是建立本地
mirror時候用的。

具體用法就是在repo init命令中加上這個選項–mirror就行了。初次建立需要在一個空目錄下面執行命令。
一般的馬哥會把本地mirror統一放到/home/mirror 路徑下面。

# 命令如下:
mkdir /home/mirror && cd /home/mirror &&  rm -rf .repo

repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest \
-b android-4.0.1_r1 \
--repo-url=https://aosp.tuna.tsinghua.edu.cn/tools/repo \
--repo-branch=stable --mirror

這樣就初始化好本地映象了。然後執行repo sync命令。網路不好的情況請多執行 repo sync 幾次。

如果不是一個空目錄是會報錯的

fatal: --mirror is only supported when initializing a new workspace.
Either delete the .repo folder in this workspace, or initialize in another location.

使用本地mirror加快程式碼下載速度

本地mirro建立完成後,以後的repo init命令中就可以使用了。具體用法是 repo init 命令中 加上–reference /home/mirror
這樣就指定使用/home/mirror路徑下面的本地映象倉庫了。這樣下程式碼會很快。

注意:這個–reference 選項和–mirror選項是不能同時使用的。
注意:/home/mirror下面 不用每次都取執行 repo sync。一個月執行一下都可以。
注意:使用了–reference /home/mirror 下載程式碼會加快,然後.repo 的大小會很小,幾套程式碼會公用這個mirro的。

repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest \
-b android-4.0.1_r1 \
--repo-url=https://aosp.tuna.tsinghua.edu.cn/tools/repo \
--repo-branch=stable --reference  /home/mirror

repo sync

sync Update working tree to the latest revision
執行完之前的repo init命令之後就可以下載程式碼了。下載程式碼的命令是repo sync。也就是同步伺服器程式碼
到本地目錄下面。這也是sync的英文單詞的意思,同步。

repo sync的選項

$ repo sync --help

Usage: repo sync [<project>...]

Options:
  -h, --help            show this help message and exit
  -f, --force-broken    continue sync even if a project fails to sync
  --force-sync          overwrite an existing git directory if it needs to
                        point to a different object directory. WARNING: this
                        may cause loss of data
  -l, --local-only      only update working tree, don't fetch
  -n, --network-only    fetch only, don't update working tree
  -d, --detach          detach projects back to manifest revision
  -c, --current-branch  fetch only current branch from server
  -q, --quiet           be more quiet
  -j JOBS, --jobs=JOBS  projects to fetch simultaneously (default 4)
  -m NAME.xml, --manifest-name=NAME.xml
                        temporary manifest to use for this sync
  --no-clone-bundle     disable use of /clone.bundle on HTTP/HTTPS
  -u MANIFEST_SERVER_USERNAME, --manifest-server-username=MANIFEST_SERVER_USERNAME
                        username to authenticate with the manifest server
  -p MANIFEST_SERVER_PASSWORD, --manifest-server-password=MANIFEST_SERVER_PASSWORD
                        password to authenticate with the manifest server
  --fetch-submodules    fetch submodules from server
  --no-tags             don't fetch tags
  --optimized-fetch     only fetch projects fixed to sha1 if revision does not
                        exist locally
  --prune               delete refs that no longer exist on the remote
  -s, --smart-sync      smart sync using manifest from the latest known good
                        build
  -t SMART_TAG, --smart-tag=SMART_TAG
                        smart sync using manifest from a known tag

  repo Version options:
    --no-repo-verify    do not verify repo source code

這個看著選項也是一大堆,其實基本上都是固定那幾個選項的,經常用的就那幾個,其他的可以不用關心。

repo sync -cdj 4 --no-tags  #一般是這樣用的。

-c選項,–current-branch:只sync,只下載當前分支,不加上會下載很多沒用的分支的。。預設情況下,sync會同步所有的遠端分支,當遠端分支比較多的時候,下載的程式碼量就大。使用該引數,可以縮減下載時間,節省本地磁碟空間。

-j選項,指定同時開啟幾個執行緒來下載程式碼,這個不要多,就使用4就行。使用的多不見得快。

-d選項,detach是分離,剝離的意思,一般在git中用git status檢視有時候能看到。
HEAD detached at 6beb886d10ec,這個是啥意思呢?這個指頭指標剝離自一個revision,
也就是當前分支剝離自一個revision,也就是一個沒用名字的分支,也就是當前分支是一個匿名分支。
這個選項在repo sync時候能有什麼作用呢?我們接下來詳細介紹。

首先我們新建一個目錄進行repo init。然後repo sync device/qcom/msm8996,下載一個msm8996的倉庫做個測試:

$ git br -vvv    
* (no branch) 5e51f0b Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch

通過 git branch -vvv我們看到初始情況是在一個匿名分支上的。
這個時候往前回退幾個提交:

$ git br -vv   
* (no branch) 48b4a9a Merge 6f578b199a8bbd8b9c053526a459db0600bf640c on remote branch

然後執行 repo sync .,發現有回到之前的那個提交了

* (HEAD detached at 5e51f0b) 5e51f0b Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch

再做個實驗,我們用之前的一個提交6b66e01 建立一個新分支test然後切換到test分支上。

$ git co 6b66e01 -b test     
Previous HEAD position was 5e51f0b... Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
Switched to a new branch 'test'

$ git st                          
On branch test
nothing to commit, working tree clean

$ git br -vvv          
* test 6b66e01 msm8996: Added Sustained and VR perf mode powerhints in xml
$ 

然後執行repo sync . 我們發現分支有切換到之前的那個5e51f0b點了,分支也離開了test分支了。

$ repo sync .      
Fetching project platform/vendor/qcom/thulium

device/qcom/msm8996/: leaving test; does not track upstream

$ git br -vvv           
* (HEAD detached at 5e51f0b) 5e51f0b Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
  test                       6b66e01 msm8996: Added Sustained and VR perf mode powerhints in xml

再做個實驗,如果test分支有改動的狀態,也就是git status看到有紅色的修改的檔案,這個使用執行repo sync . 有可能是會報錯的:

$ repo sync .     
Fetching project platform/vendor/qcom/thulium
error: Your local changes to the following files would be overwritten by checkout:
    AndroidBoard.mk
Please commit your changes or stash them before you switch branches.
Aborting

device/qcom/msm8996/: leaving test; does not track upstream
error: device/qcom/msm8996/: platform/vendor/qcom/thulium checkout 5e51f0bbfc618dcc9518be616a2843f9c69dbfdf 

$ git st    
On branch test
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   AndroidBoard.mk

no changes added to commit (use "git add" and/or "git commit -a")
$

====================================================================================================

接下來我們繼續做實驗。我們使用repo start dev . 新建個本地分支,並且追蹤遠端分支

$ repo start dev .  

$ git br -vvv    
* dev  5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
  test fe80d2f test

這個時候執行repo sync . 不會有什麼更新的,因為dev就是在最新的revision點上的。

$ git br -vvv        
* dev  07e64c0 [shgit/qcom_o_dev_20171101: ahead 1] add a commit for test      這個本地dev分支,追蹤對應的遠端分支
  test fe80d2f test                                                              這個是本地test分支

====================================================================================================

這個時候我們在dev分支上提交個commit,可以看到ahead 1 表示領先了一個提交,這個時候我們repo sync .

$ git br -vvv  
* dev  07e64c0 [shgit/qcom_o_dev_20171101: ahead 1] add a commit for test 這個本地dev分支,追蹤對應的遠端分支
  test fe80d2f test                                                          這個是本地test分支

分支領先的情況,通過repo sync 後我們發現dev分支並沒有什麼變化。

====================================================================================================

我們再看一種情況,我們分支落後的情況又如何呢?

$ git br -vvv   
* dev  48b4a9a [shgit/qcom_o_dev_20171101: behind 80] Merge 6f578b199a8bbd8b9c053526a459db0600bf640c on remote branch  這個本地dev分支,追蹤對應的遠端分支
  test fe80d2f test             這個是本地test分支
$

我們分支落後的情況,這個時候我們repo sync .

$ repo sync .                        
remote: Counting objects: 8198, done        
remote: Finding sources: 100% (6/6)           
remote: Total 6 (delta 0), reused 0 (delta 0)        
From ssh://gerrit-sh.blackshark.com:29418/git/android/platform/manifest
   6e376d832..0e5584474  bs_master  -> origin/bs_master

Fetching project platform/vendor/qcom/thulium

device/qcom/msm8996/: manifest switched refs/heads/qcom_o_dev_20171101...qcom_o_dev_20171101
project device/qcom/msm8996/
Updating 48b4a9a..5e51f0b
Fast-forward
 BoardConfig.mk                                     |   6 +-
 WCNSS_qcom_cfg.ini                                 |   6 +-
 android_filesystem_config.h                        |   6 +-
 fstab.qcom                                         |   4 +-
 init.target.rc                                     |  35 ++-
 media_codecs.xml                                   |  23 +-
 msm8996.mk                                         |  41 ++--
 .../frameworks/base/core/res/res/values/config.xml |  59 -----
 recovery_vendor_variant.fstab                      |   5 +-
 system.prop                                        |  10 +-
 vintf.xml                                          | 239 ++++++++++++++++++++-
 11 files changed, 295 insertions(+), 139 deletions(-)

$ git br -vvv   
* dev  5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch  這個本地dev分支,追蹤對應的遠端分支
  test fe80d2f test   這個是本地test分支
$ 

分支落後的情況,通過repo sync 後我們發現dev分支發生了同步更新了。

====================================================================================================

接下來我們在新建個本地分支並設定為跟蹤分支

$ git br -vvv 
  dev                       5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
* sdm660_nougat_20170213    385fc1e [shgit/sdm660_nougat_20170213] Merge dd9dcc7ddabcec42daee9473d8409aae82d6c692 on remote branch
  test                      fe80d2f test
  qcom_msm8953_apk_20170703 880dcbf [shgit/qcom_msm8953_apk_20170703] Merge e3ce047a16037379bfd859e14666a6c7eb2eae05 on remote branch

我們接著執行repo sync

$ repo sync . 
Fetching project platform/vendor/qcom/thulium
Fetching projects: 100% (1/1), done.  

device/qcom/msm8996/: manifest switched refs/heads/sdm660_nougat_20170213...qcom_o_dev_20171101
device/qcom/msm8996/: discarding 10 commits removed from upstream
$ git br -vvv       
  dev                       5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
* sdm660_nougat_20170213    5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
  test                      fe80d2f test
  qcom_msm8953_apk_20170703 880dcbf [shgit/qcom_msm8953_apk_20170703] Merge e3ce047a16037379bfd859e14666a6c7eb2eae05 on remote branch
$

我們發現本地分支發生變化了,原來跟蹤的遠端分支變掉了。變成qcom_o_dev_20171101了。這個分支是manifest.xml 對應的分支名稱。

====================================================================================================

$ git br -vvv   
  dev                       5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
  sdm660_nougat_20170213    5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
  test                      fe80d2f test
* qcom_msm8953_apk_20170703 880dcbf [shgit/qcom_msm8953_apk_20170703] Merge e3ce047a16037379bfd859e14666a6c7eb2eae05 on remote branch
$ repo sync .     
Fetching project platform/vendor/qcom/thulium

device/qcom/msm8996/: manifest switched refs/heads/qcom_msm8953_apk_20170703...qcom_o_dev_20171101
device/qcom/msm8996/: discarding 37 commits removed from upstream
$ git br -vvv       
  dev                       5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
  sdm660_nougat_20170213    5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
  test                      fe80d2f test
* qcom_msm8953_apk_20170703 5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
$ 

同樣的我們有試了另外一個本地分支,發現 原來跟蹤的遠端分支變掉了。變成qcom_o_dev_20171101了。這個分支是manifest.xml 對應的分支名稱。

====================================================================================================

這時候,我們把這個2個本地分支的追蹤跟蹤改回去。我們發現有領先,也有落後的,然後執行repo sync

$ git br -vvv       
  dev                       5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
* sdm660_nougat_20170213    5e51f0b [shgit/sdm660_nougat_20170213: ahead 123, behind 10] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
  test                      fe80d2f test
  qcom_msm8953_apk_20170703 5e51f0b [shgit/qcom_msm8953_apk_20170703: ahead 123, behind 37] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
$

$ repo sync .     
Fetching project platform/vendor/qcom/thulium

$ git br -vvv   
  dev                       5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
* sdm660_nougat_20170213    5e51f0b [shgit/sdm660_nougat_20170213: ahead 123, behind 10] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
  test                      fe80d2f test
  qcom_msm8953_apk_20170703 5e51f0b [shgit/qcom_msm8953_apk_20170703: ahead 123, behind 37] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
$ 

我們發現沒有什麼變化的,因為此時這2個本地分支指向的都是5e51f0b 這個提交,都是qcom_o_dev_20171101這個分支最新的提交了。

====================================================================================================

我們繼續,我們把這個2個本地分支的追蹤跟蹤改回去,我們在sdm660_o_bringup_20170719 分支上領先一個提交,然後repo sync

$ git br -vvv       
  dev                       5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
* sdm660_o_bringup_20170719 c7b1b47 [shgit/sdm660_o_bringup_20170719: ahead 1] test for shgit/sdm660_o_bringup_20170719
  qcom_msm8953_apk_20170703 880dcbf [shgit/qcom_msm8953_apk_20170703] Merge e3ce047a16037379bfd859e14666a6c7eb2eae05 on remote branch

$ repo sync .    
Fetching project platform/vendor/qcom/thulium
Fetching projects: 100% (1/1), done.  

device/qcom/msm8996/: manifest switched refs/heads/sdm660_o_bringup_20170719...qcom_o_dev_20171101
device/qcom/msm8996/: discarding 1 commits removed from upstream
project device/qcom/msm8996/
First, rewinding head to replay your work on top of it...

$ git br -vvvv    
  dev                       5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
* sdm660_o_bringup_20170719 5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
  qcom_msm8953_apk_20170703 880dcbf [shgit/qcom_msm8953_apk_20170703] Merge e3ce047a16037379bfd859e14666a6c7eb2eae05 on remote branch
$

發現 原來領先的那個提交也沒了 原來跟蹤的遠端分支變掉了。變成qcom_o_dev_20171101了。這個分支是manifest.xml 對應的分支名稱。

====================================================================================================

在這個基礎上我們提交個新的,讓其領先一個,也就是領先qcom_o_dev_20171101這個分支一個提交

$ git br -vvvv   
  dev                       5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
* sdm660_o_bringup_20170719 5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
  qcom_msm8953_apk_20170703 880dcbf [shgit/qcom_msm8953_apk_20170703] Merge e3ce047a16037379bfd859e14666a6c7eb2eae05 on remote branch


$ git br -vvv    
  dev                       5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
* sdm660_o_bringup_20170719 21badc9 [shgit/qcom_o_dev_20171101: ahead 1] test for
  qcom_msm8953_apk_20170703 880dcbf [shgit/qcom_msm8953_apk_20170703] Merge e3ce047a16037379bfd859e14666a6c7eb2eae05 on remote branch

$ repo sync .    
Fetching project platform/vendor/qcom/thulium
Fetching projects: 100% (1/1), done.  

$ git br -vvvv     
  dev                       5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
* sdm660_o_bringup_20170719 21badc9 [shgit/qcom_o_dev_20171101: ahead 1] test for
  qcom_msm8953_apk_20170703 880dcbf [shgit/qcom_msm8953_apk_20170703] Merge e3ce047a16037379bfd859e14666a6c7eb2eae05 on remote branch

我們發現領先qcom_o_dev_20171101分支的話,執行repo sync是沒有什麼變化的。
基本上我們可以看到,如果是領先qcom_o_dev_20171101分支的話之後更新是不會有什麼改變的

====================================================================================================

切換到qcom_msm8953_apk_20170703 分支,讓其落後幾個提交,然後執行repo sync

$ git br -vvv   
  dev                       5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
  sdm660_o_bringup_20170719 21badc9 [shgit/qcom_o_dev_20171101: ahead 1] test for
* qcom_msm8953_apk_20170703 1c57473 [shgit/qcom_msm8953_apk_20170703: behind 7] Merge 47f59af3394f5966ddeb76c769d4a116d36885dc on remote branch

$ repo sync .    
Fetching project platform/vendor/qcom/thulium

device/qcom/msm8996/: manifest switched refs/heads/qcom_msm8953_apk_20170703...qcom_o_dev_20171101
device/qcom/msm8996/: discarding 30 commits removed from upstream

$ git br -vvvv     
  dev                       5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
  sdm660_o_bringup_20170719 21badc9 [shgit/qcom_o_dev_20171101: ahead 1] test for
* qcom_msm8953_apk_20170703 5e51f0b [shgit/qcom_o_dev_20171101] Merge 6a461864882ef2fec0caab813044b2106bfa199d on remote branch
$

我們發現落後分支的話,執行repo sync是會更改追蹤的分支的。

====================================================================================================

以上測試都是沒加-d選項的

====================================================================================================

4.最後來來試試加上-d後的效果

$ repo sync . --no-tags -d
Fetching project kernel/msm-4.9
remote: Counting objects: 31, done        
remote: Finding sources: 100% (16/16)           
remote: Total 16 (delta 0), reused 15 (delta 0)        
From ssh://gerrit.blackshark.com:29418/git/android/kernel/msm-4.9
   6beb886d10ec..b03e189a7d05  qcom_o_dev_20171101 -> shgit/qcom_o_dev_20171101

repo sync中我們看到有一行6beb886d10ec..b03e189a7d05 這個,這個表示前面的提交 更新到了後面的提交了。

也就是之前的提交revision是6beb886d10ec ,sync後 更新到的revision是 b03e189a7d05 。

6beb886d10ec我們之前看到是 qcom_o_dev_20171101 分支的最後一個提交。

從中也可以看到加了-d, 它更新的是qcom_o_dev_20171101分支,同時給你切換到一個匿名分支上,這就是detach的意思。

5.最後再來看看狀態

$ git st
HEAD detached at b03e189a7d05
nothing to commit, working tree clean

執行完repo sync我們執行git status看到 當前是一個匿名分支了。這個就是manifest.xml中對應的revision值了。
這個就是-d –detach選項剝離選項的作用了。

注意這裡需要是一個本地跟蹤遠端的分支,不是跟蹤分支repo sync後會是在一個匿名分支上,剝離的分支。

–no-tags選項,這個是不下載refs/tags/下面的標籤。這個tag一般不需要下載,tag沒什麼用的。馬哥就從來就用到過。建議加上的。尤其是高通的程式碼有很多tag的,完全沒用的東西,下載也很浪費時間。

下面再介紹幾個選項的

-f 選項,同 –force-broken:當有git庫sync失敗了,不中斷整個同步操作,繼續同步其他的git庫。

–no-clone-bundle:
在向伺服器發起請求時,為了做到儘快的響應速度,會用到內容分發網路(CDN, Content Delivery Network)。同步操作也會通過CDN與就近的伺服器建立連線, 使用HTTP/HTTPS的$URL/clone.bundle來初始化本地的git庫,clone.bundle實際上是遠端git庫的映象,通過HTTP直接下載,這會更好的利用網路頻寬,加快下載速度。 當伺服器不能正常響應下載$URL/clone.bundle,但git又能正常工作時,可以通過該引數,配置不下載$URL/clone.bundle,而是直接通過git下載遠端git庫。

–force-sync 強制sync的意思,也就是當git倉庫地址遍歷會報個錯誤,錯誤中會提示你使用–force-sync,這個時候你就加上這個選項重新同步程式碼。
overwrite an existing git directory if it needs to point to a different object directory. WARNING: this may cause loss of data
類似的會報出如下錯誤:

error: Cannot fetch platform/vendor/qcom/proprietary (GitError: --force-sync not enabled; cannot overwrite a local work tree. If you're comfortable with the possibility of losing the work tree's git metadata, use `repo sync --force-sync vendor/qcom/proprietary` to proceed.)
Exception in thread Thread-85:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 763, in run
    self.__target(*self.__args, **self.__kwargs)
  File ".repo/repo/subcmds/sync.py", line 270, in _FetchProjectList
    success = self._FetchHelper(opt, project, *args, **kwargs)
  File ".repo/repo/subcmds/sync.py", line 314, in _FetchHelper
    prune=opt.prune)
  File ".repo/repo/project.py", line 1148, in Sync_NetworkHalf
    self._InitGitDir(force_sync=force_sync)
  File ".repo/repo/project.py", line 2177, in _InitGitDir
    raise e
GitError: --force-sync not enabled; cannot overwrite a local work tree. If you're comfortable with the possibility of losing the work tree's git metadata, use `repo sync --force-sync vendor/qcom/proprietary` to proceed.

-l, –local-only 只更新本地工作空間,不去遠端伺服器拉取程式碼。什麼意思呢?repo sync在同步程式碼的時候是先把伺服器上的程式碼更新(拉取,fetch)到.repo目錄下面的,然後進行checkout操作。這裡的–local-only就是隻進行checkout操作,也就是把.repo 目錄下面的程式碼更新到工作空間目錄中。
only update working tree, don’t fetch

-n, –network-only 只更新,值拉取伺服器程式碼到.repo 目錄下。這個就是和上面的–local-only相對應的。 fetch only, don’t update working tree。

上面這個2個選項什麼時候會用到呢?

好比你要給某人打包一套android的程式碼,帶上全部git歷史記錄的。
你首先想到的就是把整work目錄打包發個他,這個操作是可行的。不過就是壓縮包很大。
另外一種就是值打包.repo 目錄。在repo sync的時候加上–network-only ,更新完後打包.repo 目錄。
另一方解壓完後,repo sync時候加上 –local-only 。這樣壓縮包會小,打包時間也快。

-m NAME.xml, –manifest-name=NAME.xml 這個選項和repo init中的-m類似,這裡是更新程式碼時候臨時使用-m指定的這個xml檔案取更新程式碼。 temporary manifest to use for this sync。

–prune 刪除遠端已經不存在了,或者遠端分支沒許可權看到了 的 本地分支。 delete refs