Skip to content

Git 進階操作

Git 工作流程

Git 為當前最受歡迎的版本控制系統,提供了多種工作流程來適應不同團隊的需求。下列是常見的三種工作流程 Git Flow、GitLab Flow 與 GitHub Flow。

Git Flow

Git Flow 是一種複雜的工作流程,適用於大型項目和嚴格的環境控制。它使用多個分支來管理功能開發、修復和部署。

  • 主分支(master):存放已部署的代碼。
  • 開發分支(develop):從 master 分支衍生,用於開發新功能。
  • 功能分支(feature branches):從 develop 分支衍生,用於新功能或修復。
  • 發布分支(release branches):從 develop 分支衍生,用於發布新版本。
  • 修復分支(hotfix branches):從 master 分支衍生,用於修復生產環境中的問題。
sequenceDiagram
    participant 主分支 as 主分支(master)
    participant 開發分支 as 開發分支(develop)
    participant 功能分支 as 功能分支(feature branches)
    participant 發布分支 as 發布分支(release branches)
    participant 修復分支 as 修復分支(hotfix branches)

    主分支->>開發分支: 從 master 分支衍生
    開發分支->>功能分支: 從 develop 分支衍生
    功能分支->>開發分支: 完成開發,合併到 develop
    開發分支->>發布分支: 從 develop 分支衍生
    發布分支->>主分支: 完成發布,合併到 master
    主分支->>修復分支: 從 master 分支衍生
    修復分支->>主分支: 完成修復,合併到 master

GitLab Flow

GitLab Flow 是 Git Flow 的變體,結合了功能分支和環境分支,並在其中積極運用 Merge Request:

  • 主分支(master):存放已部署的代碼。
  • 功能分支(feature branches):用於新功能或修復。
  • Merge Requests:當功能開發完成時,通過 Merge Requests 與團隊共享,並進行代碼審查。
  • 代碼審查(Code review):在合併到 master 分支前進行。
  • 環境分支(environment branches):管理不同環境的部署。
sequenceDiagram
    participant 主分支 as 主分支(master)
    participant 功能分支 as 功能分支(feature branches)
    participant Merge_Requests as Merge Requests
    participant 代碼審查 as 代碼審查(Code review)
    participant 環境分支 as 環境分支(environment branches)

    功能分支->>Merge_Requests: 完成開發,創建 Merge Request
    Merge_Requests->>代碼審查: 進行代碼審查
    代碼審查->>主分支: 審查通過,合併到 master
    主分支->>環境分支: 部署到不同環境

GitHub Flow

  • 主分支(master):始終是可部署的。
  • 功能分支(feature branches):從 master 分支衍生,每個新功能或修復都在自己的分支上開發。
  • Pull Requests:當功能開發完成時,通過 Pull Requests 與團隊共享,並進行代碼審查。
  • 代碼審查(Code review):在合併到 master 分支前進行。
  • 部署:將更改合併到 master 分支後,立即部署到生產環境。
sequenceDiagram
    participant 主分支 as 主分支(master)
    participant 功能分支 as 功能分支(feature branches)
    participant Pull_Requests as Pull Requests
    participant 代碼審查 as 代碼審查(Code review)
    participant 部署 as 部署

    主分支->>功能分支: 從 master 分支衍生
    功能分支->>Pull_Requests: 完成開發,創建 Pull Request
    Pull_Requests->>代碼審查: 進行代碼審查
    代碼審查->>主分支: 審查通過,合併到 master
    主分支->>部署: 更改合併後立即部署

GitLab vs GitHub Flow

  • 分支策略
  • GitHub Flow 強調從 master 分支衍生功能分支,並在完成後合併回 master
  • GitLab Flow 使用功能分支和環境分支,更適合複雜的部署流程。

  • 部署焦點

  • GitHub Flow 更適合持續部署,強調每次合併到 master 都應該是可部署的。
  • GitLab Flow 提供更多靈活性,適應多環境部署,如預生產或階段性部署。

  • 適用場景

  • GitHub Flow 簡單且直接,適合小型團隊和快速迭代的項目。
  • GitLab Flow 更適合需要嚴格環境控制和複雜工作流程的大型項目。

通過比較,我們可以看到 GitHub Flow 適合快速開發與部署,而 GitLab Flow 提供了對於複雜環境和部署策略的更好控制。選擇哪一種工作流程取決於團隊的具體需求、項目的規模和複雜度,以及部署的頻率和環境。

參考資料: - GitHub Flow - Choosing the Right Git Branching Strategy: A Comparative Analysis

Git 工作流程選用

為了配合 scrum 敏捷開發,將採用 GitHub Flow 作為 Git 工作流程。GitHub Flow 相對簡潔,適合小型團隊。它強調從 master 分支衍生功能分支,並在完成後合併回 master

GitHub Flow 範例

建立分支修改程式碼

下列步驟以 GitHub Flow 為基礎,並在 GitLab 平台上操作。將建立 feature-001 分支,並合併回 main 分支。

更新本地 main 分支

確保您的本地 main 分支是最新的:

git checkout main
git pull origin main

從 main 創建 feature-006 分支

從更新後的 main 分支創建新的功能分支:

git checkout -b feature-006

在 feature-006 分支上進行開發

在這個分支上進行所需的開發工作。

定期提交更改

將更改添加到暫存區並提交:

git add .
git commit -m "Add specific changes or features"

將更改推送到遠端儲存庫

第一次推送時,您需要設置上游分支:

git push -u origin feature-006

後續推送可以簡化為:

git push

將分支合併回 main

創建 Merge Request

  • 在 GitLab 儲存庫的網頁介面上,找到「Merge Requests」區域,點擊「New merge request」。
  • 選擇 feature-006 作為「Source branch」,main 作為「Target branch」。
  • 填寫 Merge Request 的標題和描述,解釋您所做的更改。
  • 提交 Merge Request。

代碼審查和討論

  • 與團隊成員進行代碼審查和討論。
  • 如有必要,根據反饋進行更改,並更新 Merge Request。

合併 Merge Request

  • 一旦 Merge Request 獲得批准,並且所有討論都已解決,點擊「Merge」按鈕將 feature-006 合併到 main 分支。
  • 可能需要再次確認合併操作。
sequenceDiagram
    participant Dev as Developer
    participant Local as Local Repo
    participant Remote as Remote Repo
    participant GitLab as GitLab

    Note over Dev,Local: 確保本地 main 分支是最新的
    Dev->>Local: git checkout main
    Dev->>Remote: git pull origin main
    Note over Dev,Local: 從 main 創建 feature-006 分支
    Dev->>Local: git checkout -b feature-006
    Note over Dev,Local: 在 feature-006 上進行開發
    Dev->>Local: git add . 和 git commit
    Note over Dev,Remote: 將更改推送到遠端儲存庫
    Dev->>Remote: git push -u origin feature-006
    Note over Dev,GitLab: 創建 Merge Request
    Dev->>GitLab: 創建 Merge Request
    Note over GitLab: 代碼審查和討論
    GitLab->>GitLab: 審查和討論
    Note over Dev,GitLab: 根據反饋進行更改
    Dev->>GitLab: 更新 Merge Request
    Note over GitLab: 合併到 main 分支
    GitLab->>GitLab: 合併 Merge Request 到 main

Pull Requests

Pull Requests 是一種在軟體開發中用於協作和代碼審核的功能。它們允許開發者告知團隊在一個分支上已完成的工作,並請求管控人員將這些更改合併到主分支中。這個過程促進了代碼審查、討論和修改,並且在更改合併到主分支之前,可以確保代碼質量。

Pull Request 不是一個 Git 指令,而是一個在遠端儲存庫平台(如 GitHub、GitLab)上使用的功能。它是一種請求,提出將一個分支的更改合併到另一個分支的建議,通常伴隨著代碼審查和討論。

此外,Pull Request 的功能在 GitLab 中稱為 Merge Request,但是它們的作用是相同的。

以下是在 GitLab 中創建和管理 Merge Requests 的基本步驟:

創建 Merge Request

開發功能或修復

  • 首先,在您的本地儲存庫中創建一個新分支,並進行開發。例如:git checkout -b feature-006

提交並推送更改

  • 完成開發後,提交您的更改到本地分支,然後將該分支推送到遠端(GitLab)儲存庫。例如:
git add .
git commit -m "Add new feature xyz"
git push origin feature-006

設定保護分支:

  • 在 GitLab 中,可以設定保護分支,以防止未經審核的更改被合併到主分支中。這是一個重要的安全措施,可以防止意外的更改導致生產環境中的問題。

  • 在「Protected Branches」(保護分支)區塊中(選項位於GitLab Settings/Repository),選擇要保護的分支(如 main 或 master)。

  • 在「Allowed to merge」選項中,選擇「Maintainers」。

  • 在「Allowed to push」選項中,也可選擇「Maintainers」,或根據需要設置其他限制。

  • 點擊「Protect」按鈕以保存設置。

在 GitLab 上新增 Merge Request

  • 當 GitLab 啟動保護分後,Developer 完成 feature branch 是無法直接合併至 main 的 (或指定的 branch),必須透過 Merge Request 交由 Maintainer 來進行合併。

  • 要啟動 Merge Request,可以在 Code/Merge Request 頁面中,點擊「New merge request」按鈕。

在 GitLab 中執行 Merge Request

  • Maintainer 要進行併版時,在 GitLab 專案中,左上角有三個 icon,分別是「Project」、「Issues」、「Merge Requests」,點擊「Merge Requests」,即可看到所有的 Merge Requests。

  • 選擇要合併的 Merge Request,設定 from branch 和 to branch,點擊「Merge」按鈕,即可完成合併。

審核和討論

代碼審查

  • 指定的審核者會在 Merge Request 中查看更改,並可以提出問題、討論和建議更改。Merge Request 頁面中有 HTML 編輯器,可以在其中進行討論。

迴應反饋

  • 作為 Merge Request 的發起者,您應該迴應審核者的反饋。如果需要進行更改,可以在本地進行修改,然後再次推送到相同的分支,這些更新將自動出現在 Merge Request 中。

合併更改

合併分支

  • 一旦 Merge Request 獲得批准,並且所有的討論都已解決,您或具有權限的團隊成員可以合併分支。

  • 在 GitLab 中,可以點擊 Merge Request 中的 "Merge" 按鈕來完成這一操作。

關閉 Merge Request

  • 合併後,Merge Request 將被標記為已合併,並且通常會自動關閉。

使用 Merge Requests 不僅有助於保證代碼質量,還提供了一個透明且可追蹤的方式來管理代碼更改和功能迭代。在 GitLab 中有效地運用這些功能可以大大提升協作和開發效率。

衝突解決

衝突的原因和預防

  • 合併衝突的常見原因:通常,當兩個分支對同一文件的相同部分進行不同更改時,就可能會發生衝突。

  • 預防衝突:通過有效的分支策略、定期合併主分支到功能分支以及團隊成員間的積極溝通,可以大幅減少衝突的發生。當小組分派任務時,避免兩個人在同一文件上進行更改,將有助於減少衝突。

解決合併衝突

使用工具解決衝突

  • 命令行:使用 Git 命令行工具直接解決衝突。

  • 圖形化工具:利用如 VS Code 等圖形化工具,它們提供更直觀的衝突解決介面。

衝突解決後的最佳實踐

  • 解決完衝突後,進行測試以確保更改不會導致新問題。

  • 提交解決衝突後的更改,並在 commit 訊息中清楚地說明如何解決了衝突。

範例:解決 Git 合併衝突

假設您在一個名為 feature 的分支上工作,並且需要將 main 分支的最新更改合併到您的分支中。您執行了 git merge main,但遇到了衝突:

$ git merge main
Auto-merging example.txt
CONFLICT (content): Merge conflict in example.txt
Automatic merge failed; fix conflicts and then commit the result.
  1. 檢查衝突文件:打開 example.txt,您會看到以下衝突標記:
<<<<<<< HEAD
// 這是您在 feature 分支上的更改
=======
// 這是 main 分支上的更改
>>>>>>> main
  1. 手動解決衝突:決定保留哪些更改、修改或合併這些更改,然後刪除 Git 的衝突標記。

  2. 完成合併並提交更改:完成衝突解決後,您可以使用以下命令繼續合併過程:

$ git add example.txt
$ git commit -m "Resolved merge conflict by incorporating both suggestions"

通過這種方式,您就可以有效解決合併過程中的衝突,並保持代碼庫的完整性和清晰性。

Reset

Git reset 可用於回退版本或撤銷更改。這個命令允許你修改提交歷史,並有三種主要模式:--soft--mixed--hard

  • --soft

此模式僅重置提交歷史,但保留更改並將它們放在暫存區。它適用於需要重新編輯提交訊息或合併多個提交的情況。

  • --mixed

這是默認模式。它會重置提交歷史,將更改從暫存區移出,但保留在工作目錄。適合在想要放棄已暫存更改時使用。

  • --hard: 此模式會重置提交歷史、暫存區和工作目錄,並丟棄所有未提交的更改。這是一種風險較高的操作,僅在確定不再需要這些更改時使用。

使用 HEAD~1 進行版本回退

HEAD~1 表示當前分支的前一個提交 (以此類推。例如,HEAD~2 表示當前分支的前兩個提交),使用 git reset 結合 HEAD~1 可以將當前分支回退到前一次提交的狀態。

使用 Commit Hash 進行精確回退

你也可以使用特定提交的 hashcode 來進行精確的版本回退。例如,如果你想回退到具有特定 hashcode 的提交,可以這樣做:

git reset --hard [commit-hashcode]

在使用 git reset,特別是 --hard 選項時,需格外謹慎,因為它可能導致未提交的更改永久丟失。在執行這類操作前,確保已妥善備份重要更改。

通過這個進階課程,您將學會如何更有效地使用 Git 進行版本控制,並能夠在複雜的開發環境中靈活應對各種情況。這些技能將幫助您在軟體開發項目中進行更有效的協作和代碼管理。

參考資料: Learn Git