iT邦幫忙

2025 iThome 鐵人賽

DAY 9
0
自我挑戰組

30天 Git 版本控制實戰筆記系列 第 24

Day 24:多人協作進階技巧 - 避免協作陷阱

  • 分享至 

  • xImage
  •  

今日目標
• 識別並避免常見的協作陷阱
• 掌握衝突解決的進階技巧
• 建立高效的團隊工作流程
• 學習大型團隊的最佳實踐


多人協作的 5 大常見陷阱
陷阱 1:直接在 main 分支上工作
問題場景:
開發者 A:在 main 修改 index.html
開發者 B:也在 main 修改 index.html

結果:
❌ 頻繁產生衝突
❌ 無法追蹤誰改了什麼
❌ 難以回滾錯誤
❌ 無法進行 Code Review
❌ 錯誤做法:

開發者 A

git checkout main
vim index.html # 修改檔案
git add index.html
git commit -m "更新首頁"
git push origin main # 成功推送

開發者 B(幾分鐘後)

git checkout main
vim index.html # 修改同一檔案
git add index.html
git commit -m "調整樣式"
git push origin main # ❌ 失敗!產生衝突
✅ 正確做法:Feature Branch Workflow

開發者 A

git checkout -b feature/homepage-update

在自己的分支上開發

vim index.html
git commit -m "feat: 更新首頁內容"
git push origin feature/homepage-update

建立 Pull Request

開發者 B

git checkout -b feature/style-improvement

在另一個分支獨立開發

vim style.css
git commit -m "style: 調整頁面樣式"
git push origin feature/style-improvement

建立 Pull Request

兩個分支互不干擾,透過 PR 依序合併

為什麼這樣更好?
✅ 隔離變更:各自開發不互相影響
✅ 程式碼審查:透過 PR 進行 Review
✅ 清晰歷史:每個功能有獨立的分支
✅ 容易回滾:出問題可以直接刪除分支
✅ 並行開發:多人可以同時工作


陷阱 2:忘記同步遠端最新版本
問題場景:
你在本地開發了 3 天
同時:

  • 同事合併了 20 個 PR
  • main 分支已經更新很多

你推送時:
❌ 產生大量衝突
❌ 無法自動合併
❌ 浪費時間處理衝突
❌ 錯誤做法:

星期一

git checkout -b feature/my-feature

開發中... 3 天過去了...

都沒有同步遠端

星期四

git push origin feature/my-feature

❌ 建立 PR 時發現有 50 個衝突!

✅ 正確做法:定期同步

每天開始工作前

git checkout main
git pull origin main # 拉取最新版本

切回你的分支

git checkout feature/my-feature
git merge main # 合併最新的 main

git rebase main # 重新套用你的 commits

解決小衝突(如果有)

繼續開發...

好處:

- 衝突分散在每天,容易處理

- 隨時知道自己的改動是否相容

- PR 時幾乎沒有衝突

最佳實踐:
每天同步 checklist:
□ 早上開工前 pull main
□ 午休回來後 pull main
□ 下班前 pull main
□ 看到 Slack 通知有 PR 合併時 pull main

自動化提醒:
設定 git hooks 或 CI 檢查分支是否過時


陷阱 3:提交訊息太隨便
問題:
查看歷史記錄時:
abc123 - fix
def456 - update
ghi789 - 修改
jkl012 - test
mno345 - 調整

❌ 完全不知道改了什麼!
❌ 找不到 bug 是哪次引入的
❌ 無法理解變更原因
❌ 糟糕的提交訊息:
git commit -m "fix"
git commit -m "update code"
git commit -m "調整"
git commit -m "改bug"
git commit -m "test"
git commit -m "zzz"
✅ 優秀的提交訊息:

使用 Conventional Commits 規範

git commit -m "feat: 新增使用者登入功能

  • 實作登入表單 UI
  • 整合 OAuth 2.0 認證
  • 加入 session 管理

Closes #123"

git commit -m "fix: 修復購物車商品數量錯誤

當使用者快速點擊加入購物車時,數量計算不正確。
改用 atomic 操作確保資料一致性。

Fixes #456"

git commit -m "refactor: 重構使用者服務層

將 UserService 拆分為:

  • UserAuthService (認證)
  • UserProfileService (個人資料)
  • UserPermissionService (權限管理)

目的:降低單一類別複雜度,提高可測試性"
Conventional Commits 格式:
<類型>(<範圍>): <簡短描述>

<詳細說明>

類型:

  • feat: 新功能
  • fix: 修復 bug
  • docs: 文件變更
  • style: 格式調整(不影響程式碼)
  • refactor: 重構(不是新功能也不是修 bug)
  • perf: 效能優化
  • test: 測試相關
  • chore: 建置工具、設定檔等

範例:
feat(auth): 新增 Google 登入
fix(cart): 修復結帳金額計算錯誤
docs(api): 更新 API 文件
refactor(user): 簡化使用者查詢邏輯


陷阱 4:PR 太大難以 Review
問題:
一個 PR 包含:

  • 50 個檔案
  • 3000 行程式碼
  • 5 個不同功能
  • 修改時間:2 週

結果:
❌ Reviewer 看不完
❌ 容易漏掉問題
❌ 討論混亂
❌ 合併困難
❌ 出問題難以追蹤
❌ 錯誤做法:超大 PR
PR #123: 使用者系統完整開發

變更檔案:52 個
新增:+2847 行
刪除:-1523 行

包含:

  • 登入功能
  • 註冊功能
  • 忘記密碼
  • 個人資料頁面
  • 權限管理
  • 郵件通知
  • API 重構
  • 資料庫 migration
  • 順便修了幾個 bug
    ✅ 正確做法:拆分小 PR
    PR #120: 使用者登入 API(+150 行)
    ├─ 實作登入 endpoint
    ├─ JWT token 生成
    └─ 單元測試

PR #121: 使用者登入 UI(+200 行)
├─ 登入表單元件
├─ 表單驗證
└─ 錯誤處理

PR #122: 註冊功能(+180 行)
├─ 註冊 API
├─ Email 驗證
└─ 測試

PR #123: 忘記密碼流程(+160 行)
├─ 重設密碼 API
├─ Email 發送
└─ 重設頁面
理想 PR 大小:
✅ 最佳:200-400 行
✅ 可接受:400-800 行
⚠️ 過大:800-1500 行(建議拆分)
❌ 太大:1500+ 行(必須拆分)

Review 時間:

  • 理想:30-60 分鐘
  • 超過 2 小時 → 品質會下降
    如何拆分大 PR:
    方法 1:按功能拆分
  • PR 1: 後端 API
  • PR 2: 前端 UI
  • PR 3: 測試和文件

方法 2:按層次拆分

  • PR 1: 資料模型
  • PR 2: 業務邏輯
  • PR 3: API 介面
  • PR 4: 前端整合

方法 3:先重構後功能

  • PR 1: 重構現有程式碼
  • PR 2: 新增新功能

方法 4:使用 stacked PRs

  • PR 1: 基礎設施
  • PR 2: (基於 PR 1) 核心功能
  • PR 3: (基於 PR 2) UI 整合

陷阱 5:衝突處理錯誤
常見錯誤:

  1. 不小心刪掉別人的程式碼
  2. 保留所有衝突標記
  3. 測試不充分就合併
  4. 用錯合併策略
    ❌ 危險的做法:

遇到衝突就全部用自己的版本

git checkout --ours .
git add .
git commit -m "fix conflicts"

❌ 這樣會刪除別人的所有改動!

✅ 正確的衝突處理流程:

1. 拉取最新版本

git fetch origin
git merge origin/main

2. 發現衝突

Auto-merging src/index.js
CONFLICT (content): Merge conflict in src/index.js
Automatic merge failed; fix conflicts and then commit.

3. 查看衝突檔案

git status

會列出有衝突的檔案

4. 手動編輯衝突檔案

vim src/index.js

衝突看起來像這樣:

<<<<<<< HEAD (你的版本)
function calculateTotal(items) {
return items.reduce((sum, item) => sum + item.price, 0);
}

function calculateTotal(items) {
return items.reduce((sum, item) => sum + (item.price * item.quantity), 0);
}

origin/main (遠端版本)

5. 理解兩邊的改動

你的版本:只加總價格

同事的版本:價格乘以數量

6. 決定保留哪個(或整合兩者)

function calculateTotal(items) {
// 整合兩個版本的優點
return items.reduce((sum, item) => {
const itemPrice = item.price || 0;
const itemQty = item.quantity || 1;
return sum + (itemPrice * itemQty);
}, 0);
}

7. 移除衝突標記

刪除 <<<<<<<, =======, >>>>>>> 這些行

8. 測試!重要!

npm test # 跑測試
npm run lint # 檢查語法

手動測試功能

9. 標記為已解決

git add src/index.js

10. 完成合併

git commit -m "merge: 解決 calculateTotal 衝突

整合兩個版本:

  • 保留數量計算邏輯(來自 main)
  • 加入 null 檢查(改進)

測試確認:

  • 購物車計算正確
  • 邊界條件處理正常"

11. 推送

git push origin feature/my-branch
衝突解決最佳實踐:
□ 不要慌張
□ 理解雙方的改動
□ 必要時詢問對方
□ 保留有價值的改動
□ 充分測試
□ 寫清楚解決方式
□ 複雜衝突可以結對處理


進階協作工作流程

  1. Git Flow(適合發版型專案)
    分支結構:
    main (production) → 正式環境,絕對穩定

    develop → 開發主線

    feature/* → 功能開發
    release/* → 發版準備
    hotfix/* → 緊急修復

工作流程:

  1. 從 develop 建立 feature 分支
  2. 開發完成後合併回 develop
  3. 準備發版時建立 release 分支
  4. release 測試完成後合併到 main 和 develop
  5. 緊急修復從 main 建立 hotfix 分支
  6. hotfix 完成後合併回 main 和 develop
    實際操作:

開始新功能

git checkout develop
git pull origin develop
git checkout -b feature/user-authentication

開發...

git commit -m "feat: 實作登入功能"

功能完成,合併回 develop

git checkout develop
git pull origin develop
git merge feature/user-authentication
git push origin develop

準備發版

git checkout -b release/v1.2.0

進行最後測試、修 bug

git commit -m "chore: 更新版本號到 1.2.0"

發版

git checkout main
git merge release/v1.2.0
git tag -a v1.2.0 -m "Release version 1.2.0"
git push origin main --tags

同步回 develop

git checkout develop
git merge release/v1.2.0
git push origin develop

刪除 release 分支

git branch -d release/v1.2.0
適合場景:
✅ 有明確的發版週期(每月、每季)
✅ 需要維護多個版本
✅ 有測試和發版流程
✅ 大型團隊


  1. GitHub Flow(適合持續部署)
    分支結構:
    main → 永遠可部署

    feature/* → 所有開發

工作流程:

  1. 從 main 建立分支
  2. 開發並多次 commit
  3. 建立 Pull Request
  4. Code Review
  5. 測試通過後合併到 main
  6. 立即部署到 production

特點:

  • 簡單
  • 快速
  • 持續部署
    實際操作:

1. 建立分支

git checkout main
git pull origin main
git checkout -b feature/add-payment

2. 開發

git commit -m "feat: 新增付款頁面"
git commit -m "feat: 整合金流 API"
git commit -m "test: 新增付款測試"

3. 推送並建立 PR

git push origin feature/add-payment

在 GitHub 建立 Pull Request

4. Code Review

同事提出建議,你修改

git commit -m "refactor: 改善錯誤處理"
git push origin feature/add-payment

5. Review 通過,合併到 main

(通常在 GitHub 網頁操作)

6. 自動部署

CI/CD 自動將 main 部署到 production

7. 刪除分支

git branch -d feature/add-payment
git push origin --delete feature/add-payment
適合場景:
✅ 持續部署
✅ 小型到中型團隊
✅ Web 應用
✅ 快速迭代


  1. Trunk-Based Development(適合高頻部署)
    分支結構:
    main (trunk) → 所有人都在這工作

    短期 feature 分支 → 存活 < 1 天

工作流程:

  1. 直接在 main 開發或建立極短期分支
  2. 頻繁整合(每天多次)
  3. Feature Flag 控制功能上線
  4. 快速回滾機制

特點:

  • 超短週期
  • 減少合併問題
  • 需要強大的自動化測試
    實際操作:

方式 1:直接在 main(需要很好的測試覆蓋)

git checkout main
git pull origin main

小修改

git commit -m "feat: 小功能改進"
git push origin main

方式 2:短期分支(早上建立,晚上合併)

git checkout -b feature/quick-fix

快速開發

git commit -m "feat: 實作功能"
git push origin feature/quick-fix

立即建立 PR,當天合併

使用 Feature Flag

if (featureFlags.newPaymentFlow) {
// 新付款流程
} else {
// 舊付款流程
}
適合場景:
✅ 高度自動化測試
✅ 成熟的 CI/CD
✅ 小型精英團隊
✅ 需要極快的反應速度


衝突解決進階技巧

  1. 使用 git rerere(重用記錄的解決方案)

啟用 rerere(reuse recorded resolution)

git config --global rerere.enabled true

好處:

Git 會記住你如何解決衝突

下次遇到相同衝突時自動套用

場景:

你在 feature 分支,多次合併 main

每次都遇到相同的衝突

有了 rerere,第二次開始會自動解決

  1. 使用工具輔助

VS Code 內建衝突解決

會顯示:

- Accept Current Change(保留你的)

- Accept Incoming Change(保留別人的)

- Accept Both Changes(保留兩者)

- Compare Changes(並排比較)

命令列工具

git mergetool # 開啟合併工具
git mergetool --tool=vimdiff # 使用 vimdiff
git mergetool --tool=meld # 使用 meld(圖形化)

配置預設工具

git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait --merge $REMOTE $LOCAL $BASE $MERGED'
3. 預防衝突的策略
策略 1:頻繁同步

  • 每天同步 main 到你的分支
  • 衝突分散處理,不會累積

策略 2:小而頻繁的 commits

  • 不要累積太多改動才 commit
  • 小 commits 更容易解決衝突

策略 3:溝通協調

  • 修改同一區域前先溝通
  • 使用 issue 標記正在修改的檔案

策略 4:程式碼組織

  • 避免巨大的檔案
  • 功能模組化,減少交集

策略 5:自動化測試

  • 充足的測試確保合併後功能正常
  • CI 自動檢查衝突

大型團隊協作最佳實踐

  1. 分支命名規範
    格式:<類型>/<issue 編號>-<簡短描述>

範例:
feature/123-user-authentication
bugfix/456-fix-login-error
hotfix/789-critical-security-patch
refactor/101-improve-database-queries
docs/202-update-api-documentation
test/303-add-unit-tests

好處:
✅ 一眼看出分支用途
✅ 關聯 issue tracking
✅ 容易搜尋和管理
✅ 自動化工具容易處理
2. PR 模板

📋 變更說明

🔗 相關 Issue

Closes #123
Related to #456

✨ 變更類型

  • [ ] 新功能
  • [ ] Bug 修復
  • [ ] 重構
  • [ ] 文件更新
  • [ ] 效能優化
  • [ ] 測試
  • [ ] 其他

📝 變更內容

  • 新增使用者登入功能
  • 實作 JWT 認證
  • 加入 session 管理

🧪 測試方式

  1. 前往 /login 頁面
  2. 輸入測試帳號:test@example.com
  3. 確認可以成功登入並跳轉到首頁

📸 截圖/影片(如適用)

⚠️ 注意事項

  • 需要更新環境變數 JWT_SECRET
  • 需要執行 database migration

✅ 檢查清單

  • [ ] 程式碼已自我 Review
  • [ ] 測試已通過
  • [ ] 文件已更新
  • [ ] 無 console.log 或 debug 程式碼
  • [ ] commit 訊息符合規範
  • [ ] 已同步最新的 main 分支
  1. Code Owners 設定

.github/CODEOWNERS

預設 owner

  • @team-leads

前端

/frontend/** @frontend-team
*.vue @frontend-team
*.jsx @frontend-team

後端

/backend/** @backend-team
*.go @backend-team

DevOps

/docker/** @devops-team
/.github/workflows/** @devops-team
Dockerfile @devops-team

資料庫

/migrations/** @database-team @backend-team
schema.sql @database-team

文件

/docs/** @tech-writers @team-leads
README.md @team-leads

關鍵檔案(需要多人審核)

package.json @team-leads @devops-team
.env.example @team-leads @security-team

好處:
✅ 自動分配 Reviewer
✅ 確保專業領域的人審核
✅ 關鍵檔案需要特定權限
4. PR 大小和頻率指標
理想指標:
📊 PR 大小:< 400 行
⏱️ PR 存活時間:< 1 天
👥 Review 時間:< 4 小時
♻️ Revision 次數:< 3 次
✅ 首次通過率:> 80%

追蹤方式:

使用 GitHub Actions 或 GitLab CI

自動產生 PR 統計報告

範例指標

週報:

  • 本週合併 PR:42 個
  • 平均大小:287 行
  • 平均存活時間:18 小時
  • 平均 Review 時間:2.5 小時
  1. 分支保護規則

GitHub 分支保護設定

main 分支:
✅ 需要 PR 才能合併
✅ 需要至少 2 個 approve
✅ 需要 CI 全部通過
✅ 需要更新到最新版本
✅ 管理員也必須遵守規則
✅ 禁止 force push
✅ 禁止刪除

develop 分支:
✅ 需要 PR 才能合併
✅ 需要至少 1 個 approve
✅ 需要 CI 通過
✅ 允許 force push(限管理員)

release/* 分支:
✅ 需要至少 3 個 approve
✅ 需要完整測試通過
✅ 需要安全掃描通過


自動化工具和 CI/CD 整合

  1. PR 自動檢查

.github/workflows/pr-check.yml

name: PR 檢查
on: [pull_request]

jobs:
pr-checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

  # 檢查 PR 大小
  - name: 檢查 PR 大小
    run: |
      LINES=$(git diff --stat ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | tail -1 | awk '{print $4+$6}')
      if [ $LINES -gt 800 ]; then
        echo "PR 太大!($LINES 行) 建議拆分"
        exit 1
      fi
  
  # 檢查 commit 訊息
  - name: 檢查 commit 訊息格式
    run: |
      # 檢查是否符合 Conventional Commits
      
  # 檢查分支名稱
  - name: 檢查分支名稱
    run: |
      BRANCH="${{ github.head_ref }}"
      if [[ ! $BRANCH =~ ^(feature|bugfix|hotfix|refactor)/.+ ]]; then
        echo "分支名稱不符合規範"
        exit 1
      fi
  
  # 跑測試
  - name: 執行測試
    run: npm test
  
  # 程式碼檢查
  - name: Lint
    run: npm run lint
  
  # 安全掃描
  - name: 安全掃描
    run: npm audit
  1. 自動化 Review 提示

.github/workflows/pr-labeler.yml

name: PR 標籤
on: [pull_request]

jobs:
label:
runs-on: ubuntu-latest
steps:
# 根據檔案變更自動加標籤
- uses: actions/labeler@v2
with:
configuration-path: .github/labeler.yml

  # 根據 PR 大小加標籤
  - name: 大小標籤
    run: |
      # < 100 行:size/XS
      # < 300 行:size/S
      # < 500 行:size/M
      # < 1000 行:size/L
      # > 1000 行:size/XL

處理複雜衝突的實戰案例
案例 1:重構和功能開發衝突
情境:
你:重構了整個使用者模組
同事:在舊結構上新增了登入功能

結果:大量檔案衝突
解決策略:

方法 1:分階段合併

Step 1: 先合併重構

git checkout main
git merge feature/refactor-user-module

Step 2: 同事在新結構上重新實作

git checkout feature/new-login
git rebase main

手動將登入功能適配到新結構

方法 2:結對解決

兩人一起坐下來

一起審視衝突

決定如何整合

方法 3:cherry-pick 重要 commits

git checkout feature/refactor-user-module
git cherry-pick <登入功能的關鍵 commits>

手動調整使其適配新結構

案例 2:merge 和 rebase 的選擇
Merge vs Rebase:
Merge(合併):
✅ 保留完整歷史
✅ 安全,不會改寫歷史
✅ 清楚看到分支合併點
❌ 歷史較複雜(多條線)
❌ 會產生 merge commit

Rebase(重新套用):
✅ 線性乾淨的歷史
✅ 沒有 merge commit
✅ 容易閱讀
❌ 改寫歷史(危險)
❌ 需要 force push
❌ 處理衝突較複雜

黃金法則:
🚫 永遠不要 rebase 公開的分支(main、develop)
✅ 只 rebase 你自己的 feature 分支
實際操作:

場景:你的 feature 分支需要同步 main

方法 1:Merge(安全,推薦給新手)

git checkout feature/my-feature
git merge main

解決衝突

git commit
git push origin feature/my-feature

優點:安全,不會破壞歷史

缺點:會產生 merge commit

方法 2:Rebase(整潔,適合進階使用者)

git checkout feature/my-feature
git rebase main

解決衝突(可能需要多次)

git rebase --continue

或放棄:git rebase --abort

git push origin feature/my-feature --force-with-lease

優點:歷史乾淨

缺點:改寫歷史,需要 force push

推薦策略:

- 開發中:使用 merge 同步

- 準備 PR 前:用 rebase -i 整理 commits

- 永遠不要 rebase 已經 push 的 commits(除非是你自己的分支)

案例 3:誤刪別人的程式碼
情境:
合併時不小心選錯,刪除了同事的程式碼
已經推送到遠端
現在需要找回
解決方法:

1. 找出被刪除的 commit

git log --all --grep="關鍵字"

git log --all --author="同事名字"

2. 查看該 commit 的內容

git show

3. 方法 1:cherry-pick 該 commit

git cherry-pick

4. 方法 2:從 reflog 找回

git reflog

找到刪除前的 commit

git reset --hard HEAD@{n}

5. 方法 3:從別人的 fork 找回

如果同事還有該 commit

git remote add colleague https://github.com/colleague/project.git
git fetch colleague
git cherry-pick colleague/branch-name

6. 預防措施:啟用回收站

git config --global alias.trash '!mkdir -p .git/trash && git log -1 --format=%H >> .git/trash/commits.txt'


團隊溝通協調技巧

  1. 使用 Draft PR 進行早期協作
    什麼是 Draft PR?
  • 草稿狀態的 Pull Request
  • 表示「還在開發中,但歡迎看看」
  • 無法合併

何時使用:
✅ 想要早期回饋
✅ 需要討論實作方向
✅ 展示進度
✅ 確認方向正確

範例:

## 🚧 [WIP] 使用者認證系統

**⚠️ 這是 Draft PR,尚未完成**

### 已完成
- [x] 基本登入 API
- [x] JWT token 生成

### 進行中
- [ ] 註冊功能(70% 完成)
- [ ] 密碼加密

### 待辦
- [ ] Email 驗證
- [ ] OAuth 整合

### 需要討論
1. JWT token 過期時間應該設定多久?
2. 是否需要 refresh token?
3. 密碼強度要求?

### 預計完成時間
明天下午

歡迎提供意見!特別是關於安全性的建議。

### **2. Slack/Teams 整合通知**

設定自動通知:
PR 建立: 「🆕 新 PR:feat: 使用者登入功能 👤 作者:@張三 🔗 連結:github.com/... 📝 需要 Review」
PR 被 Review: 「💬 @李四 評論了你的 PR 📍 位置:src/auth.js:45 💡 建議:建議加入參數驗證」
PR 被合併: 「✅ PR 已合併:feat: 使用者登入功能 👤 作者:@張三 🎉 辛苦了!」
CI 失敗: 「❌ CI 失敗:@張四 的 PR 📍 錯誤:測試未通過 🔗 詳情:...」
好處: ✅ 團隊即時知道進度 ✅ 不會漏掉重要通知 ✅ 減少郵件疲勞

### **3. 定期同步會議**

每日站會(10-15 分鐘):
•	昨天做了什麼
•	今天要做什麼
•	有什麼阻礙
每週技術同步(30-60 分鐘):
•	Review 複雜的 PR
•	討論架構決策
•	分享學習心得
•	規劃下週重點
每月回顧(1-2 小時):
•	分析指標(PR 大小、Review 時間等)
•	討論流程改進
•	慶祝成就

---

## **處理特殊情境**

### **情境 1:需要緊急修復但分支很亂**

```bash
# 當前狀況:
# feature 分支有 10 個 commits,都還沒整理
# 突然發現 production 有嚴重 bug 需要立刻修

# 解決方案:Stash 工作,切換處理
git stash push -u -m "開發中:使用者功能"
git checkout main
git pull origin main
git checkout -b hotfix/critical-bug

# 快速修復
vim src/payment.js
git add src/payment.js
git commit -m "hotfix: 修復付款金額計算錯誤

在特殊優惠情境下,計算公式錯誤導致金額不正確。
已修正並加入測試。

Fixes #999"

# 立即部署
git push origin hotfix/critical-bug
# 建立緊急 PR,快速 Review 和合併

# 修復完成,回到原本工作
git checkout feature/user-feature
git stash pop
# 繼續開發
情境 2:多人同時修改同一功能
問題:
三個人同時要改進搜尋功能
- A:改進演算法
- B:優化效能
- C:新增篩選條件

容易產生大量衝突

解決策略:
```bash
# 方法 1:分層實作(推薦)
# 定義清楚的介面,分工開發

# A 負責核心邏輯
class SearchEngine {
  search(query, filters) {
    // 搜尋邏輯
  }
}

# B 負責快取層
class SearchCache {
  // 快取邏輯
}

# C 負責 UI 層
class SearchUI {
  // 介面邏輯
}

# 方法 2:使用 Feature Flag
if (featureFlags.newSearchAlgorithm) {
  // A 的新演算法
} else {
  // 舊演算法
}

# 各自開發,透過 flag 控制,減少衝突

# 方法 3:時間錯開
# 週一:A 先做,其他人等
# 週三:A 完成並合併
# 週四:B 和 C 基於 A 的版本繼續
情境 3:回滾已合併的 PR
# 情境:PR 合併後發現嚴重問題

# 方法 1:Revert(推薦,安全)
git checkout main
git pull origin main
git revert <merge-commit-hash>
# 會建立一個新的 commit 來撤銷變更

git push origin main
# 保留歷史,但功能被移除

# 方法 2:直接在 GitHub Revert
# GitHub PR 介面有 "Revert" 按鈕
# 會自動建立一個 revert PR

# 方法 3:Reset(危險!僅限緊急狀況)
git reset --hard <merge-commit-hash>^
git push origin main --force
# ⚠️ 會改寫歷史,只在緊急且團隊同意時使用

# 後續:修復問題後重新提交
git revert <revert-commit-hash>  # 撤銷 revert
# 修復原本的問題
git commit -m "fix: 修復原本問題並重新上線"
________________________________________
效能優化和大型 Repo 管理
1. Git 效能優化
# 淺層 clone(節省空間和時間)
git clone --depth 1 https://github.com/user/repo.git
# 只下載最近一次 commit 的歷史

# Sparse checkout(只下載部分檔案)
git clone --filter=blob:none --sparse https://github.com/user/repo.git
cd repo
git sparse-checkout set src/frontend
# 只下載 frontend 目錄

# 部分 clone
git clone --filter=blob:limit=1m https://github.com/user/repo.git
# 只下載小於 1MB 的檔案,大檔案延遲下載

# 定期維護
git gc --aggressive          # 垃圾回收
git prune                    # 清理無用物件
git repack -Ad               # 重新打包

# 加速 git status
git config core.fsmonitor true
git config core.untrackedCache true
2. 大型二進位檔案處理
# 使用 Git LFS(Large File Storage)
git lfs install

# 追蹤大型檔案
git lfs track "*.psd"
git lfs track "*.mp4"
git lfs track "*.zip"

# .gitattributes 會自動更新
git add .gitattributes

# 正常 commit
git add design.psd
git commit -m "feat: 新增設計檔"
git push

# 好處:
# - 倉庫保持輕量
# - 大檔案存在 LFS server
# - clone 時可以選擇不下載 LFS 檔案
3. Monorepo 管理
# Monorepo 結構範例
repo/
├── packages/
│   ├── frontend/
│   ├── backend/
│   ├── mobile/
│   └── shared/
├── tools/
└── docs/

# 使用 Git worktree(多個工作目錄)
git worktree add ../repo-frontend packages/frontend
git worktree add ../repo-backend packages/backend

# 在不同視窗同時開發不同 package

# 使用 submodule(不推薦,但有時需要)
git submodule add https://github.com/user/lib.git libs/external
git submodule update --init --recursive

# 更好的方案:pnpm workspace 或 yarn workspace
# 搭配 Turborepo 或 Nx
________________________________________
安全性最佳實踐
1. 保護敏感資訊
# 永遠不要 commit 的東西:
❌ .env 檔案
❌ 密碼、API keys
❌ SSL 憑證
❌ 資料庫備份
❌ node_modules/

# .gitignore 必備項目
.env
.env.local
*.key
*.pem
secrets/
*.log
node_modules/
.DS_Store

# 如果不小心 commit 了敏感資訊
# 方法 1:還沒 push
git reset --soft HEAD^
# 修改檔案
git add .
git commit -m "..."

# 方法 2:已經 push(嚴重)
# 1. 立即更改密碼/key
# 2. 使用 git filter-branch 清理歷史
git filter-branch --force --index-filter \
  "git rm --cached --ignore-unmatch .env" \
  --prune-empty --tag-name-filter cat -- --all

# 3. Force push(通知所有團隊成員)
git push origin --force --all

# 4. 更好的工具:BFG Repo-Cleaner
java -jar bfg.jar --delete-files .env
git reflog expire --expire=now --all
git gc --prune=now --aggressive
2. 簽署 Commits
# 設定 GPG 簽署(驗證身分)
# 1. 產生 GPG key
gpg --gen-key

# 2. 列出 keys
gpg --list-secret-keys --keyid-format LONG

# 3. 設定 Git 使用該 key
git config --global user.signingkey <your-key-id>

# 4. 自動簽署所有 commits
git config --global commit.gpgsign true

# 5. 簽署 commit
git commit -S -m "feat: 新增功能"

# 6. 驗證簽署
git log --show-signature

# GitHub 會顯示 "Verified" 標誌
3. 審查 PR 的安全性檢查清單
□ 沒有硬編碼的密碼或 keys
□ 使用參數化查詢(防 SQL injection)
□ 輸入驗證完整
□ 敏感資料有加密
□ 使用 HTTPS
□ CORS 設定正確
□ 沒有洩漏內部資訊到錯誤訊息
□ 依賴套件沒有已知漏洞
□ 權限檢查正確
□ 日誌不包含敏感資訊
________________________________________
團隊協作指標和改進
追蹤的關鍵指標
PR 指標:
📊 平均 PR 大小:目標 < 400 行
⏱️ 平均 Review 時間:目標 < 4 小時
📅 PR 存活時間:目標 < 1 天
✅ 首次通過率:目標 > 80%
🔄 平均 revision 次數:目標 < 3 次

部署指標:
🚀 部署頻率:目標每天 > 1 次
⏱️ Lead Time:目標 < 1 天
🔙 變更失敗率:目標 < 5%
⚡ MTTR (平均修復時間):目標 < 1 小時

協作指標:
💬 Code Review 參與度:目標 > 90%
📝 文件覆蓋率:目標 > 80%
🧪 測試覆蓋率:目標 > 80%
持續改進流程
每月回顧會議 Agenda:

1. 數據回顧(15 分鐘)
   - 查看指標趨勢
   - 識別問題區域

2. 問題討論(30 分鐘)
   - 最常見的衝突來源?
   - Review 為什麼慢?
   - 哪些流程卡住了?

3. 改進建議(20 分鐘)
   - 每人提出 1-2 個改進點
   - 投票選出優先項目

4. 行動計畫(10 分鐘)
   - 指派負責人
   - 設定時間表
   - 定義成功標準

5. 慶祝成就(5 分鐘)
   - 表揚好的 PR
   - 分享學習心得
________________________________________
快速參考清單
每日協作 Checklist
早上開工:
□ git pull origin main
□ 同步到你的 feature 分支
□ 查看 Slack 通知
□ 檢查分配給你的 PR

開發中:
□ 小步前進,頻繁 commit
□ commit 訊息清楚
□ 定期推送到遠端

準備 PR:
□ 自我 Review
□ 跑所有測試
□ 更新文件
□ 填寫 PR 描述
□ 同步最新 main

Review 別人的 PR:
□ 優先處理緊急的
□ 在 4 小時內回應
□ 提供建設性意見
□ 讚美好的部分

下班前:
□ 推送所有 commits
□ 回應 Review 意見
□ 更新 issue 狀態
緊急狀況處理
Production 壞了:
1. 立即告知團隊
2. 從 main 建立 hotfix 分支
3. 快速修復並測試
4. 緊急 PR 並快速 Review
5. 部署
6. 事後檢討

不小心刪掉重要檔案:
1. 不要慌張
2. 使用 git reflog 找回
3. 或從同事那邊拿回
4. 檢討為什麼會發生

大量衝突無法處理:
1. 不要硬幹
2. 找相關同事討論
3. 考慮分階段合併
4. 必要時重新實作

CI 持續失敗:
1. 在本地重現問題
2. 逐一檢查失敗的測試
3. 修復後再推送
4. 不要 skip 測試
________________________________________
工具推薦
Git GUI 工具
入門級:
- GitHub Desktop(簡單易用)
- GitKraken(視覺化強)
- SourceTree(功能完整)

進階:
- Fork(效能好)
- Tower(專業級)
- Sublime Merge(極簡)

IDE 整合:
- VS Code Git 擴充
- IntelliJ IDEA 內建
- Vim Fugitive
協作增強工具
Code Review:
- GitHub PR
- GitLab MR
- Gerrit(Android 使用)
- Phabricator

文件協作:
- Notion(團隊文件)
- Confluence(企業級)
- GitHub Wiki

專案管理:
- GitHub Projects
- Jira
- Linear
- Asana

溝通:
- Slack(即時)
- Discord(開源社群)
- Microsoft Teams(企業)
________________________________________
今日重點回顧
✅ 核心概念
協作陷阱:
1. 直接在 main 工作 → 用 feature branch
2. 忘記同步遠端 → 每天 pull
3. 提交訊息隨便 → 用 Conventional Commits
4. PR 太大 → 拆分成小 PR
5. 衝突處理錯誤 → 理解雙方改動

工作流程:
- Git Flow:適合發版型專案
- GitHub Flow:適合持續部署
- Trunk-Based:適合高頻部署

最佳實踐:
- 分支命名規範
- PR 模板
- Code Owners
- 自動化檢查
- 團隊溝通
🎯 行動計畫
立即實施:
□ 建立分支命名規範
□ 設定 PR 模板
□ 配置分支保護規則
□ 啟用 CI 自動檢查

本週實施:
□ 團隊討論工作流程
□ 設定 Code Owners
□ 建立協作文件
□ 追蹤協作指標

持續改進:
□ 每月回顧指標
□ 優化流程
□ 分享最佳實踐
□ 慶祝進步
________________________________________
常見問題 FAQ
Q1: 什麼時候該用 merge,什麼時候該用 rebase?
Merge:
- 合併公開分支(main、develop)
- 保留完整歷史
- 團隊共享的分支

Rebase:
- 整理自己的 feature 分支
- 準備 PR 前清理 commits
- 保持線性歷史

黃金法則:永遠不要 rebase 公開的分支!
Q2: PR 被要求修改很多次,怎麼辦?
心態調整:
✅ Review 是幫助你成長
✅ 批評程式碼不是批評你
✅ 學習機會

實際做法:
1. 仔細閱讀每個建議
2. 不懂就問
3. 同意就改
4. 不同意就討論
5. 感謝 Reviewer 的時間

預防:
- 提交前自我 Review
- 小而頻繁的 PR
- 早期使用 Draft PR 獲得回饋
Q3: 團隊成員不愛做 Code Review 怎麼辦?
問題診斷:
- PR 太大?→ 拆小
- 沒時間?→ 排入工作時程
- 不知道怎麼 Review?→ 提供指南
- 沒有激勵?→ 建立文化

解決方案:
1. 設定 Review SLA(回應時間)
2. 輪流擔任 Reviewer
3. 在 standup 提醒
4. 表揚好的 Review
5. 將 Review 納入績效
Q4: 如何處理團隊中的「Git 新手」?
教育方式:
1. Pair Programming(結對)
2. 提供簡單的指南
3. 犯錯時耐心協助
4. 分享實際案例
5. 建立安全環境

保護機制:
- 分支保護規則
- CI 自動檢查
- Pre-commit hooks
- 資深成員 Review

循序漸進:
- 從簡單任務開始
- 逐步增加複雜度
- 定期 1-on-1 指導
Q5: 如何平衡速度和品質?
不同情境不同策略:

Hotfix(緊急修復):
- 速度優先
- 但仍需 Review
- 可以降低標準
- 事後補充測試

一般功能:
- 平衡速度和品質
- 合理的 Review 標準
- 不過度追求完美

核心系統:
- 品質優先
- 嚴格 Review
- 充足的測試
- 多人審核

實驗性功能:
- 允許較低品質
- 快速驗證想法
- Feature Flag 控制
- 成功後再優化
________________________________________
明天預告
Day 25 - Git 進階操作與疑難雜症
•	深入 Git 內部運作
•	處理各種棘手情況
•	資料恢復技巧
•	進階操作指令
________________________________________
總結
多人協作的本質:
不只是技術,更是溝通和文化

技術層面:
✅ 選擇合適的工作流程
✅ 建立清楚的規範
✅ 自動化能自動化的

文化層面:
✅ 建立信任和尊重
✅ 鼓勵知識分享
✅ 持續學習改進
✅ 慶祝成功

記住:
最好的工具是人
最好的流程是團隊認同的流程
最好的實踐是不斷演進的實踐


上一篇
Day 23:Code Review 最佳實務 - 提升程式碼品質
下一篇
Day 25:Git 安全性 - 保護你的程式碼
系列文
30天 Git 版本控制實戰筆記30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言