-
1. 起步
-
2. Git 基礎
-
3. Git 分支
-
4. 伺服器上的 Git
- 4.1 協議
- 4.2 在伺服器上部署 Git
- 4.3 生成 SSH 公鑰
- 4.4 架設伺服器
- 4.5 Git Daemon
- 4.6 Smart HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 第三方託管服務
- 4.10 小結
-
5. 分散式 Git
-
A1. 附錄 A: Git 在其他環境
- A1.1 圖形介面
- A1.2 Visual Studio 中的 Git
- A1.3 Visual Studio Code 中的 Git
- A1.4 IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine 中的 Git
- A1.5 Sublime Text 中的 Git
- A1.6 Bash 中的 Git
- A1.7 Zsh 中的 Git
- A1.8 PowerShell 中的 Git
- A1.9 小結
-
A2. 附錄 B: 在應用程式中嵌入 Git
-
A3. 附錄 C: Git 命令
3.5 Git 分支 - 遠端分支
遠端分支
遠端引用是你遠端倉庫中的引用(指標),包括分支、標籤等等。你可以透過 `git ls-remote
遠端跟蹤分支是遠端分支狀態的引用。它們是不能手動移動的本地引用;每當你進行網路通訊時,Git 會自動移動它們,以確保它們準確地表示遠端倉庫的狀態。你可以把它們看作書籤,提醒你上次連線到遠端倉庫時分支的位置。
遠端跟蹤分支的命名形式為 `
這可能有點令人困惑,所以我們來看一個例子。假設你的網路上有一個 Git 伺服器,地址是 `git.ourcompany.com`。如果你從它克隆,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` 作為你的預設遠端分支。 |

如果你在本地 `master` 分支上進行了一些工作,與此同時,其他人推送到了 `git.ourcompany.com` 並更新了它的 `master` 分支,那麼你們的歷史就會以不同的方式向前發展。此外,只要你沒有與 `origin` 伺服器聯絡,你的 `origin/master` 指標就不會移動。

要將你的工作與給定的遠端倉庫同步,你可以執行 `git fetch

為了演示擁有多個遠端伺服器以及這些遠端專案的遠端分支是什麼樣子,假設你還有另一個內部 Git 伺服器,僅供你的一個衝刺團隊開發使用。該伺服器位於 `git.team1.ourcompany.com`。你可以透過執行 `git remote add` 命令將其新增為當前正在處理的專案的新的遠端引用,正如我們在Git 基礎中介紹的那樣。將此遠端倉庫命名為 `teamone`,這將是該完整 URL 的簡稱。

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

推送
當你想與他人共享一個分支時,你需要將其推送到一個你擁有寫入許可權的遠端倉庫。你的本地分支不會自動同步到你寫入的遠端倉庫——你必須顯式地推送你想要共享的分支。這樣,你可以使用私有分支進行不希望共享的工作,並只推送你希望協作的主題分支。
如果你有一個名為 `serverfix` 的分支,想和他人一起工作,你可以用和推送第一個分支相同的方式推送它。執行 `git push
$ 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` 輕鬆設定。 有關各種可用憑證快取選項的更多資訊,請參閱憑證儲存。 |
下次你的某個協作者從伺服器拉取時,他們會在遠端分支 `origin/serverfix` 下獲得對伺服器版本 `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
需要注意的是,當你執行 `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'
這會給你一個本地分支,你可以基於 `origin/serverfix` 開始工作。
跟蹤分支
從遠端跟蹤分支檢出一個本地分支會自動建立一個所謂的“跟蹤分支”(它所跟蹤的分支稱為“上游分支”)。跟蹤分支是與遠端分支有直接關係的本地分支。如果你在一個跟蹤分支上並輸入 `git pull`,Git 會自動知道要從哪個伺服器獲取以及要合併哪個分支。
當你克隆一個倉庫時,它通常會自動建立一個跟蹤 `origin/master` 的 `master` 分支。然而,如果你願意,你可以設定其他跟蹤分支——那些跟蹤其他遠端倉庫上分支的,或者不跟蹤 `master` 分支的。最簡單的情況就是你剛剛看到的例子,執行 `git checkout -b
$ 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`,並且“領先”兩個提交,這意味著我們本地有兩個提交尚未推送到伺服器。我們還可以看到我們的 `master` 分支正在跟蹤 `origin/master` 並且是最新的。接下來我們可以看到我們的 `serverfix` 分支正在跟蹤 `teamone` 伺服器上的 `server-fix-good` 分支,並且領先三個提交,落後一個提交,這意味著伺服器上有一個我們尚未合併的提交,以及三個我們尚未推送的本地提交。最後,我們可以看到我們的 `testing` 分支沒有跟蹤任何遠端分支。
需要注意的是,這些數字僅是你上次從各個伺服器拉取以來的情況。此命令不會連線到伺服器,它只是告訴你本地快取的這些伺服器上的資訊。如果你想要完全最新的領先和落後數字,你需要在此命令執行之前從所有遠端倉庫拉取。
$ git fetch --all; git branch -vv
拉取
雖然 `git fetch` 命令會獲取伺服器上你尚未擁有的所有更改,但它根本不會修改你的工作目錄。它只會為你獲取資料,並讓你自己合併。然而,有一個名為 `git pull` 的命令,它在大多數情況下本質上是緊隨其後的 `git fetch` 和 `git merge` 的組合。如果你按照上一節的演示設定了跟蹤分支,無論是顯式設定還是由 `clone` 或 `checkout` 命令為你建立,`git pull` 都會查詢當前分支正在跟蹤哪個伺服器和分支,從該伺服器獲取資料,然後嘗試合併該遠端分支。
刪除遠端分支
假設你完成了對一個遠端分支的工作——比如說你和你的協作者完成了某個功能,並已將其合併到你遠端倉庫的 `master` 分支(或你的穩定程式碼行所在的分支)中。你可以使用 `git push` 命令的 `--delete` 選項來刪除遠端分支。如果你想從伺服器刪除你的 `serverfix` 分支,可以執行以下命令:
$ git push origin --delete serverfix
To https://github.com/schacon/simplegit
- [deleted] serverfix
基本上,所有這些操作都是從伺服器上移除指標。Git 伺服器通常會將資料保留一段時間,直到垃圾回收執行,所以如果意外刪除了,通常很容易恢復。