git-workflow-expert について
開発者向けの Git ワークフロースキルです。ブランチ戦略の選択、競合解決、作業の復旧、高度なリポジトリ運用を支援します。
主な機能
- 01ブランチ戦略の選択
- 02マージとリベースの指針
- 03競合解決の手法
- 04reflogによるコミット復旧
- 05モノレポのパターンとGitフック
活用シーン
- 01チームのブランチモデル選定
- 02複雑な複数ファイル競合の解決
- 03失われたコミットやstashの復旧
- 04スパースチェックアウトやサブモジュールの管理
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ curiositech/ some_claude_skills --skill git-workflow-expertインストール後、Claude Code で/git-workflow-expertを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
.claude-plugin/plugin.jsonreferences/advanced-rebase-patterns.mdmonorepo-git-strategies.md詳細
Git ワークフローのエキスパート
日々のワークフローから災害復旧まで、Git 操作を習得します。ブランチ戦略、マージとリベースの使い分け、コンフリクト解決、モノレポのパターン、そして多くの開発者が知らないものの、どうしても必要となる高度な操作を網羅しています。
使用する場面
次の場合に使用します:
- プロジェクトのブランチ戦略を選ぶ場合(トランクベース、GitHub Flow、git-flow)
- マージコンフリクトを解決する場合(特に複数ファイルにまたがる複雑なコンフリクト)
- リベースのワークフロー(インタラクティブリベース、リベースの移動、自動スカッシュ)
- ブランチ間でチェリーピックする場合
git bisectを使ってバグを混入させたコミットを特定する場合- reflog で失った作業を復元する場合
- モノレポの Git パターン(スパースチェックアウト、サブツリー、サブモジュール)
- 整理されていない Git 履歴をクリーンアップする場合
- 品質ゲートのために Git フックを設定する場合
- 強制プッシュの安全性と共有ブランチのプロトコル
対象外:
- GitHub Actions/CI/CD パイプライン(
github-actions-pipeline-builderを使用) - PR レビュープロセスとチェックリスト(
code-review-checklistを使用) - GitHub API/ウェブフック/リポジトリ管理
- Git LFS のセットアップ(説明しますが、主な対象ではありません)
主な判断事項:ブランチ戦略
flowchart TD
Start[New project or rethinking strategy?] --> Team{Team size?}
Team -->|Solo or 2-3| Trunk[Trunk-Based Development]
Team -->|4-15| GHFlow[GitHub Flow]
Team -->|15+ or regulated| Q2{Release cadence?}
Q2 -->|Continuous deploy| GHFlow
Q2 -->|Scheduled releases| GitFlow[Git-Flow]
Q2 -->|Multiple supported versions| GitFlow
Trunk --> T1[Main branch only]
T1 --> T2[Short-lived feature branches < 1 day]
T2 --> T3[Feature flags for incomplete work]
GHFlow --> G1[main + feature branches]
G1 --> G2[PR-based review]
G2 --> G3[Deploy from main after merge]
GitFlow --> GF1[main + develop + feature + release + hotfix]
GF1 --> GF2[Formal release branches]
GF2 --> GF3[Hotfix branches from main]
戦略の比較
| 項目 | トランクベース | GitHub Flow | Git-Flow |
|---|---|---|---|
| ブランチの存続期間 | 数時間 | 数日 | 数日~数週間 |
| マージ頻度 | 1 日に複数回 | 毎日 | スプリントごと |
| CI の要件 | 必須 | 強く推奨 | 任意 |
| ロールバックの仕組み | フィーチャーフラグ | コミットをリバート | リリースブランチ |
| 最適な対象 | 信頼関係の強いチーム | ほとんどの Web プロジェクト | バージョン管理されたリリース |
| 最も不向きな対象 | ジュニア開発者が多いチーム | 複数のバージョンを同時に運用する場合 | 高速な反復 |
マージとリベースの使い分け
flowchart TD
Q[Integrating changes?] --> Shared{Is the branch shared?}
Shared -->|Yes, others push to it| Merge[Use merge]
Shared -->|No, only me| Q2{Want clean history?}
Q2 -->|Yes| Rebase[Use rebase]
Q2 -->|No, preserve context| Merge
Rebase --> Q3{Long-lived branch?}
Q3 -->|Yes, many conflicts expected| RebaseOnto[Consider rebase --onto]
Q3 -->|No| RebaseSimple[Simple rebase]
アンチパターン:共有ブランチのリベース
初心者:「履歴をきれいに保つため、共有フィーチャーブランチに main をリベースします。」
エキスパート:他の人がプッシュしているブランチは、決してリベースしないでください。リベースするとコミット SHA が書き換わり、すでにプルした人にはコミットが重複して表示され、マージが大混乱になります。共有ブランチには merge を、個人ブランチには rebase を使ってください。
兆候:プル後に、複数の開発者から「見慣れないコミットの重複がある」と報告されます。
アンチパターン:マージコミットだらけの履歴
初心者:「最新の状態を保つため、毎朝 main をフィーチャーブランチにマージします。」
エキスパート:main から毎日マージコミットを作ると、履歴が読みにくくなります。代わりに、個人ブランチで git rebase main を実行して(クリーンな操作を 1 回行うだけです)、またはマージする必要がある場合でも、少なくとも main に戻すときはスカッシュしてください。
経緯:2020 年以前はマージが標準でした。現在のチームでは、フィーチャーブランチにはリベース、PR にはマージ(またはスカッシュマージ)が好まれます。
コンフリクトの解決
落ち着いて対処する方法
# 1. Before resolving: understand what happened
git log --merge --oneline # Show conflicting commits
git diff --name-only --diff-filter=U # List conflicted files
# 2. For each file: understand both sides
git diff :2:file :3:file # :2 = ours, :3 = theirs
# 3. Resolve, then verify
git add resolved-file.ts
git diff --cached # Review what you're about to commit
# 4. After all files resolved
git merge --continue # or git rebase --continue
アンチパターン:ours/theirs を無条件に採用する
初心者:「このコンフリクトは複雑すぎるので、git checkout --ours . だけ実行して終わらせます。」
エキスパート:片方を無条件に採用すると、もう一方の作業が失われます。コンフリクトが本当に複雑な場合は、3-way マージツール(git mergetool)を使って、base、ours、theirs を同時に確認してください。大規模なコンフリクトには、コンフリクトの解決方法をキャッシュする rerere(記録された解決方法の再利用)の使用を検討してください。
兆候:マージ後に機能がいつの間にか消えています。
高度な操作
チェリーピックのワークフロー
# Pick a specific commit from another branch
git cherry-pick abc123
# Pick a range (exclusive start, inclusive end)
git cherry-pick abc123..def456
# Cherry-pick without committing (stage only)
git cherry-pick --no-commit abc123
# If conflicts: resolve then
git cherry-pick --continue
チェリーピックする場面:複数のリリースブランチに適用する必要があるホットフィックス。マージの準備ができていないフィーチャーブランチからバグ修正を取り込む場合。
チェリーピックしない場面:多くのコミットが必要な場合は、代わりにマージまたはリベースを使ってください。チェリーピックすると、SHA の異なる重複コミットが作成されます。
Git Bisect(バグを混入させたコミットの特定)
# Start bisect
git bisect start
git bisect bad # Current commit is broken
git bisect good v1.2.0 # This tag was working
# Git checks out a middle commit. Test it, then:
git bisect good # or: git bisect bad
# Repeat until git identifies the first bad commit
# Automated bisect with a test script:
git bisect start HEAD v1.2.0
git bisect run npm test # Runs test at each step automatically
Reflog による復旧(ほとんどの操作を取り消す)
# See recent HEAD positions
git reflog --oneline -20
# Recover a dropped stash
git stash list # Empty? Check reflog:
git fsck --no-reflogs | grep commit # Find dangling commits
git show <sha> # Inspect to find your stash
# Undo a bad rebase
git reflog
# Find the SHA before the rebase started
git reset --hard HEAD@{5} # Reset to that point
# Recover deleted branch
git reflog | grep "branch-name"
git checkout -b recovered-branch <sha>
インタラクティブリベース(履歴の整理)
# Rewrite last 5 commits
git rebase -i HEAD~5
# In the editor:
# pick abc123 Add user model ← keep as-is
# squash def456 Fix typo in user model ← squash into previous
# reword ghi789 Add auth ← edit commit message
# drop jkl012 WIP debugging ← remove entirely
# edit mno345 Add migration ← pause to amend
# Autosquash: commits prefixed with "fixup!" or "squash!" auto-arrange
git commit --fixup abc123 # Creates "fixup! Add user model"
git rebase -i --autosquash HEAD~5 # Automatically squashes it
モノレポの Git パターン
スパースチェックアウト(サブセットで作業する)
# Enable sparse checkout
git sparse-checkout init --cone
git sparse-checkout set packages/core packages/cli
# Now only packages/core and packages/cli are checked out
# Other directories exist in git but aren't on disk
サブツリー(別のリポジトリを埋め込む)
# Add a subtree
git subtree add --prefix=libs/shared https://github.com/org/shared.git main --squash
# Pull updates
git subtree pull --prefix=libs/shared https://github.com/org/shared.git main --squash
# Push changes back upstream
git subtree push --prefix=libs/shared https://github.com/org/shared.git feature-x
サブモジュールとサブツリー
| 項目 | サブモジュール | サブツリー |
|---|---|---|
| モデル | 外部リポジトリへのポインター | 外部リポジトリのコピー |
| クローン | --recurse-submodules が必要 | そのまま動作 |
| 更新 | git submodule update | git subtree pull |
| CI の複雑さ | 高い(初期化ステップが必要) | 低い |
| 最適な用途 | 大規模なベンダー管理依存関係 | 小規模な共有ライブラリ |
| 落とし穴のリスク | 高い(detached HEAD の罠) | 低い |
品質を高める Git フック
# .git/hooks/pre-commit (or use husky/lefthook)
#!/bin/sh
# Run linter on staged files only
npx lint-staged
# .git/hooks/commit-msg
#!/bin/sh
# Enforce conventional commits
if ! grep -qE "^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: .+" "$1"; then
echo "Commit message must follow Conventional Commits format"
exit 1
fi
# .git/hooks/pre-push
#!/bin/sh
# Run tests before push
npm test || exit 1
アンチパターン:フックをスキップする
初心者:「pre-commit フックが遅いので、--no-verify を使います。」
エキスパート:フックが遅すぎる場合は、フックを改善してください(差分に対する段階的な lint には lint-staged を使い、テストを並列化します)。--no-verify は習慣になり、本来の目的を損ないます。一度だけ本当にスキップする必要がある場合(緊急のホットフィックスなど)は、コミットメッセージに理由を記録してください。
ブランチ戦略の選択ロジック
ユーザーから使用するブランチ戦略を尋ねられた場合は、以下のルールを順番に適用してください。
厳格な制約(すべてに優先)
-
複数バージョンのライブラリ(
hasMultipleVersions: trueANDisLibrary: true)→ git-flow- 理由:v3.x の開発を進めながら v2.x のホットフィックスを保守するには、長期間存続するリリースブランチが必要です。トランクベースでは、2 つの対象ユーザーに対応できません。
- トランクベースからの移行:各メジャーバージョンの最後のタグから
release/vN.xブランチを作成します。cherry-pick でバックポートします。
-
規制対象業界(
isRegulated: true)→ git-flow- 理由:監査担当者は、承認ゲートを備え、コミットから本番環境までの明確な経緯を示し、ブランチを指して「これがリリースされたものです」と説明できる、名前付きのリリースブランチを期待します。トランクベースでもタグを使えば技術的には要件を満たせますが、git-flow のほうが監査時の説明が容易です。
- 注:CI の成熟度が高く、コンプライアンスチームが受け入れる場合は、デプロイタグと署名付きコミットを使うトランクベースのほうが優れています。ただし、コンプライアンスチームは受け入れないものと想定してください。
CI の成熟度によるゲート
- CI の成熟度が低い(
ciMaturity: 'low')→ github-flow- 理由:包括的な CI がない状態でトランクベースを採用すると、main に壊れたコードが入ることになります。GitHub Flow(フィーチャーブランチ+PR レビュー+マージ)は、人による安全網を提供します。まず CI への投資を勧め、その後トランクベースへ移行してください。
- 後でトランクベースへ移行する手順:ブランチの存続期間を <1 日に短縮し、CI の成功を必須とするブランチ保護を追加してから、小さな変更に対する PR 承認の必須要件をなくします。
デフォルト(ほとんどのチーム)
- その他すべて → trunk-based
- 理由:フィードバックループが最短で、マージ時の負担が最小限になり、優れた CI の習慣が身につきます。未完了の作業にはフィーチャーフラグを使います。譲歩として、短期間(<1 日)のブランチは許容されます。
- チームが 15 人を超える場合:短期間のフィーチャーブランチを使ったトランクベースを検討してください(これもトランクベースです。ブランチは <24h で存続し、マージ後に自動削除されます)。
移行パス
| 移行元 | 移行先 | 手順 |
|---|---|---|
| git-flow → trunk-based | 1. develop を main にマージします。2. develop を削除します。3. main にブランチ保護を設定します(CI の成功を必須にします)。4. 未完了の作業にはフィーチャーフラグを導入します。5. ブランチの存続期間の目標を <1 日に短縮します。 | |
| git-flow → github-flow | 1. develop を main にマージします。2. develop とすべての release/* ブランチを削除します。3. main に直接 PR を作成します。4. main からリリースにタグを付けます。 | |
| github-flow → trunk-based | 1. PR のサイズを <200 行に縮小します。2. 包括的な CI を追加します。3. 些細な変更については、main への直接プッシュを許可します。4. 大きな変更では PR を維持しつつ、同日中にマージします。 |
Force Push の安全性
# NEVER force push to main/master
# Use --force-with-lease instead of --force
git push --force-with-lease origin feature-branch
# --force-with-lease checks that remote hasn't been updated
# since your last fetch. Prevents overwriting others' work.
# Set as default (never use bare --force again):
git config --global alias.pushf "push --force-with-lease"
参考資料
references/advanced-rebase-patterns.md— 複雑なリベースのシナリオについては、こちらを参照してください:rebase --onto、インタラクティブリベースの戦略、長期間存続するブランチでのリベース競合への対処references/monorepo-git-strategies.md— モノレポ固有のパターンについては、こちらを参照してください:スパースチェックアウトの最適化、CODEOWNERS、パスベースの CI トリガー、大規模リポジトリのパフォーマンス