Git
Chapters ▾ 2nd Edition

6.3 GitHub - 維護專案

維護專案

現在我們可以舒適自在地對一個專案做出貢獻了,所以我們來看看另一個面向:建立、維護以及管理一個專案。

建立一個新倉儲

來建立一個拿來分享我們的原始碼的倉儲吧。 首先點擊主控面板右邊的「New Repository」;或是點擊頂端工具列裡面使用者名稱旁邊的 + 按鈕,如 「New repository」下拉式選單. 所示。

「Your Repositories」區塊
圖表 109. 「Your Repositories」區塊
「New repository」 下拉式選單
圖表 110. 「New repository」下拉式選單.

這會把你帶到「new repository」表單的所在頁面:

「new repositroy」表單
圖表 111. 「new repositroy」表單

你只需要提供專案名稱,因為剩餘的欄位是完全選擇性的。 現在,你只要點下「Create Repository」鈕,然後碰地一聲——你就擁有了一個在 GitHub 上名為 <user>/<project_name> 的全新倉儲了。

因為你這個倉儲還沒有任何原始碼在裡面,GitHub 會展示一份關於如何建立一個全新的 Git 倉儲或是連結一個舊有 Git 專案的指引。 我們在這邊不會對這這部份多做描述,如果你需要回憶一下,去看看 Git 基礎 吧。

現在你的專案被託管在 GitHub 上了,你可以把網址給任何你想要分享專案的人。 所有人都可以透過 https://github.com/<user>/<project_name> 以 HTTP 方式存取,或是透過 git@github.com:<user>/<project_name> 以 SSH 方式存取。 Git 可以透過上述兩種途徑來推送及擷取資料,但所有操作都會透過對其連結的使用的驗證資訊來做存取控管。

筆記

通常公開專案會傾向於分享基於 HTTP 的網址,因為這樣沒有 GitHub 帳戶的使用者也能夠對其存取來拓製專案。 如果你給了 SSH 版本的網址,使用者必須建立一個帳戶並加入 SSH key 才能存取專案。 而且 HTTP 網址就是他們會貼在瀏覽器裡來瀏覽專案的網址。

增加協作者

你必須要把和你合作的人加入「協作者」,這樣他們才能對專案提交變更。 如果 Ben、Jeff 和 Louise 都有 GitHub 帳戶,而且你想要給他們推送變更的權限,你可以把他們加到你的專案。 把他們加入專案後,他們可以對專案「推送」變更,這意味著他們有這專案及專案的 Git 倉儲的讀寫權限。

點擊右側欄最下面的「Settings」連結。

倉儲設定連結。
圖表 112. 倉儲設定連結。

接著選擇右邊選單的「Collaborators」。 然後在文字方塊裡輸入使用者名稱,按下「Add collaborator」。 你可以一直重複這個步驟來賦予所有你想要的人存取權限。 如果你要收回權限,只要點一下那個使用者右手邊的「X」即可。

倉儲協作者區
圖表 113. 倉儲協作者

管理 Pull Requests

現在你擁有一個裡面有些原始碼的專案,同時也可能會有些擁有推送權限的協作者。然後我們來看看當你收到 Pull Request 時要如何處理吧。

Pull Requests 可能是來自某個 fork 裡的分支,或是同個倉儲裡的某個分支。 兩者之間只差在,來自其他 fork 的 PR 通常你沒有對他們分支的推送權限,他們也沒有;而內部 PR 就是雙方都能存取分支。

關於這些東西的範例,我們就在這邊假設你是「tonychacon」而且你建立了一個名叫「fade」的 Arduino 原始碼專案吧。

電郵通知

有人對你的原始碼做了些變更,然後發給你一個 Pull Request。 這時你應該會收到像 對於新的 Pull Request 的電郵通知。 這樣的郵件。

Pull Request 電郵通知
圖表 114. 對於新的 Pull Request 的電郵通知。

這電郵裡面有些值得注意的東西。 他會給你一個簡易的差異狀態——一個在這 Pull Request 之中被變更的檔案清單,以及變動量。 內附一個 GitHub PR 連結。 同時也會給你一些可以從指令列操作的網址。

你可能會注意到這行指令 git pull <url> patch-1,這行指令是可以在不用增加遠端的情況下合併一個遠端分支的簡易方式。 我們曾在 切換到遠端分支 簡短的提過。 你可以去建立並切換至主題分支,然後執行這條指令以合併 Pull Request 中的變更。

其他有趣的網址就是 .diff.patch,你或許猜的到,他們分別提供 Pull Request 的統合差異和系列補綴。 你可以以下述方式來做技術性的合併:

$ curl http://github.com/tonychacon/fade/pull/1.patch | git am

在 Pull Request 裡合作

就如我們在 GitHub 流程 提過的,你現在可以和建立 Pull Request 的人對談了。 你可以針對某幾行原始碼提出評論、對一整個提交做評論或是對一整個 Pull Request 做評論,而且你在其中每個部分都可以使用 GitHub 風格的 Markdown。

每當有人在 Pull Request 裡留下評論時,你都會收到一封電郵通知,這樣你就能掌握整個 Pull Request 的動態。 每次通知都會附有連結連往 Pull Request 有活動的部分,同時你也可以直接回覆郵件以在 Pull Request 討論串中評論。

電郵回覆
圖表 115. 包含在討論串中的電郵回覆。

當你覺得 PR 裡面的原始碼已經可以合併的時候,你可手動拉取,然後在本地端合併;或是用 git pull <url> <branch> 這個稍早看過的語法;也可以把那個 fork 加入成遠端之一之後再擷取並合併。

如果這只是個簡單的合併,你可以按下 GitHub 網站上的「Merge」按鈕來解決。 這會做一個「非快進」的合併——即便是可以快進,仍會建立合併提交。 這意味著,不論你在何種情況按下「Merge」,都會建立一個合併提交。 如果你點了提示連結,GitHub 就會會提供你所有的資訊,就像你在 Merge 按鈕和手動合併 Pull Request 的指引。 看到的一樣。

Merge 按鈕
圖表 116. Merge 按鈕和手動合併 Pull Request 的指引。

如果你決定不要合併這個 Pull Request,你只需要關閉這個 Pull Request 即可,同時建立這個 Pull Request 的人也會收到通知。

Pull Request 參照

如果你要處理 非常多 的 Pull Request 而且不想加入一堆的遠端或是一直做只會用到一次的拉取,關於這點 GitHub 提供了一個好用的小技巧給你用。 這是個有點進階的技巧,所以我們會在 The Refspec 提到更多的細節,不過還是非常的有用。

事實上 GitHub 會把倉儲的 Pull Request 當成伺服器上的假分支。 預設情況下你不會在拓製的時候取得它們,但他們還是以隱藏的狀態存在著而且你可以用非常簡單的方式取得它們。

To demonstrate this, we’re going to use a low-level command (often referred to as a “plumbing” command, which we’ll read about more in Plumbing and Porcelain) called ls-remote. This command is generally not used in day-to-day Git operations but it’s useful to show us what references are present on the server. 為了展示這個事實,我們要使用一個比較低階的指令(通常會被稱作「底層」指令,關於這點我們會在 Plumbing and Porcelain 再做詳細描述)—— ls-remote。 這指令通常不會在日常的 Git 操作使用,但在展現伺服器上的所有參照是非常有用的。

如果對我們之前的「blink」倉儲使用這條指令,我們會得到在伺服器上這個倉儲裡所有的分支、標籤和其他各種參照的清單。

$ git ls-remote https://github.com/schacon/blink
10d539600d86723087810ec636870a504f4fee4d	HEAD
10d539600d86723087810ec636870a504f4fee4d	refs/heads/master
6a83107c62950be9453aac297bb0193fd743cd6e	refs/pull/1/head
afe83c2d1a70674c9505cc1d8b7d380d5e076ed3	refs/pull/1/merge
3c8d735ee16296c242be7a9742ebfbc2665adec1	refs/pull/2/head
15c9f4f80973a2758462ab2066b6ad9fe8dcf03d	refs/pull/2/merge
a5a7751a33b7e86c5e9bb07b26001bb17d775d1a	refs/pull/4/head
31a45fc257e8433c8d8804e3e848cf61c9d3166c	refs/pull/4/merge

當然,如果你在你的倉儲裡使用 git ls-remote origin 或是對其他任一個想確認的遠端使用,你會得到一個與這類似的結果。

如果你的倉儲是在 GItHub 上,而且有開放中的 Pull Request;你會看到一些以 refs/pull/ 開頭的參照。 它們基本上也是分支,但是因為他們不是以 refs/heads 起頭,所以你一般來說不會在拓製或擷取時從伺服器下載到他們——擷取的過程會忽略它們。

每個 Pull Request 都會有兩個參照——以 /head 結尾的是對應到目前 Pull Request 分支的最後一個提交。 所以,如果有人在我們的倉儲開了一個 Pull Request,而且他的分支名稱叫做 bug-fix 還有它指向 a5a775 這個提交,在之後我們的倉儲裡並不會出現 bug-fix 這個分支,但我們會出現指向 a5a775pull/<pr#>/head。 這意味著我們可以非常簡單的直接拉取所有 Pull Request 分支,而非加一大堆的遠端來解決。

現在,你可以直接做些事––好比說擷取參考。

$ git fetch origin refs/pull/958/head
From https://github.com/libgit2/libgit2
 * branch            refs/pull/958/head -> FETCH_HEAD

這告訴了 Git:「連結到名為 origin 的遠端,並下載名為 refs/pull/958/head 的參考。」 Git 很樂意的照做了,之後下載了所有建立這個參考的必要資訊,之後就在 .git/FETCH_HEAD 裡放了一個指向你所需要的提交的指針。 你可以接著在你想要測試的分支裡執行 git merge FETCH_HEAD,不過這個合併提交的訊息可能會有點奇怪。 不過,如果你需要審閱「一大堆」的 Pull Request,這會顯得相當的枯燥乏味。

也是有辦法可以擷取「全部」的 Pull Request 的,而且可以在你每次連接到遠端時更新。 用你習慣的編輯器打開 .git/config,並且找到關於遠端 origin 的部份。 通常會長的像這樣:

[remote "origin"]
    url = https://github.com/libgit2/libgit2
    fetch = +refs/heads/*:refs/remotes/origin/*

fetch = 開頭的那行是個「參照規格」。 這是個本地端的 .git 資料夾裏面的名稱對應到遠端的方法。 這一段告訴 Git:「在遠端 refs/heads 之下的東西,要保存在本地倉儲的 refs/remotes/origin 之下。」 你可以編輯這個段落以加入其他的參照規格:

[remote "origin"]
    url = https://github.com/libgit2/libgit2.git
    fetch = +refs/heads/*:refs/remotes/origin/*
    fetch = +refs/pull/*/head:refs/remotes/origin/pr/*

最後一行告訴 Git:「所有類似 refs/pull/123/head 的參照都會以 refs/remotes/origin/pr/123 的型式儲存在本地端。」 所以現在存檔,然後執行 git fetch

$ git fetch
# …
 * [new ref]         refs/pull/1/head -> origin/pr/1
 * [new ref]         refs/pull/2/head -> origin/pr/2
 * [new ref]         refs/pull/4/head -> origin/pr/4
# …

現在所有遠端的 Pull Request 都會以類似追蹤分支型式的參照出現在本端;他們是唯讀的,並且會在你做擷取的時候更新。 這讓在本地端測試 pull request 裡的程式碼變成超級簡單的事:

$ git checkout pr/2
Checking out files: 100% (3769/3769), done.
Branch pr/2 set up to track remote branch pr/2 from origin.
Switched to a new branch 'pr/2'

你們其中某些比較眼尖的人可能已經注意到參照規格中遠端部份的尾巴的 head。 這同時也是 GitHub 端一個名為 refs/pull/#/merge 的參照,這代表著當你點下網站上的「Merge」鈕時會產生的提交。 這讓你甚至可以在按下按鈕前測試合併結果。

對應到 Pull Request 的 Pull Request

你不只可以對主要分支或是 master 分支建立 Pull Request,你也可以對這整個網絡裡的任意一個分支做同樣的事。 事實上,你甚至可以對另外一個 Pull Request 做 Pull Request。

如果你發現一個 Pull Request 正在往良好的方向發展,而你也想加點依賴於它的變更、或是你只是不確定這變更否是個好主意、甚至只是因為你沒有對目的分支推送的權限時,你都可以直接對它開 PR。

當你要開啟一個 Pull Request 時,頁面最上方會有個區塊可以讓你選擇要請求擁有者在哪個分支上拉取變更,以及要從哪個分支拉取。 如果你按下右手邊的「Edit」鈕,你不只能指定分支,也可以指定 fork。

PR 目標
圖表 117. 手動指定 Pull Request 的目標 fork 和分支

在這邊你可以相當簡單的方式決定你要把你的新分支合併到另一個 Pull Request 或是這專案底下的其他 fork。

提及他人和通知

GitHub 也有非常好的通知系統,讓徵詢特定人或團隊的意見變成一件易如反掌的事。

在任意一個專案裡,當你一輸入 @ 這個字元後,自動完成就會提供給你所有這個計畫的協作者和貢獻者的顯示名稱及使用者名稱。

提及他人
圖表 118. 輸入 @ 來提到其他人

你也可以提及某個並沒有出現在這個下拉式清單的使用者,不過自動完成通常會更快把牠抓出來。

當你發佈了一個有提到其他使用者的評論時,那些被標記的人會收到通知。 這意味著這會是一個非常有效率的把人拉入討論的方式,而非讓那些人主動追蹤討論進度。 在 GitHub 上人們很常把同團隊或是同公司的人拉近討論裡,藉以審閱 Pull Request 或是議題。

如果有人被標記,會被自動訂閱提到他們的 Pull Request 或是議題,之後就會收到所有相關的動態。 你也會自動訂閱所有你建立的東西、你觀注的版本庫或是你曾經發表過評論的東西。 如果你不想繼續收到通知,你可以按下頁面裡的「Unsubscribe」鈕來停止收到後續的更新。

取消訂閱
圖表 119. 取消訂閱 PullRequest 或是議題。

通知總覽頁面

當我們在這邊提到關於 GitHub 的「通知」時,這是指 GitHub 試著讓你跟上新發生的事件的方式,而且你也有許多方式可以自訂。 如果進到設定頁面的「Notification Center」分頁,你會看到一些可以使用的選項。

通知中心
圖表 120. 通知中心選項。

在這邊你有兩種取得通知的方式可以選擇––「電子郵件」和「網頁」,你可以決定當你在在參與事情或是接收你關注的版本庫的動態時,你要如何透過這兩個管道接受通知。

網頁通知

網頁通知僅存在於 GitHub 上,而你也只能在 GitHub 上檢視。 如果你有選用這個選項,當你在收到通知的時候,你會在頁面上方的通知圖示上看到一個藍點,就如 通知中心 所示。

通知中心
圖表 121. 通知中心

如果你點一下那個圖示,你會看到以專案分類的通知清單。 你也可以點擊-左側列表裡的專案名稱來過濾出關於個專案的通知。 你也以按下任一項通知右側的勾選圖示來確認接收,或是點下專案名稱旁的勾選圖示來接收所有關於這個專案的通知。 勾選圖示旁邊也有個靜音按鈕,當你點下那個圖示,代表你將不會收到那項東西的後續通知。

這些工具對於管理大量的通知來說是非常的方便。 許多的 GitHub 的進階使用者會直接關掉所有的電郵通知,然後在這頁面上管理所有的通知。

電郵通知

電郵通知是 GitHub 上另一個接受通知的方式。 如果你開啟這個選項,之後每當你收到通知,你就會收到一封電郵。 我們可以在 以電子郵件型式寄送的評論對於新的 Pull Request 的電郵通知。 有範例。 這廂電子郵件會自動討論串化,如果你在使用討論串式的電郵客戶端,這會是個好事情。

GitHub 會再寄給你的通知郵件的標頭里嵌入相當多的後設資訊,這樣你在建立自訂過濾條件時可以更得心應手。

舉例來說,如果展開在 對於新的 Pull Request 的電郵通知。 寄給 Tony 的郵件的真實標頭,我們會看到這樣被寄出的訊息。

To: tonychacon/fade <fade@noreply.github.com>
Message-ID: <tonychacon/fade/pull/1@github.com>
Subject: [fade] Wait longer to see the dimming effect better (#1)
X-GitHub-Recipient: tonychacon
List-ID: tonychacon/fade <fade.tonychacon.github.com>
List-Archive: https://github.com/tonychacon/fade
List-Post: <mailto:reply+i-4XXX@reply.github.com>
List-Unsubscribe: <mailto:unsub+i-XXX@reply.github.com>,...
X-GitHub-Recipient-Address: tchacon@example.com

這裡面有不少有趣的東西。 如果你想針對特定專案甚至是 Pull Request 的電郵做特別標示或是轉寄時,「Message-ID」這項以 <user>/<project>/<type>/<id> 的格式提供了所有資訊。 如果這是個議題,`<type>`這部分就會是「issue」而非「pull」。

而而你如果有個能夠解析 List-PostList-Unsubsribe 這兩個欄位的電郵客戶端的話,你就能直接發表意見到清單裡, 或是直接「取消訂閱」這個串,就像你直接在那 Pull Request 或是議題頁面上做的一樣。

值得一提的是,如果你同時啟用網頁和電郵通知,當你使用允許內嵌圖片的郵件客戶端開啟通知郵件時,網頁上的通知也會被標示為已讀。

特殊檔案

當有些特殊檔案出現在你的版本庫時,GitHub 會注意到它們。

README

第一個就是 README 檔,它可以用任意一種可以被 GitHub 便是成文章的格式寫成。 舉例來說,它可以是 READMEREADME.mdREADME.asciidoc、等等。 如果 GitHub 在你的原始碼裡發現 README 這個檔案時,他會被渲染再在專案首頁。

許多團隊用這檔案來整理所有這專案的相關資訊,來讓第一次接觸這個專案或版本庫的人了解這個專案。 通常會包含這些東西:

  • 這個專案的目的

  • 如何設定及安裝

  • 舉個使用或執行的例子

  • 這個專案是基於哪種授權發布的

  • 如何對這專案做貢獻

因為 GitHub 會渲染這個檔案,所以你可以嵌入圖片或連結來讓他更容易理解。

CONTRIBUTING

另個 GitHub 會辨識的特殊檔案就是 CONTRIBUTING。 如果你有個帶著任意種附檔名的 CONTRIBUTING,GitHub 會把它顯示成 在有 CONTRIBUTING 這個檔案時建立 Pull Request 給那些想建立 Pull Request 的使用者看。

貢獻須知
圖表 122. 在有 CONTRIBUTING 這個檔案時建立 Pull Request

這檔案就是你可以指定發給你這專案的 Pull Request 裡面可以包含哪些以及不能包含哪些東西。 這樣大家或許就會在建立 Pull Request 前看看這些原則了。

專案管理

你在一個專案上通常沒有什麼管理性的事能做,不過這邊有幾個你或許有興趣的專案。

變更主分支

如果你希望使用其他不是「master」的分支來作為其他人建立 Pull Request 的預設目標分支,你可以在版本庫的設定頁面的「Options」分頁裡設定。

預設分支
圖表 123. 變更一個專案的預設分支

只要在下拉式清單裡選擇你要的分支,就可以簡單的變更所有主要動作的預設分支,包含其他人在拓製版本庫時預設簽出的分支。

版本庫移轉

如果你想要把一個專案轉移給其他在 GitHub 上的使用者或是組織時,你可以在倉儲設定裡同樣在「Options」分頁的底部找到 「Transfer ownership」來達成這件事。

轉移
圖表 124. 把一個專案轉移給其他的 GitHub 使用者或是組織

這當你要放棄一個專案而有人要接手時很有幫助,或是在你的專案日漸茁壯,你想要把它移到一個組織裡時也有用。

這個動作不只會把所有關注和標記星號的使用者搬到其他地方,同時也會在舊頁面建立連向新頁面的重導向連結。 這也會重導向所有來自 Git 的擷取和拓製動作,不只是網頁請求而已。