2. 搞懂 Push、Pull、Fetch 與 Clone

封面那裏我有提到,Git最最大的用處就是讓我們創建分支,一條分支當實驗用,另一條分支當正式開發用。那實際開發時,我們到底是怎麼把程式碼在「本地電腦」與「雲端 GitHub」之間搬運的呢?

最直覺的理解方式,就是把這整個過程看作是一套「物流大師的拉貨與送貨系統」。

1. 本地(Local)與 遠端(Remote)

在開始搬運前,我們要先劃分兩個世界:

  • 本地(Local): 就是你的電腦,正在用 VS Code 寫扣的地方。
  • 遠端(Remote): 遠在天邊的 GitHub 伺服器,用來保存團隊共同資產的地方。

這兩個世界各有各的 Git 紀錄。而接下來的四個動作,就是連接這兩個世界的橋梁。

2. Push、Pull、Fetch、Clone

Push

  • 白話文: 「老闆,我貨包好了,現在發車送去總倉!」
  • 幹嘛用: 當你在本地寫完程式、做好 Commit(紀錄點)後,這些變化依然只在你的電腦裡。你需要透過 Push,把本地的新 Commit 「推」上 GitHub。這樣一來,雲端上才會更新你的最新進度,協同開發的夥伴也才看得到。

Pull

  • 白話文: 「聽說總倉有新貨?立刻載回來並直接上架到我的店面!」
  • 幹嘛用: 當團隊裡的其他工程師 Push 了他們寫好的新功能到 GitHub,此時你本地的程式碼就落後了。你需要透過 Pull,把 GitHub 上別人寫好的新進度「拉」回你的電腦,而且 Git 會非常聰明地自動幫你合併(Merge)到你目前的檔案裡。

Fetch

  • 白話文: 「聽說總倉有新進度?我先拿個出貨單看看改了什麼,但我店面的貨先維持原狀。」
  • 幹嘛用: Fetch 與 Pull 非常像,但少了一個「自動合併」的步驟。 執行 Fetch 時,Git 只會把雲端的最新狀態同步到你本地的「遠端追蹤分支」紀錄裡,但完全不會動到你目前正在寫的任何檔案。適合用在你「想先確認別人改了什麼,確認沒問題後再自己手動合併」的場景。

💡 大公式: Pull = Fetch + Merge(合併)

Clone

  • 白話文: 「這家店的加盟總部蓋得太好了,我要複製一模一樣的整座倉庫到我家隔壁!」
  • 幹嘛用: 通常是用在你剛加入一個新專案,或者在 GitHub 上看到別人的開源專案很讚時。你本地目前「什麼都沒有」,這時只要輸入 git clone [網址],Git 就會把遠端儲存庫的程式碼、歷史紀錄、所有分支,原封不動、徹徹底底地完整下載一份到你的電腦裡。

3. 總表

動作方向什麼時候會用到?對本地檔案的影響
Clone雲端⮕本地第一次要下載整個專案時。建立全新資料夾與所有歷史。
Push本地⮕雲端寫完一個階段,想備份或分享進度時。無,只會更新雲端。
Pull雲端 ⮕本地開始寫程式前,確保自己拿到團隊最新進度。,直接改寫你目前的檔案。
Fetch雲端 ⮕本地想知道雲端有沒有更新,但現在不想動到本地檔案。不會動到你正在寫的檔案。

4. 實戰push !

第一章的時候我們有建立了一個專案,裡面包含index.html,並將其推送上GitHub,這些動作稱為Initialization 初始化。

那現在正式進入開發階段後,又該如何操作呢?

1. 修改檔案(例如新增一行字):

我們透過指令來修改index.html這個檔案(當然你也可以從VScode中開啟並修改)。

echo "<p>Update: Adding some new features...</p>" >> index.html
Code language: HTML, XML (xml)

2. 重複以下三步驟:

git add .
git commit -m "Update index.html with new paragraph"
git push
Code language: JavaScript (javascript)
  • git add . 表示把當前資料夾的所有檔案一次裝箱
  • git commit -m -m 後面的雙引號裡,請務必寫下「這次做了什麼更改」的白話文(通常會是: 動詞 + 名詞 e.g. 新增 首頁),給這次裝箱的貨物貼個標籤。
  • git push 把貨送上 GitHub !

以後日常開發,你只需要瘋狂重複這三行指令,你的雲端進度就會永遠維持最新狀態。

5. 實戰 Clone!

我們成功把專案推上 GitHub 後。現在,請在你的電腦上開一個全新、空空如也的資料夾,我們來模擬「在另一台電腦上下載專案」的情境。

當你到一家新公司上工,或是想把 GitHub 上別人的開源專案整包抓下來時,這是你「第一個會輸入的指令」。

進入全新的空資料夾後,請去你的 GitHub 複製上一章建立的專案網址(https://github.com/你的帳號/my-project.git),然後再終端機輸入:

git clone https://github.com/你的帳號/my-project.git
Code language: PHP (php)

接著進入資料夾並輸出檔案看看~

cd my-project
ls -la

你會看到資料夾裡不只有 index.html,連隱藏的 .git 資料夾都幫你準備好了!這代表 clone 不只幫你下載檔案,連遠端地址(origin)和所有的歷史紀錄都一併複製過來了,你不需要再重新輸入 git init

6. 實戰 fetch !

為了模擬「別人在他那裡改了程式碼」的情境,我們現在做個小實驗:

  1. 請打開你的 GitHub 網頁,點進去 index.html
  2. 點擊右上角的小鉛筆編輯它,在裡面隨便加上一行字:<h2>This line is edited from GitHub website!</h2>
  3. 點擊 Commit changes… 儲存。

此時,雲端的進度已經領先你本地的電腦了。接下來我們用 fetch 來打探敵情:

git fetch

這時終端機會跳出一些進度條,代表它已經去雲端「抓取最新的紀錄」下來了,接著用 VS Code 打開本地的 index.html,會發現剛剛在網頁上改的那行字「還沒有出現」

fetch 的本質: 它只會更新你本地電腦裡的「遠端分支紀錄」(例如 upstream/main),讓你知道雲端有新東西,但不會擅自修改你目前的實體檔案

7. 實戰 pull !

如果你看完 fetch 的項目,確認雲端的修改沒問題,想要把正式版本的新程式碼「合進來」你目前的檔案,這時就要用 pull

git pull

終端機會顯示 Fast-forward 以及有哪些檔案被修改了。

這時候回頭去看你的本地 index.html,你會發現網頁上改的那行 <h2> 已經完美出現在你的程式碼裡了!

其實日常開發中,如果你百分之百確定雲端的程式碼很乾淨,可以直接輸入 git pull,它會自動幫你做完 fetch + merge(合併)

Daily Flow

學會了這套組合拳後,以下是未來的工程師日常基本素養:

  1. 每天早上開工第一件事: 先輸入 git pull,把團隊昨天深夜推上雲端的最新進度拉下來,避免自己寫在舊的基底上。
  2. 寫完一個功能後:git add .git commit⮕ 最後 git push 送上雲端。

熟悉後就不是什麼難題啦!