Git 高度ワークフローとコンフリクト解決の実践
Git ワークフロー全体比較
適切な Git ワークフローの選択はチーム協力の基盤です。異なる規模やリリースサイクルのチームには異なるブランチ戦略が必要です。
3つの主流ワークフロー
| ワークフロー | ブランチモデル | 適用場面 | リリースサイクル |
|---|---|---|---|
| Git Flow | main + develop + feature + release + hotfix | 明確なバージョン番号があるプロジェクト | 計画リリース(v1.0、v2.0) |
| GitHub Flow | main + feature | 継続デプロイの Web/SaaS プロジェクト | 継続リリース |
| Trunk-Based | main + 短命 feature(<1日) | 成熟した CI/CD チーム | 継続インテグレーション+Feature Flag |
Git Flow 詳解
Git Flow は Vincent Driessen が提唱した最も古典的なブランチモデルです:
# Git Flow の初期化(git-flow のインストールが必要)
git flow init
# 機能開発の開始
git flow feature start user-auth
# → develop から feature/user-auth を作成
# 機能の完了(develop に自動マージしてブランチを削除)
git flow feature finish user-auth
# リリース準備の開始
git flow release start v1.2.0
# → develop から release/v1.2.0 を作成
# リリースの完了(main + develop にマージ、タグ付与)
git flow release finish v1.2.0
# 緊急修正
git flow hotfix start critical-bug
# → main から hotfix/critical-bug を作成
git flow hotfix finish critical-bug
# → main + develop にマージ、タグ付与
ブランチライフサイクル図:
main: ●────────────────●────────●
\ / /
develop: ●──●──●──●──●──●──●──●──●──●
/ / \ /
feature: ●──●──● release: ●──● hotfix: ●──●
GitHub Flow 詳解
ミニマルモデル、継続デプロイに最適:
# 1. main から機能ブランチを作成
git checkout -b feature/add-search main
# 2. 開発してコミット
git add . && git commit -m "feat: add search component"
# 3. プッシュして PR を作成
git push -u origin feature/add-search
# 4. コードレビュー承認後、main にマージ
# 5. 本番環境に自動デプロイ
Trunk-Based Development 詳解
全員が main(trunk)に頻繁に統合し、Feature Flag で未完了機能を制御:
# 短命ブランチ(1日以内にマージ必須)
git checkout -b fix/login-timeout main
git add . && git commit -m "fix: login timeout handling"
git push -u origin fix/login-timeout
# → CI 通過後すぐにマージ、ブランチ削除
# Feature Flag の例(コード内で制御)
# if (flags.NEW_SEARCH_ENABLED) {
# return newSearch(query);
# }
# return legacySearch(query);
ワークフロー長短比較
| 観点 | Git Flow | GitHub Flow | Trunk-Based |
|---|---|---|---|
| 複雑さ | 高 | 低 | 中 |
| 並行開発 | 優秀 | 良好 | 優秀(Feature Flag が必要) |
| リリース制御 | 強 | 弱 | 中 |
| コンフリクトリスク | 高(長期ブランチ) | 低 | 最低 |
| ロールバック難易度 | 容易(hotfix ブランチ) | 容易(revert PR) | Feature Flag が必要 |
| CI/CD 親和性 | 中 | 高 | 最高 |
| 適合チーム規模 | 5-50人 | 2-20人 | 10+ 成熟チーム |
💡 Hash ツール を使ってコミット署名を生成し、コードの完全性を確保。
Interactive Rebase ステップバイステップ
Interactive Rebase は Git で最も強力な履歴書き換えツールです。これをマスターすればコミット履歴の「タイムマシン」を手に入れたことになります。
基本構文
# 直近3コミットのインタラクティブリベース
git rebase -i HEAD~3
# 特定コミット以降のインタラクティブリベース
git rebase -i abc1234^
# エディタに表示される内容:
# pick f1a2b3c feat: add user model
# pick d4e5f6g fix: validation error
# pick h7i8j9k docs: update README
Squash:コミットの結合
複数の小さなコミットを1つの意味のあるコミットに圧縮:
git rebase -i HEAD~3
# 以下のように変更:
# pick f1a2b3c feat: add user model
# squash d4e5f6g fix: validation error
# squash h7i8j9k docs: update README
# → 3コミットが1つに結合され、結合後のコミットメッセージを編集
典型的なシナリオ:「WIP」「fix typo」「fix again」などの細かいコミットを1つの意味のあるレコードにまとめる。
Fixup:サイレント結合
squash と同様ですが、結合されるコミットのメッセージを自動的に破棄:
git rebase -i HEAD~3
# pick f1a2b3c feat: add user model
# fixup d4e5f6g fix: validation error
# fixup h7i8j9k fix: another fix
# → 最初のコミットのメッセージのみ保持
より速い方法 — コミット時に直接 fixup をマーク:
git commit --fixup=f1a2b3c
# その後ワンステップで自動リベース:
git rebase -i --autosquash HEAD~3
Reorder:コミット順序の調整
エディタで行の順序を直接調整:
git rebase -i HEAD~3
# 元の順序:
# pick f1a2b3c feat: add user model
# pick d4e5f6g feat: add user service
# pick h7i8j9k test: user model test
# 調整後(テストがモデルの直後に):
# pick f1a2b3c feat: add user model
# pick h7i8j9k test: user model test
# pick d4e5f6g feat: add user service
Edit:コミットの分割
大きすぎるコミットを複数に分割:
git rebase -i HEAD~2
# pick f1a2b3c feat: add user module (too large)
# edit d4e5f6g feat: add auth module
# Git が edit マークのコミットで一時停止
git reset HEAD~1
# 全ファイルがステージングエリアに戻る、バッチでコミット可能
git add src/models/user.ts
git commit -m "feat: add user model"
git add src/services/user.ts
git commit -m "feat: add user service"
git rebase --continue
リベース中の操作
# 次のコミットに進む
git rebase --continue
# 現在のコミットをスキップ
git rebase --skip
# リベース全体を中止し、元の状態に戻る
git rebase --abort
⚠️ 黄金ルール:リモートの共有ブランチにプッシュ済みのコミットは絶対にリベースしない!他の人の履歴が壊れます。
Merge vs Rebase 深い比較
これは Git コミュニティで最も古典的な議論です。両者にはそれぞれ適用場面があります。
ビジュアル比較
Merge — 完全な履歴を保持、マージコミットを生成:
main: ●──●──●──M──●
\ /
feature: ●──●
Rebase — 線形履歴、マージコミットなし:
main: ●──●──●──●'──●'
↑ feature のコミットが main の後に再配置
Merge を使うべき時
# feature ブランチを main にマージ(ブランチ履歴を保持)
git checkout main
git merge --no-ff feature/user-auth
# --no-ff はファストフォワードマージを禁止、マージコミットを確実に生成
適用場面:
- feature ブランチを main/develop にマージ
- ブランチの存在痕跡を保持する必要がある
- チームが完全なプロジェクト履歴を要求
Rebase を使うべき時
# feature ブランチで main の更新を同期
git checkout feature/user-auth
git rebase main
# → feature のコミットが main の最新コミットの「後に」配置
適用場面:
- 上流ブランチの更新をローカル feature ブランチに同期
- ローカルの細かいコミットを整理
- コミット履歴を線形で読みやすく保つ
比較まとめ
| 観点 | Merge | Rebase |
|---|---|---|
| 履歴 | 実際のブランチ履歴を保持 | 線形履歴に書き換え |
| マージコミット | あり(多数になる可能性) | なし |
| 可読性 | 複雑なブランチグラフ | クリーンな線形 |
| 安全性 | 安全(履歴を変更しない) | 危険(プッシュ済みコミットを書き換え) |
| コンフリクト処理 | 一括解決 | コミットごとに解決 |
| ロールバック | git revert -m |
rebase または reset が必要 |
| 推奨場面 | メインブランチへのマージ | 上流更新の同期 |
実践的な推奨
# 推奨されるチームワークフローの組み合わせ:
# 1. feature 開発中:rebase で develop を同期
git checkout feature/x
git fetch origin
git rebase origin/develop
# 2. feature 完了後:merge(--no-ff)で develop に戻す
git checkout develop
git merge --no-ff feature/x
# 3. develop から main:merge(--no-ff)
git checkout main
git merge --no-ff develop
コンフリクト解決戦略
コンフリクトは協力開発の日常です。体系的な解決戦略は「当てずっぽう」よりはるかに効率的です。
3-Way Merge の原理
Git は三方マージアルゴリズムを使用:
Base(共通祖先)
/ \
Ours Theirs
\ /
Merge Result
- 両ブランチの共通祖先(Base)を見つける
- Ours vs Base、Theirs vs Base を比較
- 一方のみ変更 → 自動マージ
- 両方が同じ行を変更 → コンフリクト、手動解決が必要
# コンフリクトのあるファイルを確認
git diff --name-only --diff-filter=U
# コンフリクトの詳細内容を確認
git diff
手動コンフリクト解決
コンフリクトマーカーの形式:
<<<<<<< HEAD
現在のブランチの内容
=======
マージブランチの内容
>>>>>>> feature/other-branch
解決手順:
# 1. コンフリクトファイルを開き、手動編集
# 2. コンフリクトマーカーを削除し、正しい内容を保持
# 3. 解決済みとしてマーク
git add <conflicted-file>
# 4. マージを完了
git commit
# またはリベース中:
git rebase --continue
マージツールの使用
# VS Code をマージツールとして使用
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'
# vimdiff を使用
git config --global merge.tool vimdiff
# マージツールを起動
git mergetool
git rerere:コンフリクト解決の自動記憶
rerere(Reuse Recorded Resolution)は Git に同種のコンフリクトの解決方法を記憶させ、次回自動適用:
# rerere をグローバルに有効化
git config --global rerere.enabled true
# または特定のリポジトリでのみ有効化
cd your-repo
git config rerere.enabled true
仕組み:
- 初回のコンフリクト → 手動解決 → Git が解決策を記録
- 同じコンフリクトが再発 → 前回の解決策を自動適用
- 自動解決が不適切 →
git rerere forgetで記憶を削除
# 記録済みのコンフリクト解決策を確認
git rerere status
# 現在のコンフリクトの記録済み解決策を忘れる
git rerere forget
# 手動でリプレイをトリガー
git rerere
典型的なシナリオ:長期維持の feature ブランチが develop と繰り返しマージされ、同じコンフリクトが繰り返し出現。
コンフリクト解決戦略の選択
| 戦略 | 適用場面 | コマンド |
|---|---|---|
| 手動編集 | 少数のコンフリクト、慎重な判断が必要 | ファイルを直接編集 |
| マージツール | 多数のコンフリクト、可視化が必要 | git mergetool |
| Ours 戦略 | 常に自分のバージョンを採用 | git merge -X ours |
| Theirs 戦略 | 常に相手のバージョンを採用 | git merge -X theirs |
| rerere | 繰り返し出現する同種コンフリクト | git config rerere.enabled true |
💡 JSON フォーマッター ツールでコンフリクト後の package.json を整理。
Cherry-Pick とその落とし穴
Cherry-pick は特定のコミットを現在のブランチに「摘む」ことを可能にし、ブランチ全体をマージせずに済みます。
基本的な使い方
# 単一コミットの摘出
git cherry-pick abc1234
# 複数コミットの摘出
git cherry-pick abc1234 def5678
# 範囲の摘出(start を含まず、end を含む)
git cherry-pick start..end
# 範囲の摘出(start と end の両方を含む)
git cherry-pick start^..end
よくある落とし穴
落とし穴1:重複コミット
# feature ブランチのコミット abc1234 が既に merge で main にマージ済み
# 後から同じコミットを cherry-pick
git cherry-pick abc1234
# → 新しいコミット(異なる SHA)が生成、内容は同じ
# → Git は2つの異なるコミットと見なし、将来の merge で空マージやコンフリクトが発生する可能性
落とし穴2:依存コミットの漏れ
# コミット B はコミット A の変更に依存
# A を pick せずに B だけ cherry-pick
git cherry-pick B
# → コンパイルエラーやバグが発生する可能性
落とし穴3:コンフリクト処理
# cherry-pick でコンフリクトが発生
git cherry-pick abc1234
# CONFLICT!
# コンフリクト解決後に続行
git add .
git cherry-pick --continue
# または今回の cherry-pick を中止
git cherry-pick --abort
安全な Cherry-Pick の原則
- マージ予定のないブランチにのみ cherry-pick(例:hotfix から release へ)
- 摘出するコミットが自己完結していることを確認(他の未摘出コミットに依存しない)
- cherry-pick 済みのコミットを記録、重複を避ける
- merge や rebase を優先、cherry-pick は最後の手段
典型的なシナリオ:Hotfix 同期
# main で緊急修正
git checkout main
git cherry-pick hotfix-commit-sha
# develop に同期
git checkout develop
git cherry-pick hotfix-commit-sha
# 他の release ブランチに同期
git checkout release/v1.1
git cherry-pick hotfix-commit-sha
Bisect:二分法によるバグ特定
git bisect は二分探索法でコミット履歴中からバグを導入したコミットを特定し、線形検査より指数関数的に高速です。
基本フロー
# 1. 二分探索の開始
git bisect start
# 2. 現在のバージョンを「bad」としてマーク
git bisect bad
# 3. 既知の good バージョンをマーク
git bisect good v1.0.0
# Git が中間コミットを自動チェックアウト
# このバージョンをテスト...
# 4. 中間コミットをマーク
git bisect good # このバージョンに問題がない場合
git bisect bad # このバージョンに問題がある場合
# 5. 手順4を繰り返し、Git が最初の bad コミットを見つけるまで
# → Git が表示:abc1234 is the first bad commit
# 6. 二分探索の終了
git bisect reset
自動化 Bisect
スクリプトで各コミットの良否を自動判定:
# テストスクリプトで自動判定
git bisect start HEAD v1.0.0 --
git bisect run npm test
# カスタムスクリプトを使用
git bisect run ./scripts/bisect-test.sh
bisect-test.sh の例:
#!/bin/bash
npm build || exit 125 # ビルドできないコミットをスキップ
npm test
# exit 0 = good, exit 1 = bad, exit 125 = skip
Bisect の効率
1000コミットの範囲の場合、bisect は最大 10回(log₂(1000) ≈ 10)で問題コミットを特定できますが、線形検査は最悪1000回かかります。
Worktree:ブランチ切り替えなしの並行作業
git worktree は同じリポジトリで複数のブランチを異なるディレクトリにチェックアウトでき、stash や clone が不要です。
基本的な使い方
# worktree の追加
git worktree add ../feature-x feature/x
# → ../feature-x ディレクトリに feature/x ブランチをチェックアウト
# 新しいブランチの worktree を追加
git worktree add -b feature/y ../feature-y main
# → feature/y ブランチを作成し ../feature-y にチェックアウト
# 全 worktree の一覧
git worktree list
# worktree の削除
git worktree remove ../feature-x
# 強制削除(未コミット変更がある場合)
git worktree remove --force ../feature-x
典型的なシナリオ
# シナリオ1:2つの feature で同時に作業
git worktree add ../feature-a feature/a
git worktree add ../feature-b feature/b
# → 2つのディレクトリが互いに干渉せず、異なる IDE で開ける
# シナリオ2:緊急修正で現在の作業を中断しない
git worktree add -b hotfix/urgent ../hotfix main
cd ../hotfix
# → 修正、コミット、プッシュ
cd ../main-project
git worktree remove ../hotfix
# シナリオ3:長時間実行テスト
git worktree add ../test-branch test-env
# → test-branch でテスト実行、メインディレクトリで開発継続
Worktree の注意点
- 同じブランチを2つの worktree で同時にチェックアウトできない
- worktree 削除前に変更がコミットまたは保存されていることを確認
- worktree は同じ
.gitディレクトリを共有、ディスク容量を節約
Stash 高度な使い方
git stash は未コミットの変更を一時保存する、「現在の作業を一時停止」する最良の方法です。
基本操作
# 全変更を保存(追跡ファイルの変更とステージング)
git stash
# 説明付きで保存
git stash push -m "WIP: user auth refactor"
# 全 stash を確認
git stash list
# 最新の stash を復元
git stash pop
# stash を削除せずに復元
git stash apply
# 特定の stash を復元
git stash apply stash@{2}
高度なテクニック
# 特定のファイルのみ stash
git stash push -m "partial" src/auth.ts src/auth.test.ts
# 未追跡ファイル(新ファイル)も stash
git stash -u
# 全ファイル(無視されたファイルも含む)を stash
git stash -a
# ステージングエリアの内容のみ stash
git stash --staged
# 特定の stash の内容を確認
git stash show -p stash@{0}
# stash からブランチを作成
git stash branch feature/from-stash stash@{0}
複数 Stash の管理
# シナリオ:複数の stash が蓄積
git stash list
# stash@{0}: On feature/x: WIP: refactor
# stash@{1}: On feature/x: WIP: fix tests
# stash@{2}: On main: hotfix draft
# 特定の stash を削除
git stash drop stash@{1}
# 全 stash をクリア
git stash clear
Stash とコンフリクト
# pop/apply でコンフリクトが発生
git stash pop
# CONFLICT!
# コンフリクト解決後、手動で stash を削除
git stash drop
# または pop を中止
git checkout -- .
git stash pop # 再試行
Git Hooks 自動化
Git Hooks は特定の Git イベント発生時に自動実行されるスクリプトで、ローカル自動化の強力なツールです。
よく使う Hooks の場所
# Hooks は .git/hooks/ ディレクトリに保存
ls .git/hooks/
# applypatch-msg.sample
# pre-commit.sample
# commit-msg.sample
# ...
pre-commit:コミット前チェック
# pre-commit hook の作成
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/bash
# console.log の確認
if git diff --cached | grep -q "console.log"; then
echo "❌ console.log が見つかりました。削除してからコミットしてください"
exit 1
fi
# lint の実行
npm run lint
if [ $? -ne 0 ]; then
echo "❌ Lint チェックに失敗"
exit 1
fi
# 型チェックの実行
npm run typecheck
if [ $? -ne 0 ]; then
echo "❌ 型チェックに失敗"
exit 1
fi
exit 0
EOF
chmod +x .git/hooks/pre-commit
commit-msg:コミットメッセージ規約の強制
cat > .git/hooks/commit-msg << 'EOF'
#!/bin/bash
COMMIT_MSG=$(cat "$1")
# Conventional Commits 形式の検証
PATTERN="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?: .{1,100}"
if ! echo "$COMMIT_MSG" | grep -qE "$PATTERN"; then
echo "❌ コミットメッセージが Conventional Commits 規約に従っていません"
echo "形式: type(scope): description"
echo "例: feat(auth): add login page"
exit 1
fi
exit 0
EOF
chmod +x .git/hooks/commit-msg
推奨:Husky + lint-staged の使用
手動での hooks 管理はチーム間で共有しにくいため、ツールの使用を推奨:
# Husky のインストール
npm install husky -D
npx husky init
# pre-commit hook の追加
echo "npx lint-staged" > .husky/pre-commit
# lint-staged の設定(package.json)
# "lint-staged": {
# "*.{ts,tsx}": ["eslint --fix", "prettier --write"],
# "*.{json,md}": ["prettier --write"]
# }
# commit-msg hook の追加
echo 'npx --no -- commitlint --edit "$1"' > .husky/commit-msg
その他の便利な Hooks
| Hook | トリガー | 典型的な用途 |
|---|---|---|
| pre-push | git push の前 |
フルテストスイートの実行 |
| post-merge | git pull マージ後 |
自動 npm install |
| post-checkout | ブランチ切り替え後 | node_modules の切り替え |
| prepare-commit-msg | コミットメッセージ編集前 | issue 番号の自動追加 |
Git LFS:大ファイルストレージ
Git はバイナリ大ファイル(画像、動画、モデルなど)の処理効率が低いです。Git LFS がこれを解決します。
インストールと初期化
# Git LFS のインストール
git lfs install
# 大ファイルタイプの追跡
git lfs track "*.psd"
git lfs track "*.mp4"
git lfs track "*.model"
git lfs track "datasets/**"
# 追跡ルールの確認
git lfs track
# .gitattributes をコミット(追跡ルールはバージョン管理に含める必要あり)
git add .gitattributes
git commit -m "chore: configure Git LFS"
日常的な使用
# 通常通り add/commit、LFS が自動処理
git add large-file.psd
git commit -m "feat: add design file"
# LFS で保存されたファイルの確認
git lfs ls-files
# LFS の使用容量を確認
git lfs ls-files --size
# LFS オブジェクトの取得
git lfs pull
# 特定ファイルの LFS オブジェクトのみ取得
git lfs fetch --include="*.psd"
既存ファイルの LFS への移行
# 追跡済みの .psd ファイルを LFS に移行
git lfs migrate import --include="*.psd"
# 全履歴の大ファイルを移行(履歴書き換え!)
git lfs migrate import --include="*.psd" --everything
LFS の注意点
- サーバーのサポートが必要(GitHub/GitLab は対応、クォータ制限あり)
.gitattributesをリポジトリにコミット必須- clone 時はデフォルトで LFS オブジェクトをダウンロードしない(
git lfs pullが必要) - LFS にはストレージと帯域幅のクォータがあり、コストに注意
Monorepo 戦略
Monorepo は複数のプロジェクトを同じリポジトリに配置し、コードの共有と統一管理を容易にします。
ディレクトリ構造
monorepo/
├── apps/
│ ├── web/ # フロントエンドアプリ
│ ├── mobile/ # モバイルアプリ
│ └── api/ # バックエンドサービス
├── packages/
│ ├── ui/ # 共有 UI コンポーネント
│ ├── utils/ # 共有ユーティリティ関数
│ └── config/ # 共有設定
├── package.json
├── turbo.json # Turborepo 設定
└── pnpm-workspace.yaml
スパースチェックアウト(Sparse Checkout)
必要なディレクトリのみチェックアウトし、clone を高速化:
# スパースチェックアウトの有効化
git sparse-checkout init --cone
# apps/web と packages/ui のみチェックアウト
git sparse-checkout set apps/web packages/ui
# ディレクトリの追加
git sparse-checkout add apps/api
# 現在チェックアウトされているディレクトリの確認
git sparse-checkout list
シャロークローン(Shallow Clone)
最近のコミット履歴のみ取得:
# 最新1コミットのみ取得
git clone --depth=1 https://github.com/org/monorepo.git
# 最新10コミットを取得
git clone --depth=10 https://github.com/org/monorepo.git
# 後からさらに履歴を取得
git fetch --unshallow
Monorepo ツールの選択
| ツール | 言語 | コア機能 |
|---|---|---|
| Turborepo | JS/TS | インクリメンタルビルド、リモートキャッシュ、Pipeline |
| Nx | JS/TS | 依存グラフ分析、影響を受けるプロジェクトの検出 |
| Lerna | JS/TS | バージョン管理、パブリッシュワークフロー |
| Bazel | 多言語 | Google クラスのインクリメンタルビルド |
| PNPM Workspace | JS/TS | ネイティブ monorepo サポート |
よくあるエラーと復旧
Detached HEAD
# 誤って detached HEAD 状態に入った
git checkout abc1234
# → HEAD detached at abc1234
# 現在の状態を確認
git status
# → HEAD detached at abc1234
# 復旧オプション1:新しいブランチを作成して保存
git checkout -b feature/from-detached
# 復旧オプション2:未コミット変更がある場合
git stash
git checkout main
git stash pop
Force Push 復旧
# 誰かが force push でリモートブランチを上書きした
# 1. reflog で上書きされたコミットを見つける
git reflog
# abc1234 HEAD@{0}: checkout: moving from main to feature/x
# def5678 HEAD@{1}: commit: feat: important feature
# 2. 特定のコミットに復旧
git checkout def5678
git checkout -b feature/x-recovered
git push -f origin feature/x-recovered:feature/x
Reflog:究極の復旧ツール
Reflog は HEAD のすべての移動を記録し、「削除」されたコミットも復旧可能:
# 完全な reflog を確認
git reflog
# 特定ブランチの reflog を確認
git reflog show feature/x
# 最新10件を確認
git reflog -10
# reflog のエントリに復旧
git reset --hard HEAD@{5}
# reset で失われたコミットを復旧
git reflog
# reset 前のコミット SHA を見つける
git cherry-pick <lost-commit-sha>
Reflog の保持期間:
[gc]
reflogExpire = 90.days
reflogExpireUnreachable = 30.days
誤って大ファイルをコミットした場合
# 1. 履歴から大ファイルを完全に削除
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch path/to/large-file.mp4' \
--prune-empty -- --all
# 2. またはより高速な git-filter-repo を使用
pip install git-filter-repo
git filter-repo --path path/to/large-file.mp4 --invert-paths
# 3. 強制プッシュでリモートを更新
git push --force --all
# 4. ローカルをクリーンアップ
git reflog expire --expire=now --all
git gc --prune=now --aggressive
.gitignore ベストプラクティス
階層戦略
# グローバル無視(~/.gitignore_global)
# OS ファイル
.DS_Store
Thumbs.db
Desktop.ini
# IDE
.idea/
.vscode/
*.swp
# 環境変数
.env
.env.local
プロジェクトレベルの .gitignore
# 依存関係
node_modules/
vendor/
.venv/
# ビルド成果物
dist/
build/
*.egg-info/
# ログ
*.log
logs/
# テストカバレッジ
coverage/
.nyc_output/
# 一時ファイル
*.tmp
*.temp
.cache/
# 大ファイル(LFS と併用)
# *.psd → 無視ではなく LFS 追跡を使用
無視ルールの構文
# すべての .log ファイルを無視
*.log
# ただし important.log は保持
!important.log
# build ディレクトリ下の全内容を無視
build/**
# ルートの TODO のみ無視、サブディレクトリは無視しない
/TODO
# doc ディレクトリ下のすべての .pdf を無視
doc/**/*.pdf
# すべてのディレクトリの __pycache__ を無視
__pycache__/
よくある間違い
# ❌ 間違い:既に追跡されているファイルを .gitignore に追加しても効果がない
# ✅ 正しい方法:まず追跡を解除
git rm --cached debug.log
# その後 .gitignore に追加
echo "debug.log" >> .gitignore
git add .gitignore
git commit -m "chore: ignore debug.log"
推奨テンプレート
gitignore.io を使用してプロジェクトテンプレートを生成:
# Node + VSCode + macOS の無視ルールを生成
curl -sL https://www.gitignore.io/api/node,visualstudiocode,macos > .gitignore
💡 Base64 エンコード ツールで .env ファイルの機密情報をエンコードして送信。
FAQ
Q1:リベース中にコンフリクトが多すぎる場合はどうすればよいか?
オプション:
git rebase --abortで中止し、git mergeを使用- 上流から頻繁に rebase して蓄積差分を減らす
- 大きな feature を小さく分割し、rebase の範囲を減らす
Q2:プッシュ済みのコミットを取り消すには?
# オプション1:revert(安全、新しいコミットを生成)
git revert abc1234
git push
# オプション2:reset + force push(危険、履歴を書き換え)
git reset --hard abc1234^
git push --force
# ⚠️ 他の人がこのコミットに基づいて作業していないことを確認してからのみ使用
Q3:特定のファイルの変更履歴を確認するには?
# ファイルの変更履歴を確認
git log --follow -p src/auth/login.ts
# ファイルの各行を誰が変更したかを確認
git blame src/auth/login.ts
# 特定コミット時のファイル内容を確認
git show abc1234:src/auth/login.ts
Q4:2つのブランチの差分を比較するには?
# ブランチ間のファイル差分を確認
git diff main..feature/x
# ブランチ間のコミット差分を確認
git log main..feature/x --oneline
# ブランチ間の統計を確認
git diff main..feature/x --stat
Q5:ローカルの削除済みリモートブランチ参照をクリーンアップするには?
# 存在しないリモートブランチ参照を剪定
git remote prune origin
# または fetch 時に自動剪定
git fetch -p
# または自動剪定を設定
git config --global fetch.prune true
Q6:マージコミットの revert を処理するには?
# マージコミットの revert では保持する親ブランチを指定する必要がある
# -m 1:最初の親を保持(通常は main)
git revert -m 1 <merge-commit-sha>
Q7:Git でファイルパーミッションの変更を無視するには?
git config core.fileMode false
Q8:大規模リポジトリの clone を高速化するには?
# 組み合わせ戦略:シャロークローン + スパースチェックアウト + 単一ブランチ
git clone --depth=1 --single-branch --filter=blob:none \
https://github.com/org/large-repo.git
ブラウザローカルツールを無料で試す →