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.
- 檢查衝突文件:打開
example.txt
,您會看到以下衝突標記:
<<<<<<< HEAD
// 這是您在 feature 分支上的更改
=======
// 這是 main 分支上的更改
>>>>>>> main
-
手動解決衝突:決定保留哪些更改、修改或合併這些更改,然後刪除 Git 的衝突標記。
-
完成合併並提交更改:完成衝突解決後,您可以使用以下命令繼續合併過程:
$ 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