GitFlow 分支管理模型
一、什麼是 GitFlow?
GitFlow 是一種成熟的 Git 分支管理策略,用於規範團隊協作中的代碼版本管理流程。
- GitFlow 官方文檔
二、核心分支概念
GitFlow 模型包含五大核心分支,每個分支都有明確的職責和使用場景:
1. Master 分支(主分支)
- 用途:存放穩定的生產代碼
- 特性:始終保持可部署的穩定狀態
- 管理:只接受來自 Release 分支或 Hotfix 分支的合併
- 版本標記:每個提交都應該添加版本標籤(如 v1.0.0)
2. Develop 分支(開發分支)
- 用途:集成所有正在開發的功能
- 來源:基於 Master 分支創建
- 特性:包含下一個版本要發佈的所有功能
- 管理:所有 Feature 分支開發完成後都合併到 Develop 分支
3. Feature 分支(功能分支)
- 用途:開發新功能或改進
- 來源:基於 Develop 分支創建
- 命名規範:
feature/功能名稱(如feature/user-authentication) - 管理:
- 功能開發完成後合併回 Develop 分支
- 永遠不會直接與 Master 分支交互
- push到遠程倉庫,發起 Pull Request/Merge Request 請求合併回 Develop 分支
- 經過 Code Review(代碼審核)通過後方可合併
4. Release 分支(發佈分支)
- 用途:準備新版本發佈
- 來源:基於 Develop 分支創建
- 命名規範:
release/x.y.z(如release/1.2.0,x.y.z為版本號) - 管理:
- 用於修復發佈前的 bug
- 不添加新功能,只處理 bug 修復和版本準備
- 測試通過後同時合併回 Master 分支和 Develop 分支
- 合併到 Master 分支後需要打版本標籤
- 發佈完成後應及時刪除
5. Hotfix 分支(熱修復分支)
- 用途:緊急修復生產環境中的問題
- 來源:基於 Master 分支創建
- 命名規範:
hotfix/x.y.z(如hotfix/1.2.1,x.y.z 為版本號) - 管理:
- 僅用於緊急修復,不處理新功能
- 修復完成後同時合併回 Master 分支和 Develop 分支
- 合併到 Master 分支後需要打版本標籤
- 修復完成後立即刪除
初始化倉庫
# 1. 初始化本地倉庫
git init
# 2. 添加遠程倉庫連接
git remote add origin <遠程倉庫URL>
# 3. 創建 Master 分支的首次提交
git add .
git commit --allow-empty -m "Initial commit"
# 4. 創建 Develop 分支
git checkout -b develop
# 5. 推送兩個核心分支到遠程
git push -u origin master
git push -u origin develop
# 6. 設置遠程倉庫的默認分支(可選但推薦)
git remote set-head origin master
--allow-empty 允許創建空提交
三、工作流程示例
展示適用於單人開發或無 PR 強制要求的場景流程示例
標準的現代流程為:推送功能分支到遠程 -> 在平台上創建 PR -> 審核通過後在網頁端點擊合併。
1. 功能開發流程
- 從 Develop 分支創建 Feature 分支
# 切換到 Develop 分支並確保是最新狀態
git checkout develop
git pull origin develop
git checkout -b feature/xxx develop
- 在 Feature 分支上進行功能開發
- 開發完成後,將 Feature 分支合併回 Develop 分支
git checkout develop
# 採用--no-ff參數,表示強制創建合併提交
# 合併時會創建一個新的合併提交,保留分支歷史
git merge --no-ff feature/xxx
git push
- 刪除本地 Feature 分支
git branch -d feature/xxx
# 如果之前推送了 Feature 分支,則需要刪除遠程分支
# git push origin --delete feature/xxx
2. 版本發佈流程
- 從 Develop 分支創建 Release 分支
# 切換到 Develop 分支並確保是最新狀態
git checkout develop
git pull origin develop
git checkout -b release/x.y.z develop
- 在 Release 分支上進行 bug 修復和版本準備
- 測試通過後,將 Release 分支合併回 Master 分支並打版本標籤
git checkout master
git merge --no-ff release/x.y.z
git tag -a tagName -m "Release x.y.z"
# 推送標籤到遠程倉庫
git push origin tagName
# 推送代碼到遠程倉庫
git push
- 同時將 Release 分支合併回 Develop 分支,確保開發分支包含所有修復
git checkout develop
git merge --no-ff release/x.y.z
git push
- 刪除 Release 分支
git branch -d release/x.y.z
# 如果之前推送了 Release 分支,則需要刪除遠程分支
# git push origin --delete release/x.y.z
3. 熱修復流程
- 從 Master 分支創建 Hotfix 分支
# 切換到 Master 分支並確保是最新狀態
git checkout master
git pull origin master
git checkout -b hotfix/x.y.z master
- 在 Hotfix 分支上修復問題
- 測試通過後,將 Hotfix 分支合併回 Master 分支並打版本標籤
git checkout master
git merge --no-ff hotfix/x.y.z
git tag -a tagName -m "Hotfix x.y.z"
# 推送標籤到遠程倉庫
git push origin tagName
# 推送代碼到遠程倉庫
git push
- 同時將 Hotfix 分支合併回 Develop 分支,確保開發分支包含修復
git checkout develop
git merge --no-ff hotfix/x.y.z
git push
- 刪除 Hotfix 分支
git branch -d hotfix/x.y.z
# 如果之前推送了 Hotfix 分支,則需要刪除遠程分支
# git push origin --delete hotfix/x.y.z
四、Git回退操作
有改動,無add,無commit
撤銷工作區改動
git checkout -- filename
有改動,有add,無commit
撤銷暫存區的改動
git reset HEAD filename
有改動,有add,有commit
從本地庫回退(已commit,未push)
| 操作描述 | 命令 | 效果 |
|---|---|---|
| 撤銷提交,但保留改動在工作區 | git reset --mixed HEAD^ | 提交消失,改動還在工作區 |
| 撤銷提交,但保留改動在暫存區 | git reset --soft HEAD^ | 提交消失,改動還在暫存區 |
| 徹底丟棄(真的不要了) | git reset --hard HEAD^ | 全部消失,慎用! |
有改動,有add,有commit,有push
撤銷已推送的提交
創建一個新提交,用於撤銷指定提交
提交的新提交用來"抵消"(逆向操作)指定提交的更改。
revert後需要再次 git push 才能同步到遠程
git revert <commit-hash>
reset VS revert
| 操作 | 描述 | 影響 |
|---|---|---|
| reset | 通過移動分支指針來回退到指定提交 | 直接改變歷史 |
| revert | 創建一個新提交,用於來"抵消"(逆向操作)指定提交的更改 | 不改變歷史,而是在歷史記錄中增加一個新的,反向的提交 |
五、Git Stash(暫存區域)
臨時保存工作進度,快速切換上下文,而不需要創建臨時提交。
緊急修復bug時的上下文切換
# 正在功能分支開發,突然需要修復生產bug
$ git status
# 修改:src/feature.js
# 修改:src/feature.css
# 最佳實踐:使用描述性消息
$ git stash push -m "WIP: 用户頭像上傳功能開發中"
# 切換到主分支修復bug
$ git checkout main
$ git pull origin main
$ git checkout -b hotfix/login-bug
# ... 修復工作 ...
# 返回後繼續開發
$ git checkout feature/user-avatar
$ git stash list
# stash@{0}: WIP: 用户頭像上傳功能開發中
$ git stash pop
# 恢復工作進度
默認情況下,git stash 只能暫存已跟蹤文件(tracked files)的修改,但可以通過參數
-u顯式包含未跟蹤文件。
git stash push -u -m "描述"
- 始終使用 -m 添加描述性消息
- git stash apply(僅恢復)
- git stash pop(恢復並刪除)
- 定期清理過期的 stash:git stash drop stash@
- git stash clear(清空所有 stash)
- 可以跨分支使用 stash
六、Git Cherry-Pick
將特定提交從一個分支複製到另一個分支,而不合並整個分支歷史。
- 涉及單個提交
git cherry-pick -x <commit-hash>
-x 參數表示在提交信息中添加"cherry picked from commit"説明
- 涉及多個提交
git cherry-pick -x <commit-hash1>..<commit-hash2> # 不包含起始提交
git cherry-pick -x <commit-hash1>^..<commit-hash2> # 包含起始提交
- 衝突處理
- git cherry-pick --continue # 繼續完成cherry-pick
- git cherry-pick --abort # 撤銷並回到初始狀態
七、Git Fetch & Git Pull
fetch VS pull
| 操作 | 本質 | 對本地代碼的影響 |
|---|---|---|
| fetch | 僅下載遠程更新 | 不改變工作目錄和當前分支 |
| pull | 下載+自動合併(git fetch + git merge 的自動執行) | 改變工作目錄和當前分支 |
決策樹
- 默認 git pull = git fetch + git merge (產生合併提交)
- git pull --rebase = git fetch + git rebase (歷史變平)
git pull --rebase
獲取遠程更新,將本地提交"嫁接"到遠程最新提交之上
八、Git Merge & Git Rebase
merge VS rebase
| 操作 | 本質 | 對本地代碼的影響 | 應用 | 描述 |
|---|---|---|---|---|
| merge | 合併兩個分支 | 改變工作目錄和當前分支 | 在「接收合併的目標分支」上執行 | 站在目標分支,合併進來 |
| rebase | 將指定分支的提交歷史,應用到當前分支 | 改變工作目錄和當前分支 | 在「被變基的分支」上執行 | 站在被變基分支,基於基準變 |
⚠️ 黃金法則:永遠不要對位於公共倉庫之外的提交(即已經 push 到遠程並被他人使用的提交)執行 Rebase。
只對尚未推送或僅屬於你個人的本地提交使用 Rebase。對公共歷史 Rebase 會導致團隊成員協作時產生混亂和代碼丟失。
可視化對比
分支初始狀態
Git Merge 可視化
git checkout main
git merge feature後狀態
- main 分支:指針移到新的合併提交 H,歷史新增合併記錄;
- feature 分支:指針位置不變(仍指向 G),分支本身毫髮無損;
Git Rebase 可視化
git checkout feature
git rebase main後狀態
- main 分支:完全不受影響,指針仍指向 E;
- feature 分支:指針從原來的 G 移到新的 G'(提交歷史被重寫)
附錄
- 缺少 CI/CD 配置