Git 沙盒模擬實戰(遠程篇)

Git 沙盒模擬實戰(遠程篇)

>---基礎篇html

遠程倉庫

遠程倉庫並不複雜, 在現在的雲計算盛行的世界很容易把遠程倉庫想象成一個富有魔力的東西, 但實際上它們只是你的倉庫在另個一臺計算機上的拷貝。你能夠經過因特網與這臺計算機通訊 —— 也就是增長或是獲取提交記錄git

話雖如此, 遠程倉庫卻有一系列強大的特性github

  • 首先也是最重要的的點, 遠程倉庫是一個強大的備份。本地倉庫也有恢復文件到指定版本的能力, 但全部的信息都是保存在本地的。有了遠程倉庫之後,即便丟失了本地全部數據, 你仍能夠經過遠程倉庫拿回你丟失的數據。
  • 還有就是, 遠程讓代碼社交化了! 既然你的項目被託管到別的地方了, 你的朋友能夠更容易地爲你的項目作貢獻(或者拉取最新的變動)

如今用網站來對遠程倉庫進行可視化操做變得愈加流行了(像 Github ), 但遠程倉庫永遠是這些工具的頂樑柱, 所以理解其概念很是的重要!shell


使用clone命令將遠程倉庫中的項目克隆到本地。ide

$ git clone [remoteName]

remoteName : 遠程倉庫的地址(名稱)工具

Git Fetch

Git 遠程倉庫至關的操做實際能夠概括爲兩點:向遠程倉庫傳輸數據以及從遠程倉庫獲取數據。既然咱們能與遠程倉庫同步,那麼就能夠分享任何能被 Git 管理的更新(所以能夠分享代碼、文件、想法、情書等等)。學習

本節課咱們將學習如何從遠程倉庫獲取數據 —— 命令如其名,它就是 git fetch測試

你會看到當咱們從遠程倉庫獲取數據時, 遠程分支也會更新以反映最新的遠程倉庫。在上一了咱們已經說起過這一點了。fetch

image-20210119114118304

虛線爲遠程倉庫,實線爲本地倉庫。網站

$ git fetch

image-20210119114211342

git fetch 作了些什麼

git fetch 完成了僅有的可是很重要的兩步:

  • 從遠程倉庫下載本地倉庫中缺失的提交記錄
  • 更新遠程分支指針(如 o/master)

git fetch 實際上將本地倉庫中的遠程分支更新成了遠程倉庫相應分支最新的狀態。

若是你還記得上一節課程中咱們說過的,遠程分支反映了遠程倉庫在你最後一次與它通訊時的狀態,git fetch 就是你與遠程倉庫通訊的方式了!但願我說的夠明白了,你已經瞭解 git fetch 與遠程分支之間的關係了吧。

git fetch 一般經過互聯網(使用 http://git:// 協議) 與遠程倉庫通訊。

git fetch 不會作的事

git fetch不會改變你本地倉庫的狀態。它不會更新你的 master 分支,也不會修改你磁盤上的文件。

理解這一點很重要,由於許多開發人員誤覺得執行了 git fetch 之後,他們本地倉庫就與遠程倉庫同步了。它可能已經將進行這一操做所需的全部數據都下載了下來,可是並無修改你本地的文件。咱們在後面的課程中將會講解能完成該操做的命令。

因此, 你能夠將 git fetch 的理解爲單純的下載操做。

Git Pull

既然咱們已經知道了如何用 git fetch 獲取遠程的數據, 如今咱們學習如何將這些變化更新到咱們的工做當中。

其實有不少方法的 —— 當遠程分支中有新的提交時,你能夠像合併本地分支那樣來合併遠程分支。也就是說就是你能夠執行如下命令:

  • git cherry-pick o/master
  • git rebase o/master
  • git merge o/master
  • 等等

實際上,因爲先抓取更新再合併到本地分支這個流程很經常使用,所以 Git 提供了一個專門的命令來完成這兩個操做。它就是咱們要講的 git pull

image-20210120104624095

$ git pull

image-20210120104640123

git pull 就是 git fetchgit merge <just-fetched-branch> 的縮寫!

模擬團隊合做

這裏有一件棘手的事 —— 爲了接下來的課程, 咱們須要先教你如何製造遠程倉庫的變動。

這意味着,咱們須要「僞裝」你的同事、朋友、合做夥伴更新了遠程倉庫,有多是某個特定的分支,或是幾個提交記錄。

爲了作到這點,咱們引入一個自造命令 git fakeTeamwork!它的名稱已經說明了一切,先看演示..

image-20210120104701712

$ git clone

local branch "master" set to track remote branch "o/master"

$ git commit -m "c2"

$ git commit -m "c3"

$ git push

$ git checkout c1

$ git commit -m "c4"

警告!如今是分離 HEAD 狀態

$ git checkout master

$ git merge c4

image-20210120104712094

Git Push

OK,咱們已經學過了如何從遠程倉庫獲取更新併合併到本地的分支當中。這很是棒……可是我如何與你們分享個人成果呢?

嗯,上傳本身分享內容與下載他人的分享恰好相反,那與 git pull 相反的命令是什麼呢?git push

git push 負責將你的變動上傳到指定的遠程倉庫,並在遠程倉庫上合併你的新提交記錄。一旦 git push 完成, 你的朋友們就能夠從這個遠程倉庫下載你分享的成果了!

你能夠將 git push 想象成發佈你成果的命令。它有許多應用技巧,稍後咱們會了解到,可是我們仍是先從基礎的開始吧……

注意 —— git push 不帶任何參數時的行爲與 Git 的一個名爲 push.default 的配置有關。它的默認值取決於你正使用的 Git 的版本,可是在教程中咱們使用的是 upstream。 這沒什麼太大的影響,可是在你的項目中進行推送以前,最好檢查一下這個配置。

image-20210120104724490

$ git push

過去了, 遠程倉庫接收了 C2,遠程倉庫中的 master 分支也被更新到指向 C2 了,咱們的遠程分支 (``o/master`) 也一樣被更新了。全部的分支都同步了!

image-20210120104748698

衝突處理

image-20210120104759464

git push 失敗是由於你最新提交的 C3 基於遠程分支中的 C1。而遠程倉庫中該分支已經更新到 C2 了,因此 Git 拒絕了你的推送請求。

$ git fakeTeamwork

$ git fetch

$ git commit -m "c3"

$ git rebase c2

$ git push

image-20210120104831530

git fetch 更新了本地倉庫中的遠程分支,而後用 rebase 將咱們的工做移動到最新的提交記錄下,最後再用 git push 推送到遠程倉庫。

origin 和它的周邊

合併特性分支

既然你應該很熟悉 fetch、``pullpush` 了,如今咱們要經過一個新的工做流來測試你的這些技能。

在大型項目中開發人員一般會在(從 master 上分出來的)特性分支上工做,工做完成後只作一次集成。這跟前面課程的描述很相像(把 side 分支推送到遠程倉庫),不過本節咱們會深刻一些.

可是有些開發人員只在 master 上作 pushpull —— 這樣的話 master 老是最新的,始終與遠程分支 (o/master) 保持一致。

對於接下來這個工做流,咱們集成了兩個步驟:

  • 將特性分支集成到 master
  • 推送並更新遠程分支

image-20210120104841787

$ git pull -rebase

$ git push

執行了兩個命令:

  • 將咱們的工做 rebase 到遠程分支的最新提交記錄
  • 向遠程倉庫推送咱們的工做

image-20210120104850824

fetch遠程倉庫的更新到本地倉庫,進行rebase合併,最後push到遠程倉庫中。

image-20210120104910537

$ git fetch

$ git rebase o/master side1

$ git rebase side1 side2

$ git rebase side2 side3

$ git rebase side3 master

$ git push

image-20210120104953469

爲何不用 merge 呢?

爲了 push 新變動到遠程倉庫,你要作的就是包含遠程倉庫中最新變動。意思就是隻要你的本地分支包含了遠程分支(如 o/master)中的最新變動就能夠了,至於具體是用 rebase 仍是 merge,並無限制。

那麼既然沒有規定限制,爲什麼前面幾節都在着重於 rebase 呢?爲何在操做遠程分支時不喜歡用 merge 呢?

在開發社區裏,有許多關於 mergerebase 的討論。如下是關於 rebase 的優缺點:

優勢:

  • Rebase 使你的提交樹變得很乾淨, 全部的提交都在一條線上

缺點:

  • Rebase 修改了提交樹的歷史

好比, 提交 C1 能夠被 rebaseC3 以後。這看起來 C1 中的工做是在 C3 以後進行的,但其實是在 C3 以前。

一些開發人員喜歡保留提交歷史,所以更偏心 merge。而其餘人(好比我本身)可能更喜歡乾淨的提交樹,因而偏心 rebase。仁者見仁,智者見智。

image-20210120105007891

$ git fetch

$ git checkout side1

$ git merge o/master

$ git merge side2

$ git merge side3

$ git checkout master

$ git merge side1

$ git push

image-20210120105017867

遠程跟蹤分支

在前幾節課程中有件事兒挺神奇的,Git 好像知道 mastero/master 是相關的。固然這些分支的名字是類似的,可能會讓你以爲是依此將遠程分支 master 和本地的 master 分支進行了關聯。這種關聯在如下兩種狀況下能夠清楚地獲得展現:

  • pull 操做時, 提交記錄會被先下載到 o/master 上,以後再合併到本地的 master 分支。隱含的合併目標由這個關聯肯定的。
  • push 操做時, 咱們把工做從 master 推到遠程倉庫中的 master 分支(同時會更新遠程分支 o/master) 。這個推送的目的地也是由這種關聯肯定的!

遠程跟蹤

直接了當地講,mastero/master 的關聯關係就是由分支的「remote tracking」屬性決定的。master 被設定爲跟蹤 o/master —— 這意味着爲 master 分支指定了推送的目的地以及拉取後合併的目標。

你可能想知道 master 分支上這個屬性是怎麼被設定的,你並無用任何命令指定過這個屬性呀!好吧, 當你克隆倉庫的時候, Git 就自動幫你把這個屬性設置好了。

當你克隆時, Git 會爲遠程倉庫中的每一個分支在本地倉庫中建立一個遠程分支(好比 o/master)。而後再建立一個跟蹤遠程倉庫中活動分支的本地分支,默認狀況下這個本地分支會被命名爲 master

克隆完成後,你會獲得一個本地分支(若是沒有這個本地分支的話,你的目錄就是「空白」的),可是能夠查看遠程倉庫中全部的分支(若是你好奇心很強的話)。這樣作對於本地倉庫和遠程倉庫來講,都是最佳選擇。

這也解釋了爲何會在克隆的時候會看到下面的輸出:

local branch "master" set to track remote branch "o/master"

我能本身指定這個屬性嗎?

固然能夠啦!你可讓任意分支跟蹤 o/master, 而後該分支會像 master 分支同樣獲得隱含的 push 目的地以及 merge 的目標。 這意味着你能夠在分支 totallyNotMaster 上執行 git push,將工做推送到遠程倉庫的 master 分支上。

有兩種方法設置這個屬性,第一種就是經過遠程分支檢出一個新的分支,執行:

git checkout -b totallyNotMaster o/master

就能夠建立一個名爲 totallyNotMaster 的分支,它跟蹤遠程分支 o/master


檢出 master 分支的狀況下將工做推送到的遠程倉庫中的 master 分支上。

image-20210120105052237

$ git branch side

$ git checkout side

$ git commit -m "c3"

$ git fetch

$ git rebase c2 side

$ git push

Git Push 的參數

很好! 既然你知道了遠程跟蹤分支,咱們能夠開始揭開 git pushfetchpull 的神祕面紗了。咱們會逐個介紹這幾個命令,它們在理念上是很是類似的。

首先來看 git push。在遠程跟蹤課程中,你已經學到了 Git 是經過當前檢出分支的屬性來肯定遠程倉庫以及要 push 的目的地的。這是未指定參數時的行爲,咱們能夠爲 push 指定參數,語法是:

git push <remote> <place>

<place> 參數是什麼意思呢?咱們稍後會深刻其中的細節, 先看看例子, 這個命令是:

git push origin master

把這個命令翻譯過來就是:

切到本地倉庫中的「master」分支,獲取全部的提交,再到遠程倉庫「origin」中找到「master」分支,將遠程倉庫中沒有的提交記錄都添加上去,搞定以後告訴我。

咱們經過place參數來告訴 Git 提交記錄來自於 master, 要推送到遠程倉庫中的 master。它實際就是要同步的兩個倉庫的位置。

須要注意的是,由於咱們經過指定參數告訴了 Git 全部它須要的信息, 因此它就忽略了咱們所檢出的分支的屬性!

image-20210120105126285

$ git push origin master

$ git push origin foo

image-20210120105134365

place 參數詳解

還記得以前課程說的吧,當爲 git push 指定 place 參數爲 master 時,咱們同時指定了提交記錄的來源和去向。

你可能想問 —— 若是來源和去向分支的名稱不一樣呢?好比你想把本地的 foo 分支推送到遠程倉庫中的 bar 分支。

哎,很遺憾 Git 作不到…… 開個玩笑,別當真!固然是能夠的啦 😃 Git 擁有超強的靈活性(有點過於靈活了)

接下來我們看看是怎麼作的……

要同時爲源和目的地指定 <place> 的話,只須要用冒號 : 將兩者連起來就能夠了:

git push origin <source>:<destination>

這個參數實際的值是個 refspecrefspec 是一個自造的詞,意思是 Git 能識別的位置(好比分支 foo 或者 HEAD~1

一旦你指定了獨立的來源和目的地,就能夠組織出言簡意賅的遠程操做命令了,讓咱們看看演示!

image-20210120105142621

$ git push origin foo^:master

image-20210120105152060

若是你要推送到的目的分支不存在會怎麼樣呢?沒問題!Git 會在遠程倉庫中根據你提供的名稱幫你建立這個分支!

image-20210120105201822

$ git push origin master^:foo

$ git push origin foo:master

image-20210120105210579

Git fetch 的參數

咱們剛學習了 git push 的參數,很酷的 <place> 參數,還有用冒號分隔的 refspecs<source>:<destination>)。 這些參數能夠用於 git fetch 嗎?

你猜中了!git fetch 的參數和 git push 極其類似。他們的概念是相同的,只是方向相反罷了(由於如今你是下載,而非上傳)

讓咱們逐個討論下這些概念……

place 參數

若是你像以下命令這樣爲 git fetch 設置 place 的話:

$ git fetch origin foo

Git 會到遠程倉庫的 foo 分支上,而後獲取全部本地不存在的提交,放到本地的 o/foo 上。

來看個例子(仍是前面的例子,只是命令不一樣了)

咱們只下載了遠程倉庫中 foo 分支中的最新提交記錄,並更新了 o/foo

你可能會好奇 —— 爲什麼 Git 會將新提交放到 o/foo 而不是放到我本地的 foo 分支呢?以前不是說這樣的 place 參數就是同時應用於本地和遠程的位置嗎?

好吧, 本例中 Git 作了一些特殊處理,由於你可能在 foo 分支上的工做還未完成,你也不想弄亂它。還記得在 git fetch 課程裏咱們講到的嗎 —— 它不會更新你的本地的非遠程分支, 只是下載提交記錄(這樣, 你就能夠對遠程分支進行檢查或者合併了)。

「若是咱們指定 <source>:<destination> 會發生什麼呢?」

若是你以爲直接更新本地分支很爽,那你就用冒號分隔的 refspec 吧。不過,你不能在當前檢出的分支上幹這個事,可是其它分支是能夠的。

這裏有一點是須要注意的 —— source 如今指的是遠程倉庫中的位置,而 <destination> 纔是要放置提交的本地倉庫的位置。它與 git push 恰好相反,這是能夠講的通的,由於咱們在往相反的方向傳送數據。

理論上雖然行的通,但開發人員不多這麼作。我在這裏介紹它主要是爲了從概念上說明 fetchpush 的類似性,只是方向相反罷了。


使用 fetch 時, 你必須指定source destination。 注意一下目標窗口, 由於提交對象的 ID 可能會變哦!

image-20210120105218686

$ git fetch origin master^1:foo

$ git fetch origin foo:master

$ git checkout foo

$ git merge master

image-20210120105227744

會讓人捱揍的 source

Git 有兩種關於 source 的用法是比較詭異的,即你能夠在 git pushgit fetch 時不指定任何 source,方法就是僅保留冒號和 destination 部分,source 部分留空。

  • git push origin :side

    若是 pushsource 到遠程倉庫會如何呢?它會刪除遠程倉庫中的分支!慎重使用,刪除別人的遠程分支可能會捱揍。

  • git fetch origin :bugFix

    若是 fetchsource 到本地,會在本地建立一個新分支。

Git pull 參數

既然你已經掌握關於 git fetchgit push 參數的方方面面了,關於 git pull 幾乎沒有什麼能夠講的了 😃

由於 git pull 到頭來就是 fetch 後跟 merge 的縮寫。你能夠理解爲用一樣的參數執行 git fetch,而後再 merge你所抓取到的提交記錄。

還能夠和其它更復雜的參數一塊兒使用, 來看一些例子:

如下命令在 Git 中是等效的:

git pull origin foo 至關於:

$ git fetch origin foo
$ git merge o/foo

還有...

git pull origin bar~1:bugFix 至關於:

$ git fetch origin bar~1:bugFix
$ git merge bugFix

看到了? git pull 實際上就是 fetch + merge 的縮寫, git pull 惟一關注的是提交最終合併到哪裏(也就是爲 git fetch 所提供的 destination 參數)。

經過指定 master 咱們更新了 o/master。而後將 o/master merge 到咱們的檢出位置,不管咱們當前檢出的位置(checkout的位置、HEAD所在位置)是哪。


須要下載一些提交,而後建立一些新分支,再合併這些分支到其它分支, 但這用不了幾個命令。

image-20210120105251136

$ git pull origin bar:foo

$ git pull origin master:side

image-20210119160554842

內容來源:碼雲 --- Learn Git Branching(遠程篇)

相關文章
相關標籤/搜索