Repo使用筆記


repo其實就是管理眾多git與專案的工具,他本身是用python所構成



下載Repo並設定系統路徑
$ mkdir -p ~/bin/
$ curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
$ chmod a+x ~/bin/repo
$ export PATH=${HOME}/bin:${PATH}

repo的網址我已經看到很多不同的URL,我會建議使用Android文件上提供的網址

設定Repo要下載的專案庫

例如AOSP的repo是https://android.googlesource.com/platform/manifest
$ repo init -u https://android.googlesource.com/platform/manifest

如果是要ssh登入的就是用下面類似格式
$ repo init -u ssh://帳號@可供下載的Repo網址

設定來源的同時指定要切換的branch使用-b
$ repo init -u https://android.googlesource.com/platform/manifest -b android-4.0.1_r1

repo init之後實際上會在當前目錄建立隱藏目錄.repo,並將manifest的設定從server上帶下來,
裏面會有個manifest.xml,用ls -l察看該檔案可以看到他連結到manifests目錄內的某個.xml
這個manifests目錄就是可以供選擇的專案,如果想要選擇的不是預設的專案,可以透過repo init -m 來指定要變更的xml名稱。
$ repo init -m proj20151031.xml
跟你直接改manifest.xml連結的對象也是同樣意思

看repo init的指令說明
$ repo init -h

開始下載或更新
$ repo sync -j8
-j後面的數字是連線數目

如果下載有問題可以使用proxy和更改系統設定增加穩定性,設定請參考android文件說明

列出目前Repo的git projects
$ repo list

顯示所有git的修改狀態(很慢)
$ repo forall -cp "git status"

顯示working tree的狀態
$ repo status

顯示變更
$ repo diff 

顯示repo的help menu
$ repo help

結果會是下面這樣
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

看目前改的commit
$ repo --no-pager forall -cp "git --no-pager log --oneline m/l-process-gx...HEAD"

這裡會發現repo後面接了--no-pager,而git後也用了--no-pager,這是因為repo本身執行時印出超過一頁的資訊後會暫停,等待使用者按下任意鍵繼續,而git log時也是同樣的狀況,所以兩個位置都需要加上--no-pager來讓整個指令會完整跑完而不會暫停。

-c是對每個git做處理後面所帶的指令處理
-p是印出目前正在處理的git專案目錄

對每個git取出指定tag
$ repo forall -cp "git checkout v2.3"

對每個git作產生branch的動作
$ repo --no-pager forall -cp "git checkout -b {new_branch_name}"
$ repo --no-pager forall -cp "git branch {new_branch_name}"

跟隨Master版本

$ repo --no-pager forall -cp 'git branch -m master del'
$ repo --no-pager forall -cp 'git checkout -b master -t remotes/m/master'
$ repo --no-pager forall -cp 'git branch -D del'

跟隨某個tag,第二個指令要改一下
$ repo --no-pager forall -cp 'git branch -m master del'
$ repo --no-pager forall -cp 'git checkout -b master {tag_name}'
$ repo --no-pager forall -cp 'git branch -D del'


列出某tag後的commit log

$ repo --no-pager forall -cp 'git --no-pager log --oneline v2.4.4...master'

拷貝某個tag到目前(HEAD)的修改檔案

在git時我們會用下面這個指令下來拷貝檔案
$ git show --name-only v2.3 | xargs -i cp --parents {} ~/bak/

因為repo是多git server管理工具所以,指令上有些變化,不過因為無法在一行內寫出所需的處理,所以我分出一個拷貝用的script叫作onecp.sh

拷貝repo內容到bak目錄用指令變成, 我這裡是以master作為範例
$ repo --no-pager forall -c 'git --no-pager diff --name-only v2.3 master | xargs -i {your-onecp.sh-full-patch>} {} ~/bak/$REPO_PATH/'
$REPO_PATH是repo指令操作時會自動帶入當前repo的目錄
在使用這個指令前,先確保有作過git status或是重新跟隨版本,會讓整個拷貝流程快很多

如果你已經將onecp.sh放到path中,讓它可在任何資料夾執行的話
$ repo --no-pager forall -c 'git --no-pager diff --name-only v2.3.4 master | xargs -i onecp.sh {} ~/bak/$REPO_PATH/'
因為是用diff,所以要小心一個盲點是其中包含revert patch時要小心處理,因為可能少包了一些內容,

例如這樣
v2.4++ revert revert foo檔案  (外部server最新版)
v2.4+   revert foo檔案   (內部server最新版)
v2.4     patch foo檔案    (某個Tag)

然後因為tag只有v2.4,但是我在拉最新patch只會用v2.4..HEAD, 對於這個git diff來說,foo檔案是未修改的,所以在bak資料夾不會出現
所以當我用指令產生出來bak資料夾內容,直接蓋上去內部server最新版,就會發生foo檔案依然是v2.4+的修改,也就是revert版的patch
所以建議每次都對比較版本去patch, 而不要疊加在,除非你很確定裡面沒有revert patch(不見得看patch list可以看得出來)

onecp.sh (如果指定檔案不存在則忽略)
if [ "$#" -lt 1 ] || [ -z "$1" ]
then
    echo "should assian a valid file, $1";
    exit -1;
fi
if ! [ -e "$1" ]
then
    echo "file not found! skipped copy $PWD/$1";
    exit 0;
fi
if ! [ -f "$1" ]
then
    echo "$1 not a file";
    exit -1;
fi
if [ "$#" -lt 2 ] || [ -z "$2" ]
then
    echo 'should assian a valid dest';
    exit -2;
fi
#echo "$PWD/$1"
test -d "$2" || mkdir -p "$2" && cp --parents "$1" "$2"


如果上面的script 使用有問題,可以先測試這兩個指令是否正常
$ repo --no-pager forall -cp 'git --no-pager diff --name-only v2.3 HEAD | xargs -i echo {}'
$ repo --no-pager forall -cp 'git --no-pager diff --name-only v2.3 HEAD | xargs -i echo $REPO_PATH'




參考資料:
https://source.android.com/source/downloading.html
https://source.android.com/source/using-repo.html

留言