Git
章節 ▾ 第二版

3.5 Git 分支 - 遠端分支

遠端分支

遠端參考是遠端儲存庫中的參考(指標),包括分支、標籤等等。 您可以使用 git ls-remote <remote> 顯式地取得完整的遠端參考清單,或使用 git remote show <remote> 取得遠端分支以及更多資訊。 不過,更常見的方式是利用遠端追蹤分支。

遠端追蹤分支是對遠端分支狀態的參考。 它們是您無法移動的本機參考; 每當您進行任何網路通訊時,Git 會為您移動它們,以確保它們準確地代表遠端儲存庫的狀態。 將它們視為書籤,提醒您上次連線到遠端儲存庫時,它們的分支在哪裡。

遠端追蹤分支名稱採用 <remote>/<branch> 的形式。 例如,如果您想查看上次與 origin 遠端通訊時,master 分支的樣子,您會檢查 origin/master 分支。 如果您與夥伴合作處理一個問題,他們推送了 iss53 分支,您可能會擁有自己的本機 iss53 分支,但是伺服器上的分支將由遠端追蹤分支 origin/iss53 表示。

這可能有點令人困惑,讓我們來看一個例子。 假設您在網路上的 git.ourcompany.com 有一個 Git 伺服器。 如果您從這裡複製,Git 的 clone 命令會自動將其命名為 origin,下載所有資料,建立一個指向其 master 分支所在位置的指標,並在本地將其命名為 origin/master。 Git 也會給您自己的本機 master 分支,從與 origin 的 master 分支相同的位置開始,以便您有所依據。

注意
「origin」並非特殊

就像分支名稱「master」在 Git 中沒有任何特殊含義一樣,「origin」也沒有。 雖然「master」是您執行 git init 時預設的起始分支名稱,這也是它被廣泛使用的唯一原因,「origin」是您執行 git clone 時遠端的預設名稱。 如果您改為執行 git clone -o booyah,那麼您的預設遠端分支將會是 booyah/master

Server and local repositories after cloning
圖 30. 複製後的伺服器和本機儲存庫

如果您在本機 master 分支上進行一些工作,同時其他人推送至 git.ourcompany.com 並更新其 master 分支,那麼您的歷史記錄會以不同的方式前進。 此外,只要您與 origin 伺服器保持斷線,您的 origin/master 指標就不會移動。

Local and remote work can diverge
圖 31. 本機和遠端工作可能會分歧

要將您的工作與指定的遠端同步,您需要執行 git fetch <remote> 命令(在我們的例子中是 git fetch origin)。這個命令會查詢「origin」伺服器是哪個(在這個例子中,它是 git.ourcompany.com),從該伺服器擷取您尚未擁有的任何資料,並更新您的本機資料庫,將您的 origin/master 指標移動到新的、更為最新的位置。

`git fetch` updates your remote-tracking branches
圖 32. git fetch 更新您的遠端追蹤分支

為了示範擁有多個遠端伺服器,以及這些遠端專案的遠端分支看起來如何,讓我們假設您還有另一個內部 Git 伺服器,僅供您的某個衝刺團隊進行開發使用。此伺服器位於 git.team1.ourcompany.com。您可以透過執行 git remote add 命令,將其新增為您目前正在處理的專案的新遠端參考,如同我們在Git 基礎中所介紹的。將此遠端命名為 teamone,這將是該整個 URL 的簡稱。

Adding another server as a remote
圖 33. 將另一個伺服器新增為遠端

現在,您可以執行 git fetch teamone 來擷取遠端 teamone 伺服器上您尚未擁有的所有內容。因為該伺服器擁有的資料是您目前 origin 伺服器所擁有的資料的子集,所以 Git 不會擷取任何資料,但會設定一個名為 teamone/master 的遠端追蹤分支,指向 teamonemaster 分支所指向的 commit。

Remote-tracking branch for `teamone/master`
圖 34. teamone/master 的遠端追蹤分支

推送

當您想要與世界分享一個分支時,您需要將其推送到您具有寫入權限的遠端。您的本機分支不會自動同步到您寫入的遠端 — 您必須明確地推送您想要分享的分支。這樣一來,您可以使用私有分支來處理您不想分享的工作,並且只推送您想要協作的主題分支。

如果您有一個名為 serverfix 的分支,並且想要與他人協同工作,您可以像推送您的第一個分支一樣將其推送上去。執行 git push <remote> <branch>

$ git push origin serverfix
Counting objects: 24, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (24/24), 1.91 KiB | 0 bytes/s, done.
Total 24 (delta 2), reused 0 (delta 0)
To https://github.com/schacon/simplegit
 * [new branch]      serverfix -> serverfix

這是一個簡寫。Git 會自動將 serverfix 分支名稱展開為 refs/heads/serverfix:refs/heads/serverfix,這意味著,「將我的 serverfix 本機分支推送上去,以更新遠端的 serverfix 分支。」我們將在Git 內部原理中詳細介紹 refs/heads/ 的部分,但您通常可以省略它。您也可以執行 git push origin serverfix:serverfix,這會執行相同的操作 — 它表示「取得我的 serverfix 並使其成為遠端的 serverfix」。您可以使用這種格式將本機分支推送到名稱不同的遠端分支。如果您不希望遠端上的分支被稱為 serverfix,您可以改為執行 git push origin serverfix:awesomebranch,將您的本機 serverfix 分支推送到遠端專案上的 awesomebranch 分支。

注意
不要每次都輸入您的密碼

如果您使用 HTTPS URL 來推送,Git 伺服器會要求您輸入使用者名稱和密碼進行身份驗證。預設情況下,它會在終端機上提示您輸入此資訊,以便伺服器可以判斷您是否被允許推送。

如果您不想每次推送都輸入密碼,您可以設定「憑證快取」。最簡單的方法是將其在記憶體中保留幾分鐘,您可以透過執行 git config --global credential.helper cache 輕鬆設定。

如需更多關於可用憑證快取選項的資訊,請參閱憑證儲存

下次您的合作者從伺服器擷取時,他們會獲得一個參考,指出伺服器版本的 serverfix 位於遠端分支 origin/serverfix 下方。

$ git fetch origin
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://github.com/schacon/simplegit
 * [new branch]      serverfix    -> origin/serverfix

重要的是要注意,當您執行擷取,帶下新的遠端追蹤分支時,您不會自動擁有它們的本機、可編輯副本。換句話說,在這個例子中,您沒有新的 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'

這會給您一個可以工作的本機分支,它從 origin/serverfix 所在的位置開始。

追蹤分支

從遠端追蹤分支檢出本機分支會自動建立所謂的「追蹤分支」(而它追蹤的分支稱為「上游分支」)。追蹤分支是與遠端分支有直接關係的本機分支。如果您在追蹤分支上並輸入 git pull,Git 會自動知道要從哪個伺服器擷取以及要合併哪個分支。

當您複製一個儲存庫時,它通常會自動建立一個追蹤 origin/mastermaster 分支。但是,如果您願意,您可以設定其他追蹤分支 — 追蹤其他遠端分支的分支,或者不追蹤 master 分支的分支。簡單的情況是您剛才看到的範例,執行 git checkout -b <branch> <remote>/<branch>。這是一個很常見的操作,因此 Git 提供了 --track 簡寫

$ git checkout --track origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'

事實上,這是如此常見,以至於對這個簡寫還有一個簡寫。如果您嘗試檢出的分支名稱 (a) 不存在,並且 (b) 與只有一個遠端上的名稱完全匹配,Git 會為您建立一個追蹤分支

$ git checkout 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 拉取。

如果您已經有一個本機分支,並且想要將其設定為您剛才拉取的遠端分支,或者想要變更您正在追蹤的上游分支,您可以使用 git branch-u--set-upstream-to 選項,隨時明確地設定它。

$ git branch -u origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
注意
上游簡寫

當您設定了追蹤分支時,您可以使用 @{upstream}@{u} 簡寫來參考其上游分支。因此,如果您在 master 分支上,並且它正在追蹤 origin/master,如果您願意,您可以說類似 git merge @{u} 而不是 git merge origin/master 的語句。

如果您想查看您設定了哪些追蹤分支,您可以使用 git branch-vv 選項。這將列出您的本機分支,並提供更多資訊,包括每個分支正在追蹤的內容,以及您的本機分支是否領先、落後或同時領先和落後。

$ git branch -vv
  iss53     7e424c3 [origin/iss53: ahead 2] Add forgotten brackets
  master    1ae2a45 [origin/master] Deploy index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] This should do it
  testing   5ea463a Try something new

因此,在這裡我們可以發現我們的 iss53 分支正在追蹤 origin/iss53,並且「領先」了兩個 commit,這意味著我們在本機上有兩個尚未推送到伺服器的 commit。我們還可以發現我們的 master 分支正在追蹤 origin/master,並且是最新的。接下來,我們可以發現我們的 serverfix 分支正在追蹤我們 teamone 伺服器上的 server-fix-good 分支,並且領先三個 commit,落後一個 commit,這意味著伺服器上有一個我們尚未合併的 commit,並且在本機上有三個我們尚未推送的 commit。最後,我們可以發現我們的 testing 分支沒有追蹤任何遠端分支。

重要的是要注意,這些數字僅是自您上次從每個伺服器擷取以來的數字。此命令不會連線到伺服器,它會告訴您它從這些伺服器在本機快取的內容。如果您想要完全最新的領先和落後數字,您需要在執行此命令之前從所有遠端擷取。您可以這樣做

$ git fetch --all; git branch -vv

拉取

雖然 git fetch 命令會擷取伺服器上您尚未擁有的所有變更,但它根本不會修改您的工作目錄。它只會為您取得資料,並讓您自行合併。但是,有一個命令叫做 git pull,它本質上是在大多數情況下緊接著 git mergegit fetch。如果您如上一節所示設定了追蹤分支,無論是透過明確設定還是由 clonecheckout 命令為您建立的,git pull 都會查詢您目前分支正在追蹤的伺服器和分支,從該伺服器擷取,然後嘗試合併該遠端分支。

通常,最好只是明確地使用 fetchmerge 命令,因為 git pull 的神奇之處通常會讓人感到困惑。

刪除遠端分支

假設您已完成遠端分支 — 例如您和您的合作者已完成某個功能,並將其合併到您遠端的 master 分支(或您的穩定程式碼所在的任何分支)。您可以使用 git push--delete 選項來刪除遠端分支。如果您想要從伺服器刪除您的 serverfix 分支,請執行以下操作

$ git push origin --delete serverfix
To https://github.com/schacon/simplegit
 - [deleted]         serverfix

基本上,所有這一切都是從伺服器中移除指標。Git 伺服器通常會將資料保留在那裡一段時間,直到執行垃圾收集,因此如果意外刪除,通常很容易恢復。

scroll-to-top