章節 ▾ 第二版

6.3 GitHub - 維護專案

維護專案

既然我們已經熟悉瞭如何為一個專案貢獻程式碼,接下來讓我們看看另一方面:如何建立、維護和管理你自己的專案。

建立新倉庫

讓我們建立一個新倉庫來分享我們的專案程式碼。首先點選儀表盤右側的“新建倉庫”按鈕,或者點選頂部工具欄使用者名稱旁邊的+按鈕,如“新建倉庫”下拉選單所示。

The “Your repositories” area
圖 109. “你的倉庫”區域
The “New repository” dropdown
圖 110. “新建倉庫”下拉選單

這會將你帶到“新建倉庫”表單

The “new repository” form
圖 111. “新建倉庫”表單

你真正需要做的就是提供一個專案名稱;其餘欄位完全是可選的。現在,只需點選“建立倉庫”按鈕,砰——你就在 GitHub 上有了一個新倉庫,名為<user>/<project_name>

由於你還沒有程式碼,GitHub 將顯示如何建立一個全新的 Git 倉庫,或連線一個現有 Git 專案的說明。我們在這裡不再贅述;如果你需要複習,請檢視Git 基礎

既然你的專案託管在 GitHub 上,你可以將 URL 提供給任何你想分享專案的人。GitHub 上的每個專案都可以透過 HTTPS(例如https://github.com/<user>/<project_name>)和 SSH(例如git@github.com:<user>/<project_name>)訪問。Git 可以從這兩個 URL 拉取(fetch)和推送(push),但它們會根據連線使用者的憑據進行訪問控制。

注意

對於公共專案,通常更推薦分享基於 HTTPS 的 URL,因為使用者無需擁有 GitHub 賬戶即可克隆訪問。如果你向他們提供 SSH URL,使用者則必須擁有賬戶並上傳 SSH 金鑰才能訪問你的專案。HTTPS 地址也正是他們會貼上到瀏覽器中檢視專案的 URL。

新增協作者

如果你與想要授予提交(commit)許可權的其他人一起工作,你需要將他們新增為“協作者”。如果 Ben、Jeff 和 Louise 都在 GitHub 上註冊了賬戶,並且你希望授予他們對你的倉庫的推送(push)許可權,你可以將他們新增到你的專案。這樣做將賦予他們“推送”許可權,這意味著他們對專案和 Git 倉庫同時擁有讀寫訪問權。

點選右側邊欄底部的“設定”連結。

The repository settings link
圖 112. 倉庫設定連結

然後從左側選單中選擇“協作者”。接著,只需在框中輸入使用者名稱,然後點選“新增協作者”。你可以根據需要重複此操作,以授予訪問許可權給所有你喜歡的人。如果需要撤銷訪問許可權,只需點選他們所在行右側的“X”。

The repository collaborators box
圖 113. 倉庫協作者框

管理拉取請求

既然你擁有一個包含一些程式碼的專案,甚至可能還有一些擁有推送許可權的協作者,那麼讓我們回顧一下當你自己收到拉取請求(Pull Request)時該怎麼做。

拉取請求可以來自你倉庫的派生倉庫(fork)中的分支,也可以來自同一倉庫中的另一個分支。唯一的區別是,派生倉庫中的拉取請求通常來自你無法推送到他們分支、他們也無法推送到你的分支的人,而對於內部拉取請求,通常雙方都可以訪問該分支。

對於這些示例,我們假設你是“tonychacon”,並且你建立了一個名為“fade”的 Arduino 程式碼專案。

郵件通知

有人對你的程式碼進行了更改並向你傳送了拉取請求。你應該會收到一封關於新拉取請求的通知郵件,它應該看起來像新拉取請求的郵件通知

Email notification of a new Pull Request
圖 114. 新拉取請求的郵件通知

這封郵件有幾點值得注意。它會給你一個簡短的 diffstat——一個列出在拉取請求中更改了哪些檔案以及更改了多少的列表。它還提供了指向 GitHub 上該拉取請求的連結。此外,它還提供了幾個可以在命令列使用的 URL。

如果你注意到那行寫著git pull <url> patch-1的命令,這是一種無需新增遠端倉庫即可合併遠端分支的簡單方法。我們之前在檢出遠端分支中簡要介紹過這一點。如果你願意,可以建立一個主題分支並切換到該分支,然後執行此命令來合併拉取請求的更改。

其他有趣的 URL 是.diff.patch URL,顧名思義,它們提供了拉取請求的統一差異(unified diff)和補丁(patch)版本。理論上,你可以用類似這樣的方式合併拉取請求的工作:

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

在拉取請求上協作

正如我們在GitHub 流程中所介紹的,你現在可以與開啟拉取請求的人進行對話。你可以評論特定的程式碼行、評論整個提交,或者評論整個拉取請求本身,並且處處使用 GitHub 風味 Markdown。

每次有人評論拉取請求時,你都會繼續收到郵件通知,以便你瞭解正在進行的活動。每封郵件都將包含指向活動發生位置的拉取請求連結,你也可以直接回復郵件以評論拉取請求的討論串。

Responses to emails are included in the thread
圖 115. 郵件回覆將包含在討論串中

一旦程式碼達到你喜歡的狀態並希望將其合併,你可以透過我們之前看到的git pull <url> <branch>語法在本地拉取程式碼併合並,或者透過將派生倉庫新增為遠端倉庫然後拉取(fetch)併合並。

如果合併很簡單,你也可以直接點選 GitHub 網站上的“合併”按鈕。這將執行一次“非快進合併”,即使可以進行快進合併,也會建立一個合併提交。這意味著無論如何,每次你點選合併按鈕,都會建立一個合併提交。如合併按鈕和手動合併拉取請求的說明所示,如果你點選提示連結,GitHub 會提供所有這些資訊。

Merge button and instructions for merging a Pull Request manually
圖 116. 合併按鈕和手動合併拉取請求的說明

如果你決定不合並它,你也可以直接關閉拉取請求,開啟它的人會收到通知。

拉取請求引用

如果你正在處理大量拉取請求,並且不想每次都新增一堆遠端倉庫或進行一次性拉取,GitHub 允許你使用一個巧妙的技巧。這有點高階,我們將在Refspec中更詳細地介紹它,但它可能非常有用。

GitHub 實際上將倉庫的拉取請求分支作為伺服器上的偽分支進行宣傳。預設情況下,當你克隆時不會獲取它們,但它們以一種隱蔽的方式存在,並且你可以相當容易地訪問它們。

為了演示這一點,我們將使用一個低階命令(通常被稱為“底層命令”,我們將在底層命令與日常命令中閱讀更多相關內容),名為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 上,並且你打開了任何拉取請求,你將獲得以refs/pull/為字首的這些引用。這些基本上是分支,但由於它們不在refs/heads/下,所以當你從伺服器克隆或拉取(fetch)時通常不會獲取它們——拉取過程通常會忽略它們。

每個拉取請求有兩個引用——其中以/head結尾的引用指向的提交與拉取請求分支中的最新提交完全相同。因此,如果有人在我們的倉庫中開啟一個拉取請求,他們的分支名為bug-fix並指向提交a5a775,那麼在我們的倉庫中,我們將不會有一個bug-fix分支(因為那在他們的派生倉庫中),但我們有一個指向a5a775pull/<pr#>/head引用。這意味著我們可以很容易地一次性拉取所有拉取請求分支,而無需新增一堆遠端倉庫。

現在,你可以直接獲取引用。

$ 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合併到你想測試的分支中,但這樣做的合併提交訊息看起來會有點奇怪。此外,如果你正在審查大量拉取請求,這會變得很繁瑣。

還有一種方法可以獲取所有拉取請求,並在你連線到遠端倉庫時保持它們最新。在你喜歡的編輯器中開啟.git/config,然後找到origin遠端倉庫。它應該看起來像這樣:

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

那行以fetch =開頭的行是一個“引用規範”(refspec)。它是一種將遠端倉庫中的名稱與本地.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
# …

現在,所有遠端拉取請求都在本地由引用表示,這些引用就像跟蹤分支一樣;它們是隻讀的,並且在你執行拉取(fetch)時更新。這使得在本地嘗試拉取請求的程式碼變得超級容易。

$ 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引用,它代表瞭如果你在網站上點選“合併”按鈕後將產生的提交。這可以讓你在點選按鈕之前就測試合併。

基於拉取請求的拉取請求

你不僅可以開啟以 main 或master分支為目標的拉取請求,實際上你還可以開啟以網路中任何分支為目標的拉取請求。事實上,你甚至可以以另一個拉取請求為目標。

如果你看到一個拉取請求正朝著正確的方向發展,並且你有一個依賴於它的更改想法,或者你不確定這個想法是否好,或者你只是沒有目標分支的推送許可權,你可以直接向它開啟一個拉取請求。

當你去開啟一個拉取請求時,頁面頂部有一個框,指定了你請求拉取到哪個分支以及從哪個分支拉取。如果你點選該框右側的“編輯”按鈕,你不僅可以更改分支,還可以更改是哪個派生倉庫。

Manually change the Pull Request target fork and branch
圖 117. 手動更改拉取請求的目標派生倉庫和分支

在這裡,你可以相當容易地指定將你的新分支合併到另一個拉取請求或專案的另一個派生倉庫中。

提及和通知

GitHub 還內建了一個非常好的通知系統,當你需要向特定個人或團隊提問或徵求反饋時,它會派上用場。

在任何評論中,你都可以開始輸入@字元,它將開始自動補全專案中協作者或貢獻者的姓名和使用者名稱。

Start typing @ to mention someone
圖 118. 開始輸入 @ 提及某人

你也可以提及不在該下拉列表中的使用者,但通常自動補全功能會更快。

一旦你釋出了包含使用者提及的評論,該使用者將收到通知。這意味著這是一種將人們引入對話的非常有效的方式,而不是讓他們被動輪詢。在 GitHub 的拉取請求中,人們經常會邀請團隊或公司中的其他人來審查議題或拉取請求。

如果有人在拉取請求或議題中被提及,他們將被“訂閱”該項,並在其發生任何活動時持續收到通知。如果你打開了它、正在關注倉庫或評論了某項內容,你也會被訂閱。如果你不再希望收到通知,頁面上有一個“取消訂閱”按鈕,你可以點選它以停止接收更新。

Unsubscribe from an Issue or Pull Request
圖 119. 取消訂閱議題或拉取請求

通知頁面

當我們在這裡提及 GitHub 的“通知”時,我們指的是 GitHub 在事件發生時與你聯絡的特定方式,並且有幾種不同的方式可以配置它們。如果你從設定頁面進入“通知中心”選項卡,你可以看到一些可用的選項。

Notification center options
圖 120. 通知中心選項

兩種選擇是透過“電子郵件”和“網頁”接收通知,你可以選擇兩者之一、兩者皆無或兩者兼有,用於你積極參與的活動以及你關注的倉庫的活動。

網頁通知

網頁通知只存在於 GitHub 上,你只能在 GitHub 上檢視它們。如果你在偏好設定中選擇了此選項,並且有通知觸發,你將在螢幕頂部的通知圖示上看到一個小藍點,如通知中心所示。

Notification center
圖 121. 通知中心

如果你點選它,你將看到所有你已收到通知的專案列表,按專案分組。你可以透過點選左側邊欄中的專案名稱來篩選特定專案的通知。你還可以透過點選任何通知旁邊的複選標記圖示來確認通知,或者透過點選分組頂部的複選標記來確認專案中所有的通知。每個複選標記旁邊還有一個靜音按鈕,你可以點選它來停止接收該專案的任何進一步通知。

所有這些工具對於處理大量通知都非常有用。許多 GitHub 高階使用者會乾脆完全關閉電子郵件通知,並透過此螢幕管理所有通知。

郵件通知

電子郵件通知是你在 GitHub 上處理通知的另一種方式。如果你開啟此功能,你將收到每條通知的郵件。我們在以電子郵件通知形式傳送的評論新拉取請求的郵件通知中看到了這方面的示例。如果你使用的是支援執行緒的電子郵件客戶端,這些郵件也會正確地進行執行緒化,這很好用。

GitHub 傳送給你的電子郵件的頭部還嵌入了大量的元資料,這對於設定自定義過濾器和規則非常有幫助。

例如,如果我們檢視新拉取請求的郵件通知中顯示傳送給 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

這裡有幾點有趣之處。如果你想突出顯示或重新路由郵件到這個特定專案甚至是拉取請求,Message-ID中的資訊會以<user>/<project>/<type>/<id>的格式提供所有資料。例如,如果這是一個議題,<type>欄位將是“issues”而不是“pull”。

List-PostList-Unsubscribe欄位意味著如果你有一個支援這些欄位的郵件客戶端,你可以輕鬆地向列表發帖或從討論串中“取消訂閱”。這與點選網頁版通知上的“靜音”按鈕或議題或拉取請求頁面上的“取消訂閱”本質上是相同的。

還需要注意的是,如果你同時啟用了電子郵件和網頁通知,並且你閱讀了郵件版本的通知,那麼如果你的郵件客戶端允許顯示圖片,網頁版本也將被標記為已讀。

特殊檔案

如果你的倉庫中存在一些特殊檔案,GitHub 會注意到它們。

README

第一個是README檔案,它可以是 GitHub 識別為文字的幾乎任何格式。例如,它可以是READMEREADME.mdREADME.asciidoc等。如果 GitHub 在你的原始碼中看到README檔案,它會將其呈現在專案的登入頁面上。

許多團隊使用此檔案來儲存對倉庫或專案可能不熟悉的人來說所有相關的專案資訊。這通常包括以下內容:

  • 專案用途

  • 如何配置和安裝

  • 如何使用或執行它的示例

  • 專案所使用的許可證

  • 如何貢獻

由於 GitHub 會渲染此檔案,你可以在其中嵌入影像或連結,以提高理解的便利性。

CONTRIBUTING

GitHub 識別的另一個特殊檔案是CONTRIBUTING檔案。如果你有一個名為CONTRIBUTING(帶任何副檔名)的檔案,當任何人開始開啟拉取請求時,GitHub 將顯示當存在 CONTRIBUTING 檔案時開啟拉取請求

Opening a Pull Request when a CONTRIBUTING file exists
圖 122. 當存在 CONTRIBUTING 檔案時開啟拉取請求

這裡的想法是,你可以指定你希望或不希望你的專案收到的拉取請求中包含的特定內容。這樣,人們在開啟拉取請求之前可能會真正閱讀指南。

專案管理

通常,對於單個專案,你無法進行太多管理操作,但有幾項可能會讓你感興趣。

更改預設分支

如果你使用“master”以外的分支作為你的預設分支,希望人們預設在該分支上開啟拉取請求或看到它,你可以在倉庫設定頁面的“選項”選項卡下更改它。

Change the default branch for a project
圖 123. 更改專案的預設分支

只需在下拉列表中更改預設分支,此後它將成為所有主要操作的預設設定,包括當有人克隆倉庫時預設檢出的分支。

轉移專案

如果你想將專案轉移到 GitHub 中的另一個使用者或組織,在你的倉庫設定頁面相同的“選項”選項卡底部有一個“轉移所有權”選項,允許你執行此操作。

Transfer a project to another GitHub user or Organization
圖 124. 將專案轉移到另一個 GitHub 使用者或組織

如果你放棄了一個專案並且有人想接管它,或者如果你的專案變得越來越大並希望將其移到一個組織中,這將很有幫助。

這不僅會將倉庫及其所有關注者和星標移動到另一個位置,還會設定從你的 URL 到新位置的重定向。它還會重定向 Git 的克隆(clones)和拉取(fetches),而不僅僅是網頁請求。

scroll-to-top