# 維護項目
現在我們可以很方便地向一個項目貢獻內容,來看一下另一個方面的內容:創建、維護和管理你自己的項目。
### 創建新的版本庫
讓我們創建一個版本庫來分享我們的項目。通過點擊面板右側的“New repository”按鈕,或者頂部工具條你用戶名旁邊的 `+` 按鈕來開始我們的旅程。 參見 [Figure?6-30](#)。

Figure 6-29. 這是 “Your repositories”區域.

Figure 6-30. 這是 “New repository” 下拉列表.
這會帶你到 “new repository” 表單:

Figure 6-31. 這是 “new repository” 表單.
這里除了一個你必須要填的項目名,其他字段都是可選的。現在只需要點擊 “Create Repository” 按鈕,Duang!!! – 你就在 GitHub 上擁有了一個以 `<user>/<project_name>` 命名的新倉庫了。
因為目前暫無代碼,GitHub 會顯示有關創建新版本庫或者關聯到一個已有的 Git 版本庫的一些說明。我們不會在這里詳細說明此項,如果你需要復習,去看 [Chapter?2](#)。
現在你的項目就托管在 GitHub 上了,你可以把 URL 給任何你想分享的人。GitHub 上的項目可通過 HTTP 或 SSH 訪問,格式是:HTTP : `https://github.com/<user>/<project_name>` , SSH : `git@github.com:<user>/<project_name>` 。Git 可以通過以上兩種 URL 進行抓取和推送,但是用戶的訪問權限又因連接時使用的證書不同而異。
通常對于公開項目可以優先分享基于 HTTP 的 URL,因為用戶克隆項目不需要有一個 GitHub 帳號。如果你分享 SSH URL,用戶必須有一個帳號并且上傳 SSH 密鑰才能訪問你的項目。HTTP URL 與你貼到瀏覽器里查看項目用的地址是一樣的。
### 添加合作者
如果你想與他人合作,并想給他們提交的權限,你需要把他們添加為 “Collaborators”。如果 Ben,Jeff,Louise 都在 GitHub 上注冊了,你想給他們推送的權限,你可以將他們添加到你的項目。這樣做會給他們 “推送” 權限,就是說他們對項目和 Git 版本庫都有讀寫的權限。
點擊邊欄底部的 “Settings” 鏈接。

Figure 6-32. 版本庫設置鏈接.
然后從左側菜單中選擇 “Collaborators” 。然后,在輸入框中填寫用戶名,點擊 “Add collaborator.”如果你想授權給多個人,你可以多次重復這個步驟。如果你想收回權限,點擊他們同一行右側的 “X”

Figure 6-33. 版本庫合作者.
## 管理合并請求
現在你有一個包含一些代碼的項目,可能還有幾個有推送權限的合作者,下面來看當你收到合并請求時該做什么。
合并請求可以來自倉庫副本的一個分支,或者同一倉庫的另一個分支。唯一的區別是 fork 過來的通常是和你不能互相推送的人,而內部的推送通常都可以互相訪問。
作為例子,假設你是 “tonychacon” ,你創建了一個名為 “fade” 的 Arduino 項目.
### 郵件通知
有人來修改了你的代碼,給你發了一個合并請求。你會收一封關于合并請求的提醒郵件,它看起來像 [Figure?6-34](#)。

Figure 6-34. 新的合并請求的郵件通知.
關于這個郵件有幾個要注意的地方。它會給你一個小的變動統計結果?—?一個包含合并請求中改變的文件和改變了多少的列表。它還給你一個 GitHub 上進行合并請求操作的鏈接。還有幾個可以在命令行使用的 URL。
如果你注意到 `git pull <url> patch-1` 這一行,這是一種合并遠程分支的簡單方式,無需必須添加一個遠程分支。我們很快會在 [“檢出遠程分支”](#)._ 講到它。如果你愿意,你可以創建并切換到一個主題分支,然后運行這個命令把合并請求合并進來。
還有一些有趣的 URL,像 `.diff` 和 `.patch` ,就像你猜的那樣,它們提供 diff 和 patch 的標準版本。你可以技術性地用下面的方法合并“合并請求”:
~~~
$ curl http://github.com/tonychacon/fade/pull/1.patch | git am
~~~
### 在合并請求上進行合作
就像我們在 [“GitHub 流程”](#),_ 說過的,現在你可以跟開啟合并請求的人進行會話。你既可以對某些代碼添加注釋,也可以對整個提交添加注釋或對整個合并請求添加注釋,在任何地方都可以用 GitHub Flavored Markdown。
每次有人在合并請求上進行注釋你都會收到通知郵件,通知你哪里發生改變。他們都會包含一個到改變位置的鏈接,你可以直接在郵件中對合并請求進行注釋。

Figure 6-35. Responses to emails are included in the thread.
一旦代碼符合了你的要求,你想把它合并進來,你可以把代碼拉取下來在本地進行合并,也可以用我們之前提到過的 `git pull <url> <branch>` 語法,或者把 fork 添加為一個 remote,然后進行抓取和合并。
對于很瑣碎的合并,你也可以用 GitHub 網站上的 “Merge” 按鈕。它會做一個 “non-fast-forward” 合并,即使可以快進(fast-forward)合并也會產生一個合并提交記錄。就是說無論如何,只要你點擊 merge 按鈕,就會產生一個合并提交記錄。你可以在 [Figure?6-36](#) 看到,如果你點擊提示鏈接,GitHub 會給你所有的這些信息。

Figure 6-36. 合并按鈕和手工合并一個合并請求的指令.
如果你決定不合并它,你可以把合并請求關掉,開啟合并請求的人會收到通知。
### 合并請求引用
如果你正在處理 **許多** 合并請求,不想添加一堆 remote 或者每次都要做一次拉取,這里有一個可以在 GitHub 上用的小技巧。這是有點高級的技巧,但它相當有用,我們會在 [“引用規格”](#) 有更多的細節說明。
實際上 GitHub 在服務器上把合并請求分支視為一種 “假分支”。默認情況下你克隆時不會得到它們,但它們還是隱式地存在,你可以很容易地訪問到它們。
為了展示這個,我們要用到一個叫做 `ls-remote` 的低級命令(通常被叫做“plumbing”,我們會在 [“底層命令和高層命令”](#) 讀到更多相關內容)。這個命令在日常 Git 操作中基本不會用到,但在顯示服務器上有哪些引用(reference)時很管用。
如果在我們之前用過的 “blink” 版本庫上使用這個命令,我們會得到一個版本庫里所有的分支,標簽和其它引用(reference)的列表。
~~~
$ 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/` 中,所以正常情況下你克隆時不會從服務器上得到它們?—?抓取過程正常情況下會忽略它們。
每個合并請求有兩個引用 - 其中以 `/head` 結尾的引用指向的提交記錄與合并請求分支中的最后一個提交記錄是同一個。所以如果有人在我們的版本庫中開啟了一個合并請求,他們的分支叫做 `bug-fix`,指向 `a5a775` 這個提交記錄,那么在 **我們的** 版本庫中我們沒有 `bug-fix` 分支(因為那是在他們的 fork 中),但我們 **可以** 有一個 `pull/<pr#>/head` 指向 `a5a775`。這意味著我們可以很容易地拉取每一個合并請求分支而不用添加一堆 remote。
現在,你可以像直接抓取引用一樣抓取那些分支或提交。
~~~
$ git fetch origin refs/pull/958/head
From https://github.com/libgit2/libgit2
* branch refs/pull/958/head -> FETCH_HEAD
~~~
這告訴 Git: “連接到 `origin` 這個 remote,下載名字為 `refs/pull/958/head` 的引用。”Git 高高興興去執行,下載構建那個引用需要的所有內容,然后把指針指向 `.git/FETCH_HEAD` 下面你想要的提交記錄。然后你可以用 `git merge FETCH_HEAD` 把它合并到你想進行測試的分支,但那個合并的提交信息看起來有點怪。然而,如果你需要審查 **一大批** 合并請求,這樣操作會很麻煩。
還有一種方法可以抓取 *所有的* 合并請求,并且在你連接到遠程(remote)的時候保持更新。用你最喜歡的編輯器打開 `.git/config` ,查找 `origin` 遠程(remote)。看起來差不多像下面這樣:
~~~
[remote "origin"]
url = https://github.com/libgit2/libgit2
fetch = +refs/heads/*:refs/remotes/origin/*
~~~
以 `fetch =` 開頭的行是一個 “refspec.”它是一種把 remote 的名稱映射到你本地 `.git` 目錄的方法。這一條(就是上面的這一條)告訴 Git,“remote 上 `refs/heads` 下面的內容在我本地版本庫中都放在 `refs/remotes/origin` 。”你可以把這一段修改一下,添加另一個 refspec:
~~~
[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
# …
~~~
現在所有的合并請求在本地像分支一樣展現,它們是只讀的,當你執行抓取時它們也會更新。這讓在本地測試合并請求中的代碼變得超級簡單:
~~~
$ 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'
~~~
你的鷹眼系統會發現在 refspec 的 remote 部分的結尾有個 `head` 。在 GitHub 那邊也有一個 `refs/pull/#/merge` 引用,它代表的是如果你在網站上按了 “merge” 按鈕對應的提交記錄。這甚至讓你可以在按按鈕之前就測試這個合并。
### 合并請求之上的合并請求
你不僅可以在主分支或者說 `master` 分支上開啟合并請求,實際上你可以在網絡上的任何一個分支上開啟合并請求。其實,你甚至可以在另一個合并請求上開啟一個合并請求。
如果你看到一個合并請求在向正確的方向發展,然后你想在這個合并請求上做一些修改或者你不太確定這是個好主意,或者你沒有目標分支的推送權限,你可以直接在合并請求上開啟一個合并請求。
當你開啟一個合并請求時,在頁面的頂端有一個框框顯示你要合并到哪個分支和你從哪個分支合并過來的。如果你點擊那個框框右邊的 “Edit” 按鈕,你不僅可以改變分支,還可以選擇哪個 fork。

Figure 6-37. 手工修改合并請求的目標.
這里你可以很簡單地指明合并你的分支到哪一個合并請求或 fork。
## 提醒和通知
GitHub 內置了一個很好的通知系統,當你需要與別人或別的團隊交流時用起來很方便。
在任何評論中你可以先輸入一個`@`,系統會自動補全項目中合作者或貢獻者的名字和用戶名。

Figure 6-38. 輸入 @ 來提醒某人.
你也可以提醒不在列表中的用戶,但是通常自動補全用起更快。
當你發布了一個帶用戶提醒的評論,那個用戶會收到通知。這意味著把人們拉進會話中要比讓他們投票有效率得多。對于 GitHub 上的合并請求,人們經常把他們團隊或公司中的其它人拉來審查問題或合并請求。
如果有人收到了合并請求或問題的提醒,他們會"訂閱"它,后面有新的活動發生他們都會持續收到提醒。如果你是合并請求或者問題的發起方你也會被訂閱上,比如你在關注一個版本庫或者你評論了什么東西。如果你不想再收到提醒,在頁面上有個 “Unsubscribe” 按鈕,點一下就不會再收到更新了。

Figure 6-39. 取消訂閱一個問題或合并請求.
### 通知頁面
當我們在這提到特指 GitHub 的 “notifications” ,指的是當 GitHub 上有事件發生時,它通知你的方式,這里有幾種不同的方式來配置它們。如果你打開配置頁面的 “Notification center” 標簽,你可以看到一些選項。

Figure 6-40. 通知中心選項.
有兩個選項,通過"郵件(Email)"和通過"網頁(Web)",你可以選用一個或者都不選或者都選。
### 網頁通知
網頁通知只在 GitHub 上存在,你也只能在 GitHub 上查看。如果你打開了這個選項并且有一個你的通知,你會在你屏幕上方的通知圖標上看到一個小藍點。參見 [Figure?6-41](#)。

Figure 6-41. 通知中心.
如果你點擊那個玩意兒,你會看到你被通知到的所有條目,按照項目分好了組。你可以點擊左邊欄的項目名字來過濾項目相關的通知。你可以點擊通知旁邊的對號圖標把通知標為已讀,或者點擊組上面的圖標把項目中 **所有的** 通知標為已讀。在每個對號圖標旁邊都有一個靜音按鈕,你可以點一下,以后就不會收到它相關的通知。
所有這些工具對于處理大量通知非常有用。很多 GitHub 資深用戶都關閉郵件通知,在這個頁面上處理他們所有的通知。
### 郵件通知
郵件通知是你處理 GitHub 通知的另一種方式。如果你打開這個選項,每當有通知時,你會收到一封郵件。我們在 [Figure?6-13](#) 和 [Figure?6-34](#) 看到了一些例子。郵件也會被合適地按話題組織在一起,如果你使用一個具有會話功能的郵件客戶端那會很方便。
GitHub 在發送給你的郵件頭中附帶了很多元數據,這對于設置過濾器和郵件規則非常有幫助。
舉個例子,我們來看一看在 [Figure?6-34](#) 中發給 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>` 的格式展現所有的數據。例如,如果這是一個問題(issue),那么 `<type>` 字段就會是 “issues” 而不是 “pull” 。
`List-Post` 和 `List-Unsubscribe` 字段表示如果你的郵件客戶端能夠處理這些,那么你可以很容易地在列表中發貼或取消對這個相關帖子的訂閱。那會很有效率,就像在頁面中點擊靜音按鈕或在問題/合并請求頁面點擊 “Unsubscribe” 一樣。
值得注意的是,如果你同時打開了郵件和網頁通知,那么當你在郵件客戶端允許加載圖片的情況下閱讀郵件通知時,對應的網頁通知也將會同時被標記為已讀。
### 特殊文件
如果你的版本庫中有一些特殊文件,GitHub 會提醒你。
### README
第一個就是 `README` 文件,可以是幾乎任何 GitHub 可以識別的格式。例如,它可以是 `README` ,`README.md` , `README.asciidoc` 。如果 GitHub 在你的版本庫中找到 README 文件,會把它在項目的首頁渲染出來。
很多團隊在這個文件里放版本庫或項目新人需要了解的所有相關的信息。它一般包含這些內容:
-
該項目的作用
-
如何配置與安裝
-
有關如何使用和運行的例子
-
項目的許可證
-
如何向項目貢獻力量
因為 GitHub 會渲染這個文件,你可以在文件里植入圖片或鏈接讓它更容易理解。
### 貢獻 CONTRIBUTING
另一個 GitHub 可以識別的特殊文件是 `CONTRIBUTING` 。如果你有一個任意擴展名的 `CONTRIBUTING` 文件,當有人開啟一個合并請求時 GitHub 會顯示 [Figure?6-42](#)。

Figure 6-42. 開啟合并請求時有 CONTRIBUTING 文件存在.
這個的作用就是你可以在這里指出對于你的項目開啟的合并請求你想要的/不想要的各種事情。這樣別人在開啟合并請求之前可以讀到這些指導方針。
### 項目管理
對于一個單個項目其實沒有很多管理事務要做,但也有幾點有趣的。
### 改變默認分支
如果你想用 “master” 之外的分支作為你的默認分支,其他人將默認會在這個分支上開啟合并請求或進行瀏覽,你可以在你版本庫的設置頁面的 “options” 標簽下修改。

Figure 6-43. 改變項目的默認分支.
簡單地改變默認分支下拉列表中的選項,它就會作為所有主要操作的默認分支,他人進行克隆時該分支也將被默認檢出。
### 移交項目
如果你想把一個項目移交給 GitHub 中的另一個人或另一個組織,還是設置頁面的這個 "options"標簽下有一個 “Transfer ownership” 選項可以用來干這個。

Figure 6-44. 把項目移交給另一個 GitHub 用戶或組織。
當你正準備放棄一個項目且正好有別人想要接手時,或者你的項目壯大了想把它移到一個組織里時,這就管用了。
這么做不僅會把版本庫連帶它所有的觀察和星標數都移到另一個地方,它還會將你的 URL 重定向到新的位置。它也重定向了來自 Git 的克隆和抓取,而不僅僅是網頁端請求。
- 前言
- Scott Chacon 序
- Ben Straub 序
- 獻辭
- 貢獻者
- 引言
- 1. 起步
- 1.1 關于版本控制
- 1.2 Git 簡史
- 1.3 Git 基礎
- 1.4 命令行
- 1.5 安裝 Git
- 1.6 初次運行 Git 前的配置
- 1.7 獲取幫助
- 1.8 總結
- 2. Git 基礎
- 2.1 獲取 Git 倉庫
- 2.2 記錄每次更新到倉庫
- 2.3 查看提交歷史
- 2.4 撤消操作
- 2.5 遠程倉庫的使用
- 2.6 打標簽
- 2.7 Git 別名
- 2.8 總結
- 3. Git 分支
- 3.1 分支簡介
- 3.2 分支的新建與合并
- 3.3 分支管理
- 3.4 分支開發工作流
- 3.5 遠程分支
- 3.6 變基
- 3.7 總結
- 4. 服務器上的 Git
- 4.1 協議
- 4.2 在服務器上搭建 Git
- 4.3 生成 SSH 公鑰
- 4.4 配置服務器
- 4.5 Git 守護進程
- 4.6 Smart HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 第三方托管的選擇
- 4.10 總結
- 5. 分布式 Git
- 5.1 分布式工作流程
- 5.2 向一個項目貢獻
- 5.3 維護項目
- 5.4 總結
- 6. GitHub
- 6.1 賬戶的創建和配置
- 6.2 對項目做出貢獻
- 6.3 維護項目
- 6.4 管理組織
- 6.5 腳本 GitHub
- 6.6 總結
- 7. Git 工具
- 7.1 選擇修訂版本
- 7.2 交互式暫存
- 7.3 儲藏與清理
- 7.4 簽署工作
- 7.5 搜索
- 7.6 重寫歷史
- 7.7 重置揭密
- 7.8 高級合并
- 7.9 Rerere
- 7.10 使用 Git 調試
- 7.11 子模塊
- 7.12 打包
- 7.13 替換
- 7.14 憑證存儲
- 7.15 總結
- 8. 自定義 Git
- 8.1 配置 Git
- 8.2 Git 屬性
- 8.3 Git 鉤子
- 8.4 使用強制策略的一個例子
- 8.5 總結
- 9. Git 與其他系統
- 9.1 作為客戶端的 Git
- 9.2 遷移到 Git
- 9.3 總結
- 10. Git 內部原理
- 10.1 底層命令和高層命令
- 10.2 Git 對象
- 10.3 Git 引用
- 10.4 包文件
- 10.5 引用規格
- 10.6 傳輸協議
- 10.7 維護與數據恢復
- 10.8 環境變量
- 10.9 總結
- A. 其它環境中的 Git
- A1.1 圖形界面
- A1.2 Visual Studio 中的 Git
- A1.3 Eclipse 中的 Git
- A1.4 Bash 中的 Git
- A1.5 Zsh 中的 Git
- A1.6 Powershell 中的 Git
- A1.7 總結
- B. 將 Git 嵌入你的應用
- A2.1 命令行 Git 方式
- A2.2 Libgit2
- A2.3 JGit
- C. Git 命令
- A3.1 設置與配置
- A3.2 獲取與創建項目
- A3.3 快照基礎
- A3.4 分支與合并
- A3.5 項目分享與更新
- A3.6 檢查與比較
- A3.7 調試
- A3.8 補丁
- A3.9 郵件
- A3.10 外部系統
- A3.11 管理
- A3.12 底層命令