はじめに
これまでの章で学んだGitとGitHubの機能を統合し、実際のチーム開発で使われる ワークフローを構築します。この章では、Git Flow、GitHub Flow、GitLab Flowなどの 代表的な開発フローを比較し、プロジェクトに最適なワークフローを選択・カスタマイズ する方法を学びます。
完璧なワークフローは存在しません。チームの規模、プロジェクトの性質、リリースサイクルに応じて最適なフローを選択し、継続的に改善することが重要です。
5.1 代表的な開発フローの比較
Git Flow
特徴
Vincent Driessenによって提案された、最も構造化されたワークフロー
ブランチ構成
- master/main - 本番環境のコード
- develop - 開発の統合ブランチ
- feature/* - 機能開発ブランチ
- release/* - リリース準備ブランチ
- hotfix/* - 緊急修正ブランチ
# Git Flow の初期化
git flow init
# フィーチャーブランチの開始
git flow feature start user-authentication
# フィーチャーの完了(developにマージ)
git flow feature finish user-authentication
# リリースの開始
git flow release start 1.0.0
# リリースの完了(masterとdevelopにマージ)
git flow release finish 1.0.0
# ホットフィックスの開始
git flow hotfix start critical-security-fix
# ホットフィックスの完了
git flow hotfix finish critical-security-fix
メリット
- 明確な役割分担とブランチ戦略
- 大規模プロジェクトに適している
- リリースサイクルが明確
デメリット
- 複雑で学習コストが高い
- 継続的デプロイには不向き
- ブランチが多くなりがち
GitHub Flow
特徴
GitHubが推奨するシンプルなワークフロー
基本的な流れ
- mainブランチは常にデプロイ可能な状態
- 新機能はフィーチャーブランチで開発
- 定期的にコミットしてリモートにプッシュ
- プルリクエストを作成してレビュー
- レビュー後、mainにマージ
- 即座にデプロイ
# メインブランチから新しいブランチを作成
git checkout -b feature/add-payment-system
# 作業を進めてコミット
git add .
git commit -m "feat: 支払いシステムの基本実装"
# リモートにプッシュ
git push -u origin feature/add-payment-system
# GitHub上でプルリクエストを作成
# レビューとCI/CDのチェックが完了後、マージ
# マージ後、ローカルを更新
git checkout main
git pull origin main
# 不要になったブランチを削除
git branch -d feature/add-payment-system
メリット
- シンプルで理解しやすい
- 継続的デプロイに最適
- コラボレーションが容易
デメリット
- 複数バージョンの管理には不向き
- リリース管理が曖昧になりがち
GitLab Flow
特徴
環境ブランチを活用した中間的なアプローチ
環境ブランチ戦略
main └─> staging (ステージング環境) └─> production (本番環境) または main ├─> develop (開発環境) ├─> staging (ステージング環境) └─> production (本番環境)
メリット
- 環境ごとの管理が明確
- Git FlowとGitHub Flowの良いとこ取り
- 柔軟性が高い
デメリット
- チームでの理解統一が必要
- 環境間の同期に注意が必要
ワークフロー比較表
項目 | Git Flow | GitHub Flow | GitLab Flow |
---|---|---|---|
複雑さ | 高い | 低い | 中程度 |
リリース頻度 | 定期的 | 継続的 | 柔軟 |
チーム規模 | 大規模向け | 小〜中規模向け | 中〜大規模向け |
適用プロジェクト | エンタープライズ | Webサービス | 汎用 |
実践演習 5.1
各ワークフローの体験:
- 3つの練習用リポジトリを作成
- それぞれでGit Flow、GitHub Flow、GitLab Flowを実践
- 同じ機能追加を3つのフローで実装
- それぞれの利点と課題を記録
- 自分のプロジェクトに最適なフローを選択
5.2 フィーチャーブランチ戦略
効果的なブランチ命名規則
推奨される命名パターン
タイプ | パターン | 例 |
---|---|---|
機能追加 | feature/[issue-id]-[description] |
feature/123-user-authentication |
バグ修正 | bugfix/[issue-id]-[description] |
bugfix/456-login-error |
緊急修正 | hotfix/[issue-id]-[description] |
hotfix/789-security-patch |
リファクタ | refactor/[description] |
refactor/api-structure |
実験的 | experiment/[description] |
experiment/new-algorithm |
ブランチのライフサイクル管理
ブランチ管理のベストプラクティス
1. ブランチ作成時
# 最新のmainから作成
git checkout main
git pull origin main
git checkout -b feature/234-shopping-cart
# Issueと関連付け(コミットメッセージで)
git commit -m "feat: ショッピングカート機能の初期実装 #234"
2. 開発中
- 定期的にmainの変更を取り込む(リベースまたはマージ)
- 意味のある単位でコミット
- CIが通ることを確認
# mainの最新変更を取り込む(リベース)
git fetch origin
git rebase origin/main
# コンフリクトが発生した場合
git status # コンフリクトファイルを確認
# ファイルを編集して解決
git add .
git rebase --continue
3. マージ後
# ローカルブランチの削除
git branch -d feature/234-shopping-cart
# リモートブランチの削除(GitHub上で自動削除も可)
git push origin --delete feature/234-shopping-cart
# 古いブランチの一括削除
git remote prune origin
git branch --merged | grep -v main | xargs -n 1 git branch -d
長期ブランチの管理
ブランチが長期化すると以下の問題が発生します:
- マージコンフリクトの増加
- レビューの困難化
- バグの混入リスク
- 他の開発との整合性の喪失
長期ブランチを避ける方法
- 機能を小さく分割
- 大きな機能は複数の小さなPRに分割
- 各PRは1-3日で完了できるサイズに
- フィーチャーフラグの活用
if (featureFlags.newShoppingCart) { // 新機能のコード } else { // 既存のコード }
- 継続的な統合
- 未完成でも動作する状態でマージ
- UIは非表示、APIはドキュメントのみなど
5.3 CI/CDとの統合
継続的インテグレーション(CI)の実装
CIは、コードの変更を頻繁に統合し、自動的にビルド・テストを実行するプラクティスです。 GitHub Actionsを使用した実装例を見ていきましょう。
基本的なCIワークフロー
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x, 18.x, 20.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
- name: Run tests
run: npm test -- --coverage
- name: Upload coverage reports
uses: codecov/codecov-action@v3
with:
file: ./coverage/lcov.info
- name: Build
run: npm run build
- name: Run E2E tests
run: npm run test:e2e
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run security audit
run: npm audit
- name: Run Snyk scan
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
ブランチ保護ルールの設定
推奨される保護ルール
- ✓ Require pull request reviews before merging
- 必要な承認数: 1-2
- コードオーナーからの承認を要求
- 古い承認を却下
- ✓ Require status checks to pass before merging
- CI/CDパイプラインの成功
- コードカバレッジの基準
- セキュリティスキャン
- ✓ Require branches to be up to date before merging
- ✓ Require conversation resolution before merging
- ✓ Include administrators(推奨)
継続的デプロイメント(CD)の実装
環境別デプロイメント戦略
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches:
- main
- staging
- develop
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set environment
run: |
if [[ ${{ github.ref }} == 'refs/heads/main' ]]; then
echo "ENVIRONMENT=production" >> $GITHUB_ENV
echo "DEPLOY_URL=https://app.example.com" >> $GITHUB_ENV
elif [[ ${{ github.ref }} == 'refs/heads/staging' ]]; then
echo "ENVIRONMENT=staging" >> $GITHUB_ENV
echo "DEPLOY_URL=https://staging.example.com" >> $GITHUB_ENV
else
echo "ENVIRONMENT=development" >> $GITHUB_ENV
echo "DEPLOY_URL=https://dev.example.com" >> $GITHUB_ENV
fi
- name: Build application
run: |
npm ci
npm run build:${{ env.ENVIRONMENT }}
- name: Deploy to ${{ env.ENVIRONMENT }}
uses: peaceiris/actions-gh-pages@v3
if: env.ENVIRONMENT == 'production'
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist
cname: app.example.com
- name: Notify deployment
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
text: |
Deployment to ${{ env.ENVIRONMENT }} ${{ job.status }}
URL: ${{ env.DEPLOY_URL }}
Commit: ${{ github.sha }}
Author: ${{ github.actor }}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
品質ゲートの実装
自動品質チェック
コードカバレッジ
> 80%
技術的負債
< 5%
セキュリティ脆弱性
0
5.4 リリース管理
セマンティックバージョニング
バージョン番号の構成
- MAJOR: 後方互換性のない変更
- MINOR: 後方互換性のある機能追加
- PATCH: 後方互換性のあるバグ修正
例:
1.0.0
→2.0.0
: APIの破壊的変更1.0.0
→1.1.0
: 新機能の追加1.0.0
→1.0.1
: バグ修正1.0.0-alpha.1
: プレリリース版
リリースワークフロー
自動リリースプロセス
# .github/workflows/release.yml
name: Release
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # 全履歴を取得
- name: Generate changelog
id: changelog
run: |
PREVIOUS_TAG=$(git describe --tags --abbrev=0 HEAD^)
CHANGELOG=$(git log $PREVIOUS_TAG..HEAD --pretty=format:"- %s" --no-merges)
echo "CHANGELOG<> $GITHUB_ENV
echo "$CHANGELOG" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- name: Create Release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
body: |
## 変更内容
${{ env.CHANGELOG }}
## インストール
```bash
npm install @company/package@${{ github.ref }}
```
draft: false
prerelease: false
- name: Publish to npm
run: |
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc
npm publish
リリースノートの自動生成
コミットメッセージからの自動生成
Conventional Commitsを使用することで、意味のあるリリースノートを自動生成できます:
タイプ | リリースノート | バージョン影響 |
---|---|---|
feat: |
新機能 | MINOR |
fix: |
バグ修正 | PATCH |
docs: |
ドキュメント | なし |
BREAKING CHANGE: |
破壊的変更 | MAJOR |
ロールバック戦略
本番環境へのデプロイでは、常にロールバック計画を用意しておくことが重要です。
# タグを使った迅速なロールバック
# 現在のバージョンを確認
git describe --tags
# 前のバージョンにロールバック
git checkout v1.2.3
npm run deploy:production
# または、リバートコミットを作成
git revert --no-commit HEAD~3..HEAD
git commit -m "revert: v1.3.0の変更を取り消し"
git push origin main
実践演習 5.2
完全な開発フローの実践:
- 新機能のIssueを作成
- フィーチャーブランチで開発
- CIパイプラインを設定(テスト、リント、ビルド)
- プルリクエストを作成してレビュー
- マージ後、自動デプロイを確認
- セマンティックバージョニングに従ってリリース
- リリースノートの自動生成を確認
5.5 チーム開発のベストプラクティス
コードオーナーシップ
CODEOWNERSファイルの活用
# .github/CODEOWNERS
# グローバルオーナー
* @tech-lead @senior-dev
# フロントエンド
/frontend/ @frontend-team
/src/components/ @ui-team
*.css @design-team
*.scss @design-team
# バックエンド
/backend/ @backend-team
/api/ @api-team
/database/ @database-admin
# インフラ
/infrastructure/ @devops-team
/.github/workflows/ @devops-team
/docker/ @devops-team
Dockerfile @devops-team
# ドキュメント
/docs/ @documentation-team
*.md @documentation-team
# 特定の重要ファイル
/src/auth/ @security-team @tech-lead
/src/payment/ @payment-team @security-team
コミュニケーションガイドライン
効果的なコミュニケーション
プルリクエストでのコミュニケーション
- 明確な説明: 何を、なぜ変更したかを説明
- スクリーンショット: UI変更は必ず添付
- テスト手順: レビュアーが確認できる手順を記載
- 関連リンク: Issue、設計書、参考資料へのリンク
コードレビューのエチケット
- 24時間以内にレビュー開始
- 建設的なフィードバック
- 代替案の提示
- 良い点も指摘
- レビュー可能なサイズに分割
- セルフレビューの実施
- フィードバックへの迅速な対応
- 議論は前向きに
ドキュメンテーション戦略
プロジェクトドキュメントの構成
project-root/ ├── README.md # プロジェクト概要 ├── CONTRIBUTING.md # 貢献ガイド ├── CODE_OF_CONDUCT.md # 行動規範 ├── SECURITY.md # セキュリティポリシー ├── docs/ │ ├── architecture/ # アーキテクチャ設計書 │ ├── api/ # APIドキュメント │ ├── guides/ # 開発ガイド │ └── decisions/ # 技術的決定記録(ADR) ├── .github/ │ ├── ISSUE_TEMPLATE/ │ ├── PULL_REQUEST_TEMPLATE.md │ └── workflows/
知識共有の仕組み
チーム内での知識共有
- 定期的な勉強会: 新技術や設計パターンの共有
- ペアプログラミング: 知識の直接的な伝達
- コードレビュー: 実装を通じた学習
- Wiki/Confluence: 永続的な知識ベース
- Slack/Teams: 日常的な質問と回答
開発メトリクスの活用
重要な指標
サイクルタイム
コード作成からデプロイまでの時間
目標: < 2日
PRサイズ
変更行数の平均
目標: < 400行
レビュー時間
PRオープンからマージまで
目標: < 24時間
5.6 まとめと次のステップ
この章で学んだこと
- Git Flow、GitHub Flow、GitLab Flowの比較と選択
- 効果的なブランチ戦略とライフサイクル管理
- CI/CDパイプラインの構築と品質ゲート
- セマンティックバージョニングとリリース管理
- チーム開発のベストプラクティス
開発フローのチェックリスト
プロジェクト開始時
- 適切なワークフローの選択
- ブランチ命名規則の決定
- CI/CDパイプラインの設定
- ブランチ保護ルールの設定
- CODEOWNERSファイルの作成
日常の開発
- フィーチャーブランチでの開発
- 定期的なmainとの同期
- 意味のあるコミットメッセージ
- PRの適切なサイズ維持
- タイムリーなレビュー対応
理解度チェック
確認問題
- Git FlowとGitHub Flowの主な違いを3つ挙げてください
- 長期ブランチを避けるべき理由を説明してください
- CI/CDパイプラインに含めるべき要素を5つ挙げてください
- セマンティックバージョニングのルールを説明してください
- 効果的なコードレビューの特徴を3つ挙げてください
次章への準備
第6章では、GitHub Actionsを使った自動化について詳しく学びます。 CI/CDの基礎を理解した上で、より高度な自動化ワークフローの構築方法を マスターしましょう。
この章で学んだ内容は、実際のプロジェクトで試してみることが重要です。 小さなプロジェクトから始めて、徐々に複雑なワークフローに挑戦してください。 失敗を恐れず、チームと共に最適なフローを見つけていきましょう。