遠程分支
遠程引用是對遠程倉庫的引用(指針),包括分支、標簽等等。 你可以通過 git ls-remote (remote)來顯式地獲得遠程引用的完整列表,或者通過 git remote show (remote) 獲得遠程分支的更多信息。 然而,一個更常見的做法是利用遠程跟蹤分支。
遠程跟蹤分支是遠程分支狀態的引用。 它們是你不能移動的本地引用,當你做任何網絡通信操作時,它們會自動移動。 遠程跟蹤分支像是你上次連接到遠程倉庫時,那些分支所處狀態的書簽。
它們以 (remote)/(branch) 形式命名。 例如,如果你想要看你最后一次與遠程倉庫 origin 通信時master 分支的狀態,你可以查看 origin/master 分支。 你與同事合作解決一個問題並且他們推送了一個 iss53 分支,你可能有自己的本地 iss53 分支;但是在服務器上的分支會指向 origin/iss53 的提交。
這可能有一點兒難以理解,讓我們來看一個例子。 假設你的網絡里有一個在 git.ourcompany.com 的 Git 服務器。 如果你從這里克隆,Git 的 clone 命令會為你自動將其命名為 origin,拉取它的所有數據,創建一個指向它的 master 分支的指針,並且在本地將其命名為 origin/master。 Git 也會給你一個與 origin 的 master 分支在指向同一個地方的本地 master 分支,這樣你就有工作的基礎。
NOTE
“origin” 並無特殊含義
遠程倉庫名字 “origin” 與分支名字 “master” 一樣,在 Git 中並沒有任何特別的含義一樣。 同時 “master” 是當你運行 git init 時默認的起始分支名字,原因僅僅是它的廣泛使用,“origin” 是當你運行 git clone 時默認的遠程倉庫名字。 如果你運行 git clone -o booyah,那么你默認的遠程分支名字將會是 booyah/master。
Figure 3-22. 克隆之后的服務器與本地倉庫
如果你在本地的 master 分支做了一些工作,然而在同一時間,其他人推送提交到git.ourcompany.com 並更新了它的 master 分支,那么你的提交歷史將向不同的方向前進。 也許,只要你不與 origin 服務器連接,你的 origin/master 指針就不會移動。
Figure 3-23. 本地與遠程的工作可以分叉
如果要同步你的工作,運行 git fetch origin 命令。 這個命令查找 “origin” 是哪一個服務器(在本例中,它是 git.ourcompany.com),從中抓取本地沒有的數據,並且更新本地數據庫,移動origin/master 指針指向新的、更新后的位置。
Figure 3-24. git fetch 更新你的遠程倉庫引用
為了演示有多個遠程倉庫與遠程分支的情況,我們假定你有另一個內部 Git 服務器,僅用於你的 sprint 小組的開發工作。 這個服務器位於 git.team1.ourcompany.com。 你可以運行 git remote add 命令添加一個新的遠程倉庫引用到當前的項目,這個命令我們會在 Git 基礎 中詳細說明。 將這個遠程倉庫命名為 teamone,將其作為整個 URL 的縮寫。
Figure 3-25. 添加另一個遠程倉庫
現在,可以運行 git fetch teamone 來抓取遠程倉庫 teamone 有而本地沒有的數據。 因為那台服務器上現有的數據是 origin 服務器上的一個子集,所以 Git 並不會抓取數據而是會設置遠程跟蹤分支teamone/master 指向 teamone 的 master 分支。
Figure 3-26. 遠程跟蹤分支 teamone/master
推送
當你想要公開分享一個分支時,需要將其推送到有寫入權限的遠程倉庫上。 本地的分支並不會自動與遠程倉庫同步 - 你必須顯式地推送想要分享的分支。 這樣,你就可以把不願意分享的內容放到私人分支上,而將需要和別人協作的內容推送到公開分支。
如果希望和別人一起在名為 serverfix 的分支上工作,你可以像推送第一個分支那樣推送它。 運行 git push (remote) (branch):
$git push origin serverfixCounting 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 分支。
NOTE
如何避免每次輸入密碼
如果你正在使用 HTTPS URL 來推送,Git 服務器會詢問用戶名與密碼。 默認情況下它會在終端中提示服務器是否允許你進行推送。
如果不想在每一次推送時都輸入用戶名與密碼,你可以設置一個 “credential cache”。 最簡單的方式就是將其保存在內存中幾分鍾,可以簡單地運行 git config --global credential.helper cache 來設置它。
想要了解更多關於不同驗證緩存的可用選項,查看 憑證存儲。
下一次其他協作者從服務器上抓取數據時,他們會在本地生成一個遠程分支 origin/serverfix,指向服務器的 serverfix 分支的引用:
$git fetch originremote: 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/serverfixBranch 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 [branch] [remotename]/[branch]。 這是一個十分常用的操作所以 Git 提供了 --track 快捷方式:
$git checkout --track origin/serverfixBranch serverfix set up to track remote branch serverfix from origin.Switched to a new branch 'serverfix'
如果想要將本地分支與遠程分支設置為不同名字,你可以輕松地增加一個不同名字的本地分支的上一個命令:
$git checkout -b sf origin/serverfixBranch sf set up to track remote branch serverfix from origin.Switched to a new branch 'sf'
現在,本地分支 sf 會自動從 origin/serverfix 拉取。
設置已有的本地分支跟蹤一個剛剛拉取下來的遠程分支,或者想要修改正在跟蹤的上游分支,你可以在任意時間使用 -u 或 --set-upstream-to 選項運行 git branch 來顯式地設置。
$git branch -u origin/serverfixBranch serverfix set up to track remote branch serverfix from origin.
NOTE
上游快捷方式
當設置好跟蹤分支后,可以通過 @{upstream} 或 @{u} 快捷方式來引用它。 所以在 master分支時並且它正在跟蹤 origin/master 時,如果願意的話可以使用 git merge @{u} 來取代git merge origin/master。
如果想要查看設置的所有跟蹤分支,可以使用 git branch 的 -vv 選項。 這會將所有的本地分支列出來並且包含更多的信息,如每一個分支正在跟蹤哪個遠程分支與本地分支是否是領先、落后或是都有。
$git branch -vviss53 7e424c3 [origin/iss53: ahead 2] forgot the bracketsmaster 1ae2a45 [origin/master] deploying index fix* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do ittesting 5ea463a trying something new
這里可以看到 iss53 分支正在跟蹤 origin/iss53 並且 “ahead” 是 2,意味着本地有兩個提交還沒有推送到服務器上。 也能看到 master 分支正在跟蹤 origin/master 分支並且是最新的。 接下來可以看到 serverfix 分支正在跟蹤 teamone 服務器上的 server-fix-good 分支並且領先 2 落后 1,意味着服務器上有一次提交還沒有合並入同時本地有三次提交還沒有推送。 最后看到 testing 分支並沒有跟蹤任何遠程分支。
需要重點注意的一點是這些數字的值來自於你從每個服務器上最后一次抓取的數據。 這個命令並沒有連接服務器,它只會告訴你關於本地緩存的服務器數據。 如果想要統計最新的領先與落后數字,需要在運行此命令前抓取所有的遠程倉庫。 可以像這樣做:$ git fetch --all; git branch -vv
拉取
當 git fetch 命令從服務器上抓取本地沒有的數據時,它並不會修改工作目錄中的內容。 它只會獲取數據然后讓你自己合並。 然而,有一個命令叫作 git pull 在大多數情況下它的含義是一個 git fetch 緊接着一個 git merge 命令。 如果有一個像之前章節中演示的設置好的跟蹤分支,不管它是顯式地設置還是通過 clone 或 checkout 命令為你創建的,git pull 都會查找當前分支所跟蹤的服務器與分支,從服務器上抓取數據然后嘗試合並入那個遠程分支。
由於 git pull 的魔法經常令人困惑所以通常單獨顯式地使用 fetch 與 merge 命令會更好一些。
刪除遠程分支
假設你已經通過遠程分支做完所有的工作了 - 也就是說你和你的協作者已經完成了一個特性並且將其合並到了遠程倉庫的 master 分支(或任何其他穩定代碼分支)。 可以運行帶有 --delete 選項的 git push命令來刪除一個遠程分支。 如果想要從服務器上刪除 serverfix 分支,運行下面的命令:
$git push origin --delete serverfixTo https://github.com/schacon/simplegit- [deleted] serverfix
基本上這個命令做的只是從服務器上移除這個指針。 Git 服務器通常會保留數據一段時間直到垃圾回收運行,所以如果不小心刪除掉了,通常是很容易恢復的。
