Git 和 Git Flow 是什麼?如何應用?

2023年2月5日

💎 加入 E+ 成長計畫 與超過 750+ 位工程師一同在社群成長,並獲得更多深度的軟體前後端學習資源

假如你今天在開發一個重要功能,結果團隊中的其他人更新了一段程式碼,你同步後發現整個專案都跑不起來了。又或者,另一位團隊成員正在修復線上的緊急問題,但這些修改又跟你的程式碼產生衝突,讓程式跑不起來。這類混亂的情況,是在沒有適當版本控制策略的團隊中,經常會發生的。

而 Git 和 Git Flow 就是為了解決這類問題而生。讓我們透過這篇文章,來了解如何透過 Git 與 Git Flow 來讓軟體團隊協作變得更有條理。

Git 是什麼?

Git 是一個分散式版本控制系統,它讓開發團隊能用非常簡單的方式管理程式碼庫。雖然 Git 會被用來追蹤檔案變化,但 Git 背後的運作方式,其實會更貼近「快照」的思考方式。

讓我們用一個具體的例子來理解這個概念。假設今天我們要開發一個簡單的網站,在最開始有兩個初始檔案:index.htmlstyle.css

版本 1              版本 2              版本 3
┌──────────────┐   ┌──────────────┐   ┌──────────────┐
│   專案        │   │   專案       │   │   專案        │
│ ┌──────────┐ │   │ ┌──────────┐ │   │ ┌──────────┐ │
│ │index.html│+ │ │index.html│+ │ │index.html│
│ │style.css │ │   │  (ref v1) │ │   │  (ref v1) │ │
│ └──────────┘ │   │ │style.css │ │   │ │style.css │ │
└──────────────┘   │  (ref v1) │ │   │  (新 v3)  │ │
                   │ │about.html│ │   │ │about.html│
                   │ │script.js │ │   │  (ref v2) │ │
                   │ └──────────┘ │   │ │script.js │ │
                   └──────────────┘   │  (ref v2) │ │
                                      │ └──────────┘ │
                                      └──────────────┘
     初始檔案          新增檔案          更新 style.css

版本 1:我們建立了初始的網站檔案— index.html 放首頁內容,style.css 放初始的樣式。Git 會為整個專案拍一個完整的快照。

版本 2:我們擴展了網站功能,新增 about.htmlscript.js。由於 index.htmlstyle.css 沒有變化,Git 只需要參照版本 1 的內容。只有新檔案會被儲存為新的內容。

版本 3:我們修改了 style.css 來改善設計。index.html 還是參照版本 1,about.htmlscript.js 參照版本 2。只有更新的 style.css 會被儲存為新內容。

可以看到,這種快照的形式,跟追蹤個別檔案變化不太一樣。而也因為 Git 在每個時間點都會捕捉專案的完整狀態,我們可以很輕易地跳到任何之前的版本。

Git 的三個狀態:你的程式碼存在哪裡?

在 Git 中,你的檔案可以存在三種不同的狀態,理解這個概念可以幫你避免很多麻煩。

工作目錄           索引 (Git 暫存區)    儲存庫
┌─────────────────┐ ┌────────────────────┐ ┌─────────────────┐
│                 │ │                    │ │                 │
│ ┌─────────────┐ │ │  ┌─────────────┐   │ │ ┌─────────────┐ │
│ │ 已修改檔案    │ │ │  │ 已暫存檔案   │   │ │ │ 已提交快照    │ │
│ │             │ │ │  │             │   │ │ │             │ │
│ │             │ │ │  │             │   │ │ │             │ │
│ │ *.html      │ │ │  │ README.md   │   │ │ │ v1.0 ────── │ │
│ │ *.css       │ │ │  │ style.css   │   │ │ │ v1.1 ────── │ │
│ │ *.js        │ │ │  │             │   │ │ │ v1.2 ────── │ │
│ └─────────────┘ │ │  └─────────────┘   │ │ └─────────────┘ │
│                 │ │                    │ │                 │
└─────────────────┘ └────────────────────┘ └─────────────────┘
        │                       │                       │
        │ git add <file>        │ git commit            │
        └───────────────────────┼───────────────────────┘

                    "git add ." 暫存所有變更

工作目錄:這是你實際編輯檔案的地方。當你在編輯器中打開 index.html 並做修改時,你就是在工作目錄中操作。這些變更只存在於你的電腦上,除非你對它們做些什麼。

索引 (Git 暫存區):把這個想像成一個準備區。當你對修改滿意,想要把它們包含在下一個快照中時,你可以用 git add 把它們加到索引中。這就像在說「我準備好要提交這些特定的變更,但其他的還沒準備好」。

儲存庫:這是 Git 永久儲存快照的地方。當你執行 git commit 時,Git 會把索引中的所有內容拿來建立一個新的提交物件到儲存庫中。

你可能會問「為什麼要有索引?」想像一下,你同時在開發兩個不同的功能,修改了五個檔案。你想要現在就提交功能 A 的工作,但功能 B 還沒準備好。索引讓你可以選擇性地選擇哪些變更要放進每次提交中,保持你的專案歷史乾淨且有邏輯。

Git Flow 是什麼?

瞭解了 Git 的運作方式後,現在讓我們面對一個更大的挑戰:當有多個開發者同時在處理不同功能、bug 修復、以及版本發布時,我們該如何組織工作?

考慮一個典型的開發情境:

  • 一個開發者正在開發新的使用者註冊功能
  • 另一個開發者正在修復線上的重要安全性問題
  • 你正在準備下個月的版本發布
  • 你的團隊主管正在審查和測試功能,準備上線

我們要如何防止這些不同的工作流程互相干擾?如何確保緊急的 bug 修復不會意外包含尚未完成的功能?

Git Flow 透過結構化的分支策略提供了解決方案。就像為不同類型的工作準備不同的工作空間。

                    Git Flow 分支模型

Master     ●────────●────────●────────●────────●
           │        │        │        │        │
           │        │        │        │        │
           │        │   v1.0 │   v1.1 │   v2.0
           │        │        │        │        │
           │        │        │        │        │
Hotfix     │        │        ●────────┘        │
           │        │       ╱                  │
           │        │      ╱                   │
           │        │     ╱                    │
           │        │    ╱                     │
Release    │        ●───╱──────────────────────┘
           │       ╱
           │      ╱
           │     ╱
           │    ╱
Develop    ●───●────●────●────●────●────●────●
           │        │    │    │    │    │    │
           │        │    │    │    │    │    │
Feature A  │        ●────●────┘    │    │    │
           │       ╱    ╱           │    │    │
           │      ╱    ╱            │    │    │
Feature B  │     ╱    ╱             ●────●────┘
           │    ╱    ╱             ╱    ╱
           │   ╱    ╱             ╱    ╱
           │  ╱    ╱             ╱    ╱
           │ ╱    ╱             ╱    ╱
           ●╱    ╱             ╱    ╱
                ╱             ╱    ╱
               ╱             ╱    ╱
              ╱             ╱    ╱
             ╱             ╱    ╱
            ╱             ╱    ╱
           ╱             ╱    ╱
          ╱             ╱    ╱
         ●             ╱    ╱
                      ╱    ╱
                     ╱    ╱
                    ╱    ╱
                   ╱    ╱
                  ╱    ╱
                 ╱    ╱
                ╱    ╱
               ●────●

圖例:
= 提交/合併點
= 分支建立
── = 分支延續

五種分支類型:各有各的用途

讓我們來瞭解 Git Flow 中每種分支類型的作用,以及什麼時候會用到它們。

Master 分支:你的生產環境程式碼 master 分支代表目前正在線上運行的版本。master 上的每個提交都應該是穩定、經過測試、準備好讓使用者使用的。把它想成你的「黃金版本」——這是客戶實際使用的版本。我們什麼時候會動到 master?只有在準備發布到生產環境時才會。我們絕不直接在 master 上開發,因為我們希望隨時保持它的穩定性。

Develop 分支:整合發生的地方 develop 分支是我們整合已完成功能、準備下一次發布的地方。就像一個中介區域,我們把不同的工作合併在一起,看看它們如何協作。所有功能開發都從 develop 開始,功能完成後也會合併回 develop。這個分支通常應該是穩定的,但在整合新工作時偶爾可能會出現問題。

Feature 分支:個人開發工作空間 這裡是真正開發發生的地方。當有人開始開發使用者註冊功能時,他們會建立一個叫做 feature/user-registration 的功能分支。這給了他們一個完全獨立的工作空間,可以實驗、弄壞東西、反覆修改,而不會影響到其他人。功能分支總是從 develop 分支出來,完成後也會合併回 develop。

Release 分支:準備上線 當我們在 develop 中累積了足夠的功能,準備發布時,我們會建立像 release/1.2.0 這樣的發布分支。這個分支是我們進行最終測試、bug 修復、以及準備工作的地方。為什麼不直接從 develop 發布?因為當我們在準備 1.2.0 版本時,其他開發者可能正在加入預定給 1.3.0 版本的功能。發布分支給我們一個穩定的快照,讓我們可以在上線前進行最後的打磨。

Hotfix 分支:緊急生產修復 有時候線上環境出問題,我們需要立即修復。我們不能等到下一個計劃的發布。這時就需要 hotfix 分支。Hotfix 分支是唯一直接從 master(生產環境)分支出來的分支類型。當有人發現重要的安全漏洞時,他們會建立 hotfix/security-vulnerability,修復它,然後合併回 master 和 develop。

什麼時候用 Git Flow(什麼時候不用)

Git Flow 並不適合每個團隊或專案。我們來想想什麼時候使用它比較合適。

Git Flow 適合的情況:

  • 你有計劃性的發布,而不是持續部署
  • 多個開發者同時工作
  • 需要維護穩定的生產分支
  • 你的團隊能夠處理多種分支類型的複雜度
  • 你在開發有明確發布週期的傳統軟體

考慮使用更簡單的替代方案:

  • 小團隊(1-3 個開發者)進行持續部署
  • 你每天部署多次
  • 你的團隊剛開始學習 Git
  • 你在開發簡單的專案或原型

對於小團隊,GitHub Flow 可能更適合——它只使用功能分支和 master,直接從 master 部署。

下一步該怎麼做

瞭解了五種分支類型和它們的作用後,你對 Git Flow 如何組織開發工作就有了完整的概念。master 和 develop 分支提供穩定的基礎,而 feature、release、和 hotfix 分支則處理特定類型的工作,彼此不會干擾。這種結構化的方法把混亂的程式碼協作轉變成有組織的團隊合作。

但瞭解理論只是開始。成功實施 Git Flow 的關鍵是要配合你團隊的具體需求。當你有計劃性的發布、多個開發者、需要維護穩定的生產程式碼時,使用 Git Flow。對於進行持續部署的小團隊,GitHub Flow 這樣的簡單替代方案可能更適合。如果你的團隊還沒有採用 Git Flow,建議從小規模開始——先在一個小專案上試試看,然後逐漸引入到團隊中。記住,Git Flow 是工具,不是規則。適應你的工作流程,但要確保團隊中的每個人都理解並遵循一致的策略。


加入 E+ 成長計畫

如果你覺得這篇內容有幫助,喜歡我們的內容,歡迎加入 ExplainThis 籌辦的 E+ 成長計畫,透過每週的深度主題文,以及技術討論社群,讓讀者在前端、後端、軟體工程的領域上持續成長。

🧵 如果你想收到最即時的內容更新,可以在 FacebookInstagram 上追蹤我們