Gitワークフローガイド:ブランチ、マージ、チームコラボレーション
Gitのブランチ戦略、コミットのベストプラクティス、リベースとマージの違い、プロのエンジニアリングチームが使用するワークフローをマスターしよう。
Gitはあらゆる現代のソフトウェアチームのワークフローの基盤です。しかし多くの開発者は commit、push、pull しか使っておらず、チーム開発をスムーズにしコンフリクトを防ぐための機能を活用できていません。このガイドでは、プロのチームが実践するブランチ戦略、コミットの習慣、日常的なコマンドを解説します。
基本的なメンタルモデル
Gitはスナップショット(コミット)の有向非巡回グラフです。各コミットは親コミットを指しています。ブランチはコミットへの名前付きポインタに過ぎず、軽量で作成コストもほぼゼロです。
main: A → B → C → D
feature: C → E → F
ブランチはファイルをコピーしません。新しいポインタを作るだけです。だからこそ、リポジトリのサイズに関係なくブランチの作成はミリ秒で完了します。
ブランチ戦略
GitHub Flow(シンプル、継続的デリバリー向け)
頻繁にデプロイするチームに最適:
mainは常にデプロイ可能な状態に保つ- すべての変更にフィーチャーブランチを作成する
- レビュー準備ができたらプルリクエストを開く
- 承認後に
mainへマージする - 即座にデプロイする
git checkout -b feature/add-user-auth
# ... 変更を加える ...
git push origin feature/add-user-auth
# PR作成 → レビュー → マージ → デプロイ
Git Flow(構造化されたリリース向け)
バージョン管理されたリリースを行うプロダクト(アプリ、ライブラリ)に最適:
main— 本番コードのみdevelop— 統合ブランチfeature/*— 新機能(developからブランチを切る)release/*— リリース準備(developからブランチを切る)hotfix/*— 緊急の本番修正(mainからブランチを切る)
より構造化されていますがオーバーヘッドが増えます。並行リリース管理が本当に必要な場合を除き、GitHub Flowを使いましょう。
トランクベース開発
開発者は main(または1日未満の短命なブランチ)に直接コミットします。ユーザーに何を見せるかはフィーチャーフラグで制御します。強力なCI/CDとテストカバレッジが必要です。Google、Facebook、および開発速度の高いチームで採用されています。
良いコミットメッセージの書き方
コミットメッセージは未来の自分(とチームメンバー)への手紙です。Conventional Commitsフォーマットに従いましょう:
<type>(<scope>): <短い要約>
<任意の本文 — 何を、なぜ。どのようにではなく>
<任意のフッター — 破壊的変更、issueの参照>
タイプ:
feat— 新機能fix— バグ修正docs— ドキュメントのみの変更refactor— バグ修正でも機能追加でもないコード変更test— テストの追加または修正chore— ビルドプロセス、依存関係、ツール関連
例:
feat(auth): add JWT refresh token rotation
Implements sliding session windows using refresh token rotation.
Previous tokens are invalidated on use to detect theft.
Closes #142
fix(api): return 404 instead of 500 for missing user
The /users/:id endpoint was throwing an unhandled exception when
the user didn't exist. Now returns a proper 404 with error message.
目安: コミットメッセージが
fix stuffやWIPなら、チームメンバーに迷惑をかけています。具体的に書きましょう。
マージ vs. リベース
マージ
git checkout main
git merge feature/my-feature
2つのブランチを結合するマージコミットを作成します。完全な履歴が保持されるため、ブランチがいつ分岐してマージされたかを正確に確認できます。
A → B → C → M (マージコミット)
↑ ↑
E → F (feature)
マージを使う場面:長期間のブランチを統合するとき、履歴のコンテキストを保持したいとき。
リベース
git checkout feature/my-feature
git rebase main
コミットをターゲットブランチの先頭に再適用します。線形な履歴が生成され、フィーチャーが最新の main の上に構築されたかのように見えます。
Before: A → B → C (main)
↑
D → E (feature, based off B)
After: A → B → C → D' → E' (feature rebased onto C)
リベースを使う場面:PR前にローカルのコミットを整理するとき、フィーチャーブランチを最新の状態に保つとき。
鉄則: 共有ブランチにプッシュ済みのコミットはリベースしないこと。リベースは履歴を書き換えるため、他のメンバーのローカルブランチが壊れます。
インタラクティブリベース:履歴の整理
PR作成前に、作業中の雑然としたコミットをまとめて整理しましょう:
git rebase -i HEAD~4 # 直近4コミットをインタラクティブに編集
インタラクティブエディタのオプション:
pick— コミットをそのまま残すsquash— 前のコミットにマージし、メッセージを結合するfixup— 前のコミットにマージし、メッセージを破棄するreword— 変更を残し、メッセージを編集するdrop— コミットを完全に削除する
コンフリクトの解決
コンフリクトは2つのブランチが同じ行を変更したときに発生します。Gitは次のようにマークします:
<<<<<<< HEAD (your branch)
const timeout = 5000;
=======
const timeout = 3000;
>>>>>>> feature/update-timeouts
ファイルを正しい状態に編集して(マーカーを削除してから)、以下を実行します:
git add src/config.ts
git merge --continue # または git rebase --continue
予防は治療に勝る:
mainから頻繁にプルしてブランチを短命に保つ- 同じファイルで作業するときはチームメンバーと連携する
- PRを小さく保つ — 大きなPRはコンフリクトが増えレビューも難しくなる
日常的な必須コマンド
# 新しいフィーチャーを開始する
git checkout -b feature/my-feature
# 特定の変更だけをステージする(ファイル全体ではなく)
git add -p
# ステージされていない変更を確認する
git diff
# ステージされた変更を確認する
git diff --staged
# 直前のコミットを修正する(プッシュ前)
git commit --amend --no-edit
# コミットされていない作業を一時的に退避する
git stash
git stash pop
# バグを導入したコミットを特定する(二分探索)
git bisect start
git bisect bad # 現在のコミットはバグあり
git bisect good v1.2.0 # 最後に正常だったコミット
# 削除したブランチや失ったコミットを復元する
git reflog
# ブランチのビジュアルグラフを表示する
git log --oneline --graph --all
プルリクエストのベストプラクティス
良いPRとは:
- 1つのことだけ行う — レビュアーが変更全体を把握できる
- 明確な説明がある — 何が変わったか、なぜ変えたか、テスト方法
- 小さい — 差分400行未満を目安にする
- CIが通っている — ビルドが壊れた状態でレビューを依頼しない
- issueへのリンクがある —
Closes #42でマージ時に自動クローズ
README Generator を使って、コード変更と並行してドキュメントの雛形を作成しましょう。
.gitignore の必須設定
.gitignore に必ず追加すべき内容:
# 環境変数
.env
.env.local
.env.*.local
# 依存関係
node_modules/
vendor/
# ビルド出力
dist/
build/
.next/
# OSファイル
.DS_Store
Thumbs.db
# エディタファイル
.vscode/settings.json
.idea/
*.swp
プロジェクト固有の .gitignore は gitignore.io で生成できます。数百もの言語やツールに対応しています。
Gitの習熟度は時間とともに積み重なっていきます。メンタルモデルを理解し、良いコミット習慣を身につければ、チームのコラボレーションは劇的にスムーズになるでしょう。