遠程分支(remote branch)是對遠程倉庫中的分支的索引。它們是一些無法移動的本地分支;只有在 Git 進行網絡交互時才會更新。遠程分支就像是書簽,提醒著你上次連接遠程倉庫時上面各分支的位置。
我們用 (遠程倉庫名)/(分支名) 這樣的形式表示遠程分支。比如我們想看看上次同 origin 倉庫通訊時 master 分支的樣子,就應該查看 origin/master 分支。如果你和同伴一起修復某個問題,但他們先推送了一個 iss53 分支到遠程倉庫,雖然你可能也有一個本地的 iss53 分支,但指向服務器上最新更新的卻應該是 origin/iss53 分支。
可能有點亂,我們不妨舉例說明。假設你們團隊有個地址為 git.ourcompany.com 的 Git 服務器。如果你從這里克隆,Git 會自動為你將此遠程倉庫命名為 origin,并下載其中所有的數據,建立一個指向它的 master 分支的指針,在本地命名為 origin/master,但你無法在本地更改其數據。接著,Git 建立一個屬于你自己的本地 master 分支,始于 origin 上 master 分支相同的位置,你可以就此開始工作(見圖 3-22):

圖 3-22. 一次 Git 克隆會建立你自己的本地分支 master 和遠程分支 origin/master,并且將它們都指向 origin 上的 master 分支。
如果你在本地 master 分支做了些改動,與此同時,其他人向 git.ourcompany.com 推送了他們的更新,那么服務器上的 master 分支就會向前推進,而與此同時,你在本地的提交歷史正朝向不同方向發展。不過只要你不和服務器通訊,你的 origin/master 指針仍然保持原位不會移動(見圖 3-23)。

圖 3-23. 在本地工作的同時有人向遠程倉庫推送內容會讓提交歷史開始分流。
可以運行 `git fetch origin` 來同步遠程服務器上的數據到本地。該命令首先找到 origin 是哪個服務器(本例為 git.ourcompany.com),從上面獲取你尚未擁有的數據,更新你本地的數據庫,然后把 origin/master 的指針移到它最新的位置上(見圖 3-24)。

圖 3-24. git fetch 命令會更新 remote 索引。
為了演示擁有多個遠程分支(在不同的遠程服務器上)的項目是如何工作的,我們假設你還有另一個僅供你的敏捷開發小組使用的內部服務器 git.team1.ourcompany.com。可以用第二章中提到的 `git remote add` 命令把它加為當前項目的遠程分支之一。我們把它命名為 teamone,以便代替完整的 Git URL 以方便使用(見圖 3-25)。

圖 3-25. 把另一個服務器加為遠程倉庫
現在你可以用 `git fetch teamone` 來獲取小組服務器上你還沒有的數據了。由于當前該服務器上的內容是你 origin 服務器上的子集,Git 不會下載任何數據,而只是簡單地創建一個名為 teamone/master 的遠程分支,指向 teamone 服務器上 master 分支所在的提交對象 31b8e(見圖 3-26)。

圖 3-26. 你在本地有了一個指向 teamone 服務器上 master 分支的索引。
## 推送本地分支
要想和其他人分享某個本地分支,你需要把它推送到一個你擁有寫權限的遠程倉庫。你創建的本地分支不會因為你的寫入操作而被自動同步到你引入的遠程服務器上,你需要明確地執行推送分支的操作。換句話說,對于無意分享的分支,你盡管保留為私人分支好了,而只推送那些協同工作要用到的特性分支。
如果你有個叫 serverfix 的分支需要和他人一起開發,可以運行 `git push (遠程倉庫名) (分支名)`:
~~~
$ git push origin serverfix
Counting objects: 20, done.
Compressing objects: 100% (14/14), done.
Writing objects: 100% (15/15), 1.74 KiB, done.
Total 15 (delta 5), reused 0 (delta 0)
To git@github.com:schacon/simplegit.git
* [new branch] serverfix -> serverfix
~~~
這里其實走了一點捷徑。Git 自動把 serverfix 分支名擴展為 `refs/heads/serverfix:refs/heads/serverfix`,意為“取出我在本地的 serverfix 分支,推送到遠程倉庫的 serverfix 分支中去”。我們將在第九章進一步介紹 `refs/heads/` 部分的細節,不過一般使用的時候都可以省略它。也可以運行 `git push origin serverfix:serverfix` 來實現相同的效果,它的意思是“上傳我本地的 serverfix 分支到遠程倉庫中去,仍舊稱它為 serverfix 分支”。通過此語法,你可以把本地分支推送到某個命名不同的遠程分支:若想把遠程分支叫作 awesomebranch,可以用 `git push origin serverfix:awesomebranch` 來推送數據。
接下來,當你的協作者再次從服務器上獲取數據時,他們將得到一個新的遠程分支 origin/serverfix,并指向服務器上 serverfix 所指向的版本:
~~~
$ git fetch origin
remote: Counting objects: 20, done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 15 (delta 5), reused 0 (delta 0)
Unpacking objects: 100% (15/15), done.
From git@github.com:schacon/simplegit
* [new branch] serverfix -> origin/serverfix
~~~
值得注意的是,在 fetch 操作下載好新的遠程分支之后,你仍然無法在本地編輯該遠程倉庫中的分支。換句話說,在本例中,你不會有一個新的 serverfix 分支,有的只是一個你無法移動的 origin/serverfix 指針。
如果要把該遠程分支的內容合并到當前分支,可以運行 `git merge origin/serverfix`。如果想要一份自己的 serverfix 來開發,可以在遠程分支的基礎上分化出一個新的分支來:
~~~
$ git checkout -b serverfix origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'
~~~
這會切換到新建的 serverfix 本地分支,其內容同遠程分支 origin/serverfix 一致,這樣你就可以在里面繼續開發了。
## 跟蹤遠程分支
從遠程分支 checkout 出來的本地分支,稱為 跟蹤分支 (tracking branch)。跟蹤分支是一種和某個遠程分支有直接聯系的本地分支。在跟蹤分支里輸入 `git push`,Git 會自行推斷應該向哪個服務器的哪個分支推送數據。同樣,在這些分支里運行 `git pull` 會獲取所有遠程索引,并把它們的數據都合并到本地分支中來。
在克隆倉庫時,Git 通常會自動創建一個名為 master 的分支來跟蹤 origin/master。這正是 `git push` 和 `git pull` 一開始就能正常工作的原因。當然,你可以隨心所欲地設定為其它跟蹤分支,比如 origin 上除了 master 之外的其它分支。剛才我們已經看到了這樣的一個例子:`git checkout -b [分支名] [遠程名]/[分支名]`。如果你有 1.6.2 以上版本的 Git,還可以用 `--track` 選項簡化:
~~~
$ git checkout --track origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'
~~~
要為本地分支設定不同于遠程分支的名字,只需在第一個版本的命令里換個名字:
~~~
$ git checkout -b sf origin/serverfix
Branch sf set up to track remote branch serverfix from origin.
Switched to a new branch 'sf'
~~~
現在你的本地分支 sf 會自動將推送和抓取數據的位置定位到 origin/serverfix 了。
## 刪除遠程分支
如果不再需要某個遠程分支了,比如搞定了某個特性并把它合并進了遠程的 master 分支(或任何其他存放穩定代碼的分支),可以用這個非常無厘頭的語法來刪除它:`git push [遠程名] :[分支名]`。如果想在服務器上刪除 serverfix 分支,運行下面的命令:
~~~
$ git push origin :serverfix
To git@github.com:schacon/simplegit.git
- [deleted] serverfix
~~~
咚!服務器上的分支沒了。你最好特別留心這一頁,因為你一定會用到那個命令,而且你很可能會忘掉它的語法。有種方便記憶這條命令的方法:記住我們不久前見過的 `git push [遠程名] [本地分支]:[遠程分支]` 語法,如果省略 [本地分支],那就等于是在說“在這里提取空白然后把它變成[遠程分支]”。
- 1. 起步
- 1.1 關于版本控制
- 1.2 Git 簡史
- 1.3 Git 基礎
- 1.4 安裝 Git
- 1.5 初次運行 Git 前的配置
- 1.6 獲取幫助
- 1.7 小結
- 2. Git基礎
- 2.1 取得項目的 Git 倉庫
- 2.2 記錄每次更新到倉庫
- 2.3 查看提交歷史
- 2.4 撤消操作
- 2.5 遠程倉庫的使用
- 2.6 打標簽
- 2.7 技巧和竅門
- 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 公共訪問
- 4.6 GitWeb
- 4.7 Gitosis
- 4.8 Gitolite
- 4.9 Git 守護進程
- 4.10 Git 托管服務
- 4.11 小結
- 5. 分布式Git
- 5.1 分布式工作流程
- 5.2 為項目作貢獻
- 5.3 項目的管理
- 5.4 小結
- 6. Git工具
- 6.1 修訂版本(Revision)選擇
- 6.2 交互式暫存
- 6.3 儲藏(Stashing)
- 6.4 重寫歷史
- 6.5 使用 Git 調試
- 6.6 子模塊
- 6.7 子樹合并
- 6.8 總結
- 7. 自定義Git
- 7.1 配置 Git
- 7.2 Git屬性
- 7.3 Git掛鉤
- 7.4 Git 強制策略實例
- 7.5 總結
- 8. Git與其他系統
- 8.1 Git 與 Subversion
- 8.2 遷移到 Git
- 8.3 總結
- 9. Git 內部原理
- 9.2 Git 對象
- 9.3 Git References
- 9.4 Packfiles
- 9.5 The Refspec
- 9.6 傳輸協議
- 9.7 維護及數據恢復
- 9.8 總結
- 9.1 底層命令 (Plumbing) 和高層命令 (Porcelain)