cover

架構概覽

flowchart LR
    Feature[Feature Branch<br/>功能開發] -->|Merge Request| Develop[develop 分支<br/>整合測試]
    Develop -->|合併| Main[main 分支]
    Main -->|git tag v1.x.0| CI[CI Pipeline<br/>build + test]
    CI -->|deploy| Staging[Staging 環境<br/>QA 驗證]
    Staging -->|手動確認| Prod[Prod 環境<br/>正式上線]
    Main -->|緊急修復| Hotfix[Hotfix 分支]
    Hotfix -->|合回| Main
    Hotfix -->|同步| Develop

Git & CI:讓每一次交付都可追蹤、可回滾

Git 不只是版本控制工具,它同時也是 CD 的觸發源、Release 的版本紀錄、以及 Rollback 的回復依據。這篇文章定義分支策略、Release 流程、以及出事時怎麼快速回滾,讓團隊不會因為「不確定上了什麼版本」而慌張。

架構概覽

gitGraph
  commit id: "init"
  branch develop
  commit id: "feat-A"
  commit id: "feat-B"
  checkout main
  merge develop id: "v1.0.0" tag: "v1.0.0"
  branch hotfix
  commit id: "fix-critical"
  checkout main
  merge hotfix id: "v1.0.1" tag: "v1.0.1"
  checkout develop
  merge hotfix
  commit id: "feat-C"
  checkout main
  merge develop id: "v1.1.0" tag: "v1.1.0"

主要分支:main(穩定版本)、develop(開發中)。功能在 develop 開發,合併到 main 時打 tag 觸發 Release。緊急修復走 hotfix 分支,修完同時合回 maindevelop

核心概念

  1. 分支策略:採用簡化版的 Git Flow。main 永遠是可部署的穩定版本,develop 是下一個版本的開發分支。功能開發從 develop 開 feature branch,完成後 merge 回 develop。這樣做比直接在 main 上開發安全,因為 main 始終對應到正在運行的版本,不會有半完成的功能。

  2. Semantic Versioning:版本號用 v{major}.{minor}.{patch} 格式。major 代表破壞性變更(API 不相容)、minor 代表新功能、patch 代表 bug 修復。這讓任何人看到版本號就知道這次更新的影響範圍。例如 v1.0.0v1.0.1 代表只有 bug fix,可以安心升級。

  3. Release 流程:從 develop 合併到 main,在 main 上打 tag(v1.1.0),CI 自動觸發 build → deploy to staging。QA 驗證通過後,手動觸發 deploy to prod。每個 Release 都在 GitLab 建立 Release note,記錄包含哪些 commit 和功能。

  4. Rollback 機制:如果新版本出問題,有兩種回滾方式。快速回滾:在 PortainerDocker image tag 退回前一個版本(例如 v1.0.0),幾秒內生效。完整回滾:從 main 的前一個 tag checkout,重新 build 並部署。前者適合緊急情況,後者適合需要包含 config 變更的回滾。

使用情境

  • 正常 Release:開發團隊完成了 3 個新功能,在 develop 上都通過測試。PM 確認要上線,將 develop merge 到 main,打 tag v1.2.0。CI 自動 build、push image、deploy to staging。QA 花一天驗證,沒問題後手動觸發 prod deploy。

  • 緊急 Hotfix:prod 上發現 critical bug。從 main 的最新 tag 開 hotfix/fix-payment 分支,修完後 merge 回 main,打 tag v1.2.1。CI 走加速流程(跳過 staging,直接 deploy prod)。修完後也要 merge 回 develop,避免下次 release 又把 bug 帶回來。

  • Rollback 情境v1.3.0 上線後發現效能嚴重下降。立即在 Portainer 把 image tag 從 v1.3.0 退回 v1.2.1,服務恢復正常。同時在 develop 上排查效能問題,修完後走正常 Release 流程重新上線。

實作範例 / 設定範例

Release 腳本

#!/bin/bash
# scripts/release.sh - 建立新 Release
set -euo pipefail
 
VERSION=$1  # e.g., v1.2.0
 
# 確認在 main 分支
CURRENT_BRANCH=$(git branch --show-current)
if [ "$CURRENT_BRANCH" != "main" ]; then
  echo "Error: must be on main branch"
  exit 1
fi
 
# 確認沒有未 commit 的變更
if [ -n "$(git status --porcelain)" ]; then
  echo "Error: uncommitted changes"
  exit 1
fi
 
# 建立 annotated tag
git tag -a "$VERSION" -m "Release $VERSION"
git push origin "$VERSION"
 
echo "Release $VERSION created and pushed."
echo "CI will automatically build and deploy to staging."

Rollback 操作手冊

# === 快速回滾(Docker image 層級)===
# 1. 確認要回滾到的版本
docker images | grep myapp-api
 
# 2. 在 docker-compose.yml 修改 image tag
# image: registry.example.com/myapp-api:v1.3.0
# → image: registry.example.com/myapp-api:v1.2.1
 
# 3. 重新部署
docker compose pull && docker compose up -d
 
# 4. 驗證
curl -sf https://api.example.com/health
 
# === 完整回滾(包含 config 變更)===
# 1. 找到要回滾的 commit
git log --oneline --tags
 
# 2. 建立 revert branch
git checkout -b revert/v1.3.0 v1.2.1
 
# 3. 推送並觸發 CI
git push origin revert/v1.3.0
 
# 4. 建立 MR merge 回 main

GitLab Release Note 模板

## v1.2.0 Release Notes
 
### New Features
- [EC-123] 新增購物車批次刪除功能
- [EC-124] 支援多種付款方式切換
 
### Bug Fixes
- [EC-125] 修正訂單金額計算錯誤
 
### Breaking Changes
-
 
### Migration Steps
- 無需額外步驟
 
### Rollback Plan
- Docker image rollback to v1.1.0
- 無 DB migration 需要回滾

常見問題與風險

  • 直接在 main 上開發:跳過 develop 直接在 main 提交,導致 main 上有未完成的功能。如果這時需要 hotfix,就會把半成品一起上線。避免方式:設定 GitLab 的 branch protection,禁止直接 push 到 main。

  • Tag 忘記打:deploy 了但沒有打 tag,之後要 rollback 時找不到對應的版本。避免方式:CI pipeline 強制要求 deploy 必須有 tag,沒有 tag 的 commit 不允許 deploy 到 staging/prod。

  • Hotfix 沒有 merge 回 develop:hotfix 只合回 main,忘記也合回 develop。結果下次 release 時,修好的 bug 又出現了。避免方式:hotfix PR 的 checklist 加上「已 merge 回 develop」。

  • Rollback 後資料庫不相容:新版本做了 DB migration(加了 column),rollback 到舊版本後,舊版的程式碼不認識新 column,可能出錯。避免方式:DB migration 要設計成向前相容(additive only),不要在 migration 中刪 column 或改 column type。

優點

  • 每個版本有明確的 tag 和 release note,方便追蹤
  • Rollback 機制明確,出事時不慌張
  • 分支策略清楚,多人協作不衝突

缺點 / 限制

  • Git Flow 對小團隊可能太重(可以簡化為 trunk-based development)
  • Hotfix 流程比較繁瑣(要 merge 到多個分支)
  • DB migration 的回滾比程式碼回滾複雜很多

延伸閱讀