本文摘錄自本人的《Git聊天入門》
arc 為何物
- arc 全稱是 arcanist,百度給出的中文翻譯是:巧匠。
- arc 是Facebook的Phabricator系統中用戶端的命令行工具,配合pha提交變更評審的。
- arc 的安裝還有點折騰,要先在本機安裝PHP,和一個php的工具集:libphutil
- windows的安裝后,目錄下包括下面3個主要部件:
Phabricator/--arc/--arcanist | |-libphutil |-xampplite-win32-1.7.3
+ arcantist是arc的主程序:https://github.com/phacility/arcanist.git + libphutil是php的工具集:https://github.com/phacility/libphutil.git + xampplite是apache+php+mysql+perl的一個打包,160+M,要知道phabricator整個才180+M。
- arc 包含很多子命令,
-
arc help
:列出來子命令看看 -
arc diff
:調用svn diff
或git diff
生成差異并發送給phabricator生成評審單 -
arc list
:列出當前peding的revision —— revision要說明一下:pha生產的每個評審單都對應一個revision,可以理解為svn/git的一次提交,但又不在用戶的svn/git上體現,可以理解為pha上也駐留這一個svn/git,來存儲評審單信息,每單對應一個revision。 -
arc patch
:將pha上的revision變更patch到本地工作拷貝上 -
arc amend
:更新git commit的message,即:可以把pha上某個revision的message應用到本地git的某個commit上 -
arc commit
:svn專用,pha上評審完畢后,將本地的變更做svn commit
-
arc land
:git專用,pha上評審完畢后,將本地分支做git push
,所以需要有 origin -
arc lint
:靜態代碼分析,不要以為arc只是生成評審單的,它還內嵌了一堆的lint工具,python的、java的、js的……五花八門,在Phabricator\arc\arcanist\src\lint\linter\__tests__
這個目錄下列出了這些lint工具 -
arc unit
:執行單元測試,這個就需要用戶自己來指定單元測試工具了 -
arc close-revision
:使用arc關閉某個revision,而不必上pha上鼠標點點點啦 - …… 還有n多,不一一列舉了,頭暈
-
- arc 的 configuration
- 和git類似,git有
git config --[global/system/local] xxx ...
,arc也有arc set-config --[user/local] xxx ...
- 和git類似,git查看config有
git config -l
,arc也有arc get-config
- 和git類似,git有
arc的安裝和配置
Windows下的安裝
略
Ubuntu下的安裝
- 安裝
sudo apt-get install php5 php5-curl
-
cd somewhere
//arc的安裝目錄 git clone https://github.com/phacility/libphutil.git
git clone https://github.com/phacility/arcanist.git
sudo ln -s arcanist/bin/arc /usr/local/bin/arc
-
vi ~/.bashrc
source $somewhere/arcanist/resources/shell/bash-completion
- 配置
-
arc set-config $pha-server
//eg:arc set-config http://pha.etz.com.cn
-
arc install-certificate
- 到 $pha-server 上查找幫助,找到tocken,填到這里
- 注意proxy的屏蔽
-
arc diff 初步
- SVN中,
arc diff
會把未提交的本地工作拷貝中的變更生成評審單,執行arc diff
之前不需要也不能執行svn commit
,最終評審完,用arc commit
來代替svn commit
- git中則完全不一樣,
arc diff <startCommit>
之前需要首先git add
&git commit
,如果本地工作拷貝中有變更,arc diff會自動替你add和commit,因為arc diff
是把git中兩個commit之間(即:一個range)的變更提交到pha上生成評審單,所以問題來了:兩個commit節點是如何指定的?- 兩個commit節點是:startCommit 和 HEAD
- startCommit如果缺失,則默認使用
git merge-base origin/master HEAD
- 這又是個啥東東?
git help merge-base
,意思是找到 origin/master 和 HEAD 之間的最近祖先節點。 -
git help merge-base
中有幾個例子,其中一個是:
o---o---o---B / ---o---1---o---o---o---A
* `git merge-base A B `將返回節點1,好好體會一下,呵呵。
- 所以為了不出亂子,最好自己指定 startCommit
- 這又是個啥東東?
-
arc diff
需要填寫一些信息,所以執行過程中會跳入到一個編輯器中,windows版的arc會打開一個簡陋的窗口,ubuntu版的arc就直接打開默認的編輯器(如vi)了。需要填寫的信息有:- Test Plan - 必填,詳細說明你的測試計劃;
- Reviewers - 必填,審查人的賬戶,多個使用","隔開;
- 在ubuntu下,用vi編輯此信息時,不會自動不全人名,則需要到phabricator網站上的搜索窗口,找到需要的人,把TA的賬號寫在此處
- Subscribers - 非必填訂閱人,多個使用","隔開。
實戰一下:
- 創建一個temp的git repo
10036143@A20939270 MINGW32 /f/temp (master)
$ git log
* 75c616b | 2016-06-08 15:55:19 +0800 | wkevin hah
* 7584e84 | 2016-06-08 15:55:01 +0800 | wkevin create
-
arc diff
- 會提示錯誤,沒有指定 origin/master,因為默認startComiit是
git merge-base origin/master HEAD
嘛
- 會提示錯誤,沒有指定 origin/master,因為默認startComiit是
-
arc diff 7584
- 可以創建評審單的,因為是拿 HEAD(即75c6)與7584比較
-
git show HEAD
可以查看 HEAD 指向哪個節點
-
arc diff 7584 --preview
- 可以在pha上創建評審單,但跳過指定評委等步驟,單子已經在pha上有了,可以先看看,后續在pha上慢慢指定評委等
- 這是專門給處女座準備的啊
- 有一點需要說明:
-
arc diff
會根據工作拷貝的相關信息(比如 path, branch name, local commit hashes, and local tree hashes)來自動創建和關聯一個pha上的revision,這讓一些掌控欲比較強的人可能有些惱火,可以手工指定-
arc diff --create <startCommit>
:在pha上創建一個新的revision -
arc diff --update Dxxxx <startCommit>
:在pha上一個已有的revision(編號Dxxxx)上做增量
-
-
arc diff 為什么把我已有的commit log修改了
在上面的步驟中有一個奇怪的地方:執行完arc diff xxxx
后,原有的HEAD節點被arc重新創建的一個節點所替代
- 執行
arc diff 7584
后,75c6被替代為了26c0
$ git l
* 26c0efc | 2016-06-08 15:55:19 +0800 | wkevin hah
* 7584e84 | 2016-06-08 15:55:01 +0800 | wkevin create
- 再次執行
arc diff 7584
后,26c0被替代為了e6db
$ git l
* e6db93c | 2016-06-08 15:55:19 +0800 | wkevin hah
* 7584e84 | 2016-06-08 15:55:01 +0800 | wkevin create
- 再次執行
arc diff 7584
后,e6db被替代為了7c29
$ git l
* 7c29204 | 2016-06-08 15:55:19 +0800 | wkevin hah
* 7584e84 | 2016-06-08 15:55:01 +0800 | wkevin create
- 但其實75c6、26c0、e6db都還是存在的,
git show
可以看到
$ git show 75c6
commit 75c616b3a6de15e7004c231486a91e338ae023a6
Author: wkevin <wkevin27@gmail.com>
Date: Wed Jun 8 15:55:19 2016 +0800
hah
事情變得很蹊蹺,arc為什么要新建一個commit呢?
下面再來驗證一下:如果本地有modified(待add)或stagging(待commit)文件的話,arc diff
是不是也會新建一個commit呢?
- 當前狀態
$ git l
* 1cce5be | 2016-06-08 16:05:27 +0800 | wkevin neww
* 7c29204 | 2016-06-08 15:55:19 +0800 | wkevin hah
* 7584e84 | 2016-06-08 15:55:01 +0800 | wkevin create
- 做一些有本地修改,但不
git commit -a
-
arc diff HEAD^
,會首先把未提交的變更進行提交,并且更新(amend)當前commit的message,然后向已有的revision進行update
$ arc diff HEAD^
You have uncommitted changes in this working copy.
Working copy: F:\temp\
Unstaged changes in working copy:
README.md
Do you want to amend this change to the current commit? [y/N] y
Linting...
No lint engine configured for this project.
Running unit tests...
No unit test engine is configured for this project.
SKIP STAGING Unable to determine repository for this change.
Updated an existing Differential revision:
Revision URI: http://pha.zte.com.cn/D30449
Included changes:
M README.md
- 1cce5be 又被 20ae4c5 替代了,而不是在 1cce5be 的基礎上新建一個commit
$ git l
* 20ae4c5 | 2016-06-08 16:05:27 +0800 | wkevin neww
* 7c29204 | 2016-06-08 15:55:19 +0800 | wkevin hah
* 7584e84 | 2016-06-08 15:55:01 +0800 | wkevin create
為了解開這個謎團,我們來跟蹤一下arc diff
的操作
arc diff --trace <startCommit>
摘錄一部分打印:
>>> [1] <http> http://pha.zte.com.cn/api/user.whoami
>>> [2] <exec> $ git diff --no-ext-diff --no-textconv --raw 'HEAD' --
>>> [3] <exec> $ git ls-files --others --exclude-standard
>>> [4] <exec> $ git diff-files --name-only
>>> [6] <exec> $ git rev-parse 'HEAD'
>>> [7] <exec> $ git merge-base 'f8c1' 'd6efce6e8804ecb027762e0151ed071bc7d63b6d'
>>> [8] <exec> $ git log --first-parent --format=medium 'f8c101daaf75121dd4f1f1380b4dc5c1ed85cea0'..'d6efce6e8804ecb027762e0151ed071bc7d63b6d'
首先到phabricator服務器上驗證tocken,并根據 startCommit 做出一些判斷
>>> [16] <event> diff.willBuildMessage <listeners = 0>
>>> [17] <conduit> differential.getcommitmessage() <bytes = 295>
>>> [18] <http> http://pha.zte.com.cn/api/differential.getcommitmessage
>>> [19] <exec> $ git symbolic-ref --quiet HEAD
>>> [20] <exec> $ which 'editor'
>>> [21] <exec> $ editor '/tmp/edit.cjol8q3bi1sg0kwk/new-commit'
然后到phabricator服務器上創建一個單,并根據pha的請求,打開editor,編輯評審單的信息
>>> [22] <exec> $ git commit --amend --allow-empty -F '/tmp/8qihi3x4l2ww4o8w/10039-Vbjrxm'
關鍵是這里了,無條件的更新了當前 HEAD 節點的 message。
其實 git commit --amend
的官方help中是這樣解釋的: Replace the tip of the current branch by creating a new commit.
這樣arc diff <startCommit>
步驟就明朗了:
- 提示用戶填寫評審單信息(Test Plans、Reviewers、Subscribers……),然后使用這些信息
git commit --amend
到當前分支的 HEAD 節點 - 新的節點(即:新的HEAD) 成為 endCommit
- 再拿 HEAD(即endCommit)與 startCommit 執行
git diff
,輸出的內容提交到 pha
arc 為什么要這么做?為什么要“玷污”我的現有節點?如果這個節點是其他分支的基礎節點怎么辦?…… —— 這個事情可以這么看:arc diff
只是新建了一個commit,用來存儲評審單的相關信息,并且把當前分支的HEAD指向了新建的commit,想好了這一點,事情其實很好辦,下一節我們來規避它。
如何避免arc diff玷污現有節點
創建專用于評審的分支
git branch review
git checkout review
-
arc diff <xxx>
或arc diff --preview <xxx>
//創建評審單或預審單(到pha網站上進行下一步的操作,可用于ubuntu下不能自動補全人名的環境) git checkout master
-
git branch -D review
//評審單一旦創建,review分支就沒有存在的必要性了
如何創建只包含部分文件的評審單
可能只希望評審方案文件(假設: design.md),但commit中包含相關的圖片、svg、等文件,不需要提交到pha,如下處理:
-
git branch review <oneOldCommit>
//從 design.md 創建或修改前的節點創建一個分支 git checkout review
-
git checkout master design.md
//將master分支上的 design.md check 到 review 分支 git commit -am "review for design.md"
-
arc diff HEAD^
或arc diff --preview HEAD^
git checkout master
git branch -D review