不少系統(例如Linux)已經默認提供了Git,在Git主頁也能夠找到安裝程序。對於Windows用戶,最好的選擇是MsysGit。請注意,若是你安裝了Apple Developer Tools (for Xcode 4),那麼其中已經自帶Git二進制包了。若是遇到了問題,help.github.com中能夠找到不少很是出色的指南。html
由於全部的Git提交都帶有做者和電子郵件地址,若是你尚未設置過這些內容,請執行如下命令進行配置:java
$ git config --global user.name "Alex Blewitt" $ git config --global user.email Alex.Blewitt@example.com
最好有一個Git代碼庫。Gerrit在初始化階段會自動掃描Git代碼庫,這樣作比在後期配置代碼庫容易一些,所以最好在初始化Gerrit前準備好Git代碼庫。git
若是尚未Git代碼庫,能夠建立一個:github
git init --bare /path/to/gits/example.git
能夠從http://code.google.com/p/gerrit/下載到Gerrit,那是一個WAR文件。Gerrit有很好的文檔(目前的最新文檔是2.2.1,但也可用於2.1.7)和安裝指南。sql
Gerrit在運行時須要用到數據庫(用於存儲代碼審查的信息)。目前支持的數據庫包括H二、PostgreSQL和MySQL。在沒有進行額外配置的狀況下,它默認使用H2。shell
請注意,Gerrit 2.2.x正把項目配置、權限和其餘元數據移到Git存儲中,這樣就能夠經過Git進行訪問和版本控制。在2.2.x中,這個轉變會慢慢擴展到其餘類型的元數據上,包含代碼評審內容。詳見2.2.0版本的發佈說明。數據庫
要初始化Gerrit,運行java -jar gerrit.war init -d /path/to/location會在指定路徑上安裝Gerrit運行時。xcode
若是是在交互終端中運行的,安裝程序會提幾個問題,例如:瀏覽器
其中大部分能夠保留默認值,可是有幾個須要重點關注。服務器
Gerrit啓動後,會打開一個瀏覽器,顯示Gerrit主頁。登陸的第一個用戶將自動成爲管理員;全部後續登陸的用戶都是無權限用戶。若是你選擇了development_become_any_account,在頁面頂端會有一個Become連接,經過它能夠進入註冊/登陸頁面。
爲了使用Gerrit,你須要一個帳號,生成一個SSH密鑰對。在命令行中運行 ssh-keygen -t rsa -b 2048能夠生成密鑰對,將其放到你的.ssh目錄中。若是你須要更多信息,能夠訪問這篇博文,這是我六年前寫的SSH密鑰相關文章。此外,GitHub 幫助頁面中也有更多相關信息。
默認文件名爲id_rsa(這是私鑰)和id_rsa.pub(這是公鑰)。你只能給別人公鑰,千萬別給別人私鑰。
有了密鑰,你就能夠在Gerrit中註冊新帳戶了。點擊頂部右端的「Become」連接,而後再點擊「New account」按鈕,輸入Git知道的名稱和電子郵件(即上面用git config配置的),這些內容要徹底匹配(包括大小寫)。保存變動,而後選擇一個惟一的用戶名(填入了名稱後點擊'select username',例如demo)。
在'add SSH public key'文本框中,添加.pub文件中的公鑰。若是你使用的是OS X,pbcopy < ~/.ssh/id_rsa.pub就可輕鬆搞定。記住要點擊「Add」保存公鑰。
點擊Continue後應該就能登陸到Gerrit的主窗口了。到目前爲止一切還不錯,如今能夠測試SSH的連通性了。
鍵入ssh -p 29418 demo@localhost會嘗試鏈接Gerrit服務器,會出現如下三者之一:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
這並無看上去那麼糟。它只是說你的~/.ssh/known_hosts文件中有舊的密鑰。最懶的一種修復方法是刪除這個文件(這是GitHub推薦的作法)。更好的方法是找到提示出錯的那一行,把它刪了:
Offending key in /Users/demo/.ssh/known_hosts:123
你能夠用任何文本編輯器來刪除known_hosts文件中的第123行。在標準UNIX配置下,能夠用如下命令自動刪除:
sed -i '' '123d' ~/.ssh/known_hosts
The authenticity of host '[localhost]:29418 ([::1]:29418)' can't be established. RSA key fingerprint is e8:e2:fe:19:6f:e2:db:c1:05:b5:bf:a6:ad:4b:04:33. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '[localhost]:29418' (RSA) to the list of known hosts. Permission denied (publickey).
若是看到這個消息,說明Gerrit沒有識別出你提交的任何密鑰。ssh默認會發送id_rsa,要確認它的確發送了該值,能夠查看.ssh/config,文件頭上有一行IdentityFile ~/.ssh/id_rsa。能夠運行ssh -v查看發送的內容:
debug1: Next authentication method: publickey debug1: Trying private key: /Users/demo/.ssh/id_dsa debug1: Offering public key: /Users/demo/.ssh/id_rsa
假設已經發送了正確的密鑰,那麼在settings - ssh public keys菜單項中檢查該密鑰是否關聯了Gerrit中的用戶。若是沒有的話點擊'Add Key'並和以前同樣粘貼公鑰。
若是Gerrit仍是說你未經身份驗證,檢查用戶名和配置頁面裏的用戶名是否一致。若是用戶名不一樣,試試ssh -p 29418 username@localhost。
最後,要驗證具體的密鑰,能夠運行ssh -i ~/.ssh/id_rsa顯式地選擇要使用的密鑰,而不是讓它自動選擇密鑰。若是這樣能夠工做,但不帶-i參數卻不行的話,那麼問題出在你的~/.ssh/config文件裏――你須要保證選擇了合適的IdentityFile。
**** Welcome to Gerrit Code Review **** Hi demo, you have successfully connected over SSH. Unfortunately, interactive shells are disabled. To clone a hosted Git repository, use: git clone ssh://demo@localhost:29418/REPOSITORY_NAME.git Connection to localhost closed.
若是看到這個提示,說明Gerrit已經正常工做了。
若是以前你沒法在Gerrit中註冊電子郵件地址,那麼能夠手工進行註冊。咱們能夠中止Gerrit,運行GSQL工具更新特定數據字段。
$ bin/gerrit.sh stop $ java -jar bin/gerrit.war gsql Welcome to Gerrit Code Review 2.1.6.1 (H2 1.2.134 (2010-04-23)) Type '\h' for help. Type '\r' to clear the buffer. gerrit> select * from ACCOUNT_EXTERNAL_IDS; ACCOUNT_ID | EMAIL_ADDRESS | PASSWORD | EXTERNAL_ID -----------+------------------------+----------+------------------------------------------ 1000000 | NULL | NULL | uuid:ac1b8a08-2dd1-4aa1-8449-8b2994dffaed 1000000 | NULL | NULL | username:demo (2 rows; 23 ms) gerrit> update ACCOUNT_EXTERNAL_IDS set EMAIL_ADDRESS='alex.blewitt@example.com' where ACCOUNT_ID=1000000; UPDATE 2; 5 ms gerrit> select * from ACCOUNT_EXTERNAL_IDS; ACCOUNT_ID | EMAIL_ADDRESS | PASSWORD | EXTERNAL_ID -----------+------------------------+----------+------------------------------------------ 1000000 | alex.blewitt@example.com | NULL | uuid:ac1b8a08-2dd1-4aa1-8449-8b2994dffaed 1000000 | alex.blewitt@example.com | NULL | username:demo (2 rows; 23 ms) gerrit> \q Bye $ bin/gerrit.sh start
開始前,咱們須要先在Gerrit中建立一個項目。若是Gerrit沒有在你的範例目錄中檢測到項目,在它運行時,咱們能夠建立一個項目。
$ ssh -p 29418 demo@localhost gerrit create-project --name example.git
上述命令會建立一個名爲example的項目,在以前指定的Git目錄裏初始化一個空的代碼庫。若是已經有一個代碼庫了,Gerrit不容許建立同名代碼庫——但你能夠先對它進行臨時重命名,隨後再把名字改回來。
隨後,能夠建立一個克隆:
$ git clone ssh://demo@localhost:29418/example.git
Cloning into example...
warning: You appear to have cloned an empty repository.
咱們能夠向代碼庫進行提交和推送,就和其餘Git系統同樣:
$ cd example $ echo hello > world $ git add world $ git commit -m "The World" [master (root-commit) 06bf85e] The World 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 world $ git push No refs in common and none specified; doing nothing. Perhaps you should specify a branch such as 'master'. $ git push origin master Counting objects: 3, done. Writing objects: 100% (3/3), 217 bytes, done. Total 3 (delta 0), reused 0 (delta 0) To ssh://me@localhost:29418/example.git ! [remote rejected] master -> master (prohibited by Gerrit) error: failed to push some refs to 'ssh://demo@localhost:29418/example.git'
這是什麼狀況?Gerrit不但願咱們直接覆寫Git代碼庫中的任何分支,而是將變動推送到另外一個refspec中,這讓Gerrit有機會在代碼審查中修改代碼。最簡單的方法是爲推送配置一個默認的refspec:
$ git config remote.origin.push refs/heads/*:refs/for/* $ git push origin Counting objects: 3, done. Writing objects: 100% (3/3), 217 bytes, done. Total 3 (delta 0), reused 0 (delta 0) To ssh://demo@localhost:29418/example.git * [new branch] master -> refs/for/master
咱們推送了一個分支,在Gerrit的change,1裏能夠發現,儘管實際的分支名稱是refs/changes/01/1/1,但看到的倒是refs/for/master。你會發現當前分支的哈希值和此處顯示的同樣(在個人例子裏是06bf85e)。若是咱們要再次推送,會建立一個新的分支refs/changes/02/2/1,而不是覆蓋refs/for/master。第一個數字是變動號的最後兩位,第二個數字是變動號,第三個數字是補丁集號。因此變動123的補丁集17就是refs/changes/23/123/17。
若是想要修正(amend)提交,Gerrit會建立一個新的代碼審查引用,這麼作不太好。若是兩次變動之間有審查評語,你將丟失這些內容。
咱們能夠修改commit-msg,添加一個(Gerrit專門的)Change-Id。同一變動的全部後續提交都會關聯到一個補丁集上。Gerrit提供了一個實現,只要複製出來就好了。
$ cd .git/hooks $ scp -P 29418 demo@localhost:hooks/commit-msg . $ cd ../..
如今,當咱們要提交修正時便會自動生成一個Change-Id。能夠用這個值爲變動集生成多個補丁。經過修正提交,並提供Gerrit變動的Change-Id,咱們能夠修改當前的提交。
$ git commit --amend -m "Hello World > > Change-Id: I06bf85ed12f370212ec22dbd76c115861b653cf2 > " [master 86a7a39] Hello World 1 files changed, 1 insertions(+), 0 deletions(-) $ git push Counting objects: 3, done. Writing objects: 100% (3/3), 260 bytes, done. Total 3 (delta 0), reused 0 (delta 0) remote: (W) 86a7a39: no files changed, message updated To ssh://me@localhost:29418/example.git * [new branch] master -> refs/for/master
如今再去看Gerrit中的change 1,你會發現出現了第二個與該變動相關聯的補丁集。遠端分支refs/changes/01/1/2包含了新的提交消息(儘管全部文件仍是同樣的)。
一般狀況下,你並不須要添加Change-Id,由於提交消息Hook會自動幫你添加的。
咱們要建立一個build.sh腳原本執行構建過程。Jenkins/Hudson會簽出並運行該腳本。通常而言,這是一個Maven的構建,也多是xcodebuild或make——爲了不針對某種語言,咱們就使用一個普通的腳本。
$ cat > build.sh #!/bin/sh echo Pretending to build ... echo done ^D $ chmod a+x build.sh $ git add build.sh $ git commit -m "Adding (dummy) build script" $ git push
問題是這些變動還在Gerrit的評審隊列裏,咱們要先批准這些變動。進入變動頁面,會看到這些文件,還有一個Review按鈕。在變動頁面有一個讓你作代碼審查的Review按鈕,但卻沒有提交按鈕……
這是由於變動在提交前默認要評審+2,每一個人只能+1,也就是說只有一我的作代碼審查是沒法提交代碼的。
咱們能夠修改Gerrit的規則,容許一我的投票+2,也能夠准許+1提交。
最簡單的方法是進入項目管理頁面的All Projects Access標籤頁(在Gerrit 2.2.1和2.1.7.2裏這個標籤從--All Projects--改爲了All-Projects)。點擊「Code review」規則旁邊的複選框,修改「Permitted Range」爲+2: Looks good to me, approved。Gerrit還須要一個+1校驗,隨後也會爲Jenkins/Hudson配置的。按照下面內容添加一條新規則:
Category Verified Group Name Non-Interactive Users Reference Name refs/* Permitted Range -1: Fails to +1: Verified
點擊「Add Access Right」來配置該權限。
咱們須要爲Jenkins/Hudson建立一個新用戶並添加到這個分組裏,所以進到登陸頁面註冊一個新帳戶buildbot。還須要一個新的SSH密鑰(名字是id_rsa.buildbot),和以前同樣粘貼在公鑰一欄裏。
從新用管理員ID登陸(你早些時候建立的那個帳戶),進入Admin - Groups標籤。在Non-Interactive Users里加入buildbot和demo用戶(後者是臨時的)。
配置好了校驗規則,咱們應該回到變動頁面,將這個變動標記爲經過。
但咱們仍是缺乏一個Submit按鈕,須要用它來合併分支。提交權限獨立於校驗和代碼審查權限以外,所以須要回到All Projects Access標籤頁,添加一個權限:
Category Submit Group Name Registered Users Reference Name refs/* Permitted Range +1: Submit
點擊「Add Access Right」來配置該權限。
如今,回到變動頁面,咱們就能看到Submit按鈕(若是變動已經經過了代碼審查)了,在評論/代碼審查頁面也有Publish and Submit按鈕。(請注意,若是代碼審查還沒到達提交所需的級別,在點擊Publish and Submit時會出現一個錯誤提示。)
最後,發佈並提交全部未完成的代碼審查(保證構建腳本已經就緒),執行git pull來確保你的代碼庫是最新的。它們應該出如今已合併標籤頁中。
管理員注意事項:通常來講,不會廣泛賦予'All Projects Access'權限,而是根據項目進行分配。這裏使用'All Projects'是爲了方便運行,也能夠根據項目進行配置。
如今要作的就是配置Jenkins(若是你喜歡也能夠用Hudson)。它們和Gerrit同樣,默認運行在8080端口上,你須要爲它們換個端口。修改Gerrit的端口要從新執行以前的配置過程,修改Jenkins/Hudson的端口只需命令行便可。
$ #java -jar hudson-2.0.1.war --httpPort=1234 $ java -jar jenkins.war -httpPort=1234 ...
Jenkins/Hudson能夠直接簽出Git項目,也能夠經過Gerrit簽出。可是簽出過程未必都能自定義SSH身份(不用.ssh/config中的默認身份集)。有時使用匿名Git協議來託管Git代碼庫會容易些,即無需身份驗證。能夠運行以下命令:
$ git daemon --export-all --base-path=/path/to/gits
咱們還須要安裝Git插件和Git/Gerrit觸發器。打開位於http://localhost:1234的Jenkins/Hudson,點擊左上方的Manage Jenkins/Hudson連接,再點擊Manage Plugins連接。切換到 Available標籤頁,安裝:
Install按鈕在右下方,Jenkins/Hudson稍後會重啓。Gerrit Trigger會安裝Git插件。請注意,有一個Gerrit Plugin,那個不是咱們要裝的。(若是你在使用Hudson,而且更新頁面裏沒有任何內容的話,進入'Advanced'點擊下方的'Check now'。)
如今,咱們能夠開始配置Jenkins/Hudson了。先按如下步驟新建一個CI任務檢查Git代碼庫的變動(合併):
上面建立了一個項目,簽出master,若是有變化則執行build.sh。點擊build now連接會簽出代碼,運行腳本並報告執行成功與否。(若是失敗了,能夠檢查構建日誌瞭解詳細信息,在繼續後續任務前把問題解決掉。)
咱們如今已經能夠在master發生變動時經過Jenkins/Hudson自動構建了,可是咱們還應該在提交代碼審查時進行構建。
下面要建立另外一個任務:
Name Example-Gerrit Type Free-style SCM Git URL git://localhost/example.git Advanced (below URL of repository) Refspec $GERRIT_REFSPEC Advanced (above repository browser) Choosing strategy Gerrit-plugin Build Triggers Gerrit Event Gerrit Project Path - ** - Path - **
有新事件發生時,Gerrit會觸發項目。可是咱們還差一步,要告訴Jenkins/Hudson監聽哪一個Gerrit服務器。
在Manage Jenkins/Hudson標籤頁中,有一項Gerrit Trigger,添加以下信息:
Hostname localhost URL http://localhost:8080 Port 29418 Username buildbot Keyfile /path/to/.ssh/id_rsa.buildbot SSH Keyfile password ...
首先,點擊下方的「Save」按鈕。而後,點擊Test Connection按鈕檢查配置是否成功。若是成功,點擊「Restart」,或者重啓Jenkins/Hudson。
若是一切順利,應該能夠回到主頁,左邊有一個Query and Trigger Gerrit Patches連接。點擊該連接,輸入is:open查看打開的變動,is:merged查看合併的變動。完成後,選中複選框,點擊Trigger Selected觸發該變動的構建。
若是你使用的是Hudson 2.0.0和Gerrit 2.2.0,在Hudson控制檯裏會看到java.lang.reflect.InvocationTargetException錯誤。這是新Gerrit Trigger的一個問題;升級到Hudson 2.0.1就行了。
你如今能夠在代碼庫的本地克隆中建立一個變動,推送到Gerrit中,讓Jenkins/Hudson自動爲你執行構建。
要測試失敗的狀況,編輯build.sh腳本,在文件末尾輸入exit 1。提交文件並將其推送到Gerrit,你會看到Jenkins/Hudson的狀態會變爲失敗,由於如今的構建腳本返回了一個非零碼。修復提交,將剛纔那行改成exit 0,推送以後你會看到構建結果變回成功。
最後,若是要使用xcodebuild構建iOS應用程序,經過ocunit2junit.rb腳原本串聯整個構建,它會把SenTest的斷言轉爲Jenkins/Hudson能夠理解的形式,這樣失敗的斷言就能打印在輸出的構建日誌裏了。