Skip to content
Published on

Git完全攻略:ジュニアからシニアまで、実務で即使えるGit上級ワークフロー

Authors

はじめに

Gitはすべての開発者の日常ツールです。しかし、ほとんどの開発者はgit addgit commitgit push程度しか使わず、Gitが提供する強力な機能の10%も活用できていません。このガイドでは、ジュニアからシニアまで、Gitの内部構造から実務で即適用可能な上級ワークフローを総まとめします。

コードレビューで「このコミット履歴を整理してください」というフィードバックを受けたことはありませんか?マージコンフリクトが発生してパニックになったことは?この記事を最後まで読めば、そのような状況に自信を持って対処できるようになります。


1. Git内部構造の理解 — Objects、DAG、そして.gitディレクトリ

Gitを真にマスターするには、内部動作原理(ないぶどうさげんり)を理解する必要があります。Gitは単なるバージョン管理ツールではなく、content-addressableファイルシステムの上に構築された精巧なシステムです。

1.1 Gitの4つのオブジェクト

Git内部には4つの核心オブジェクトが存在します。

Blob(Binary Large Object): ファイルの内容を保存します。ファイル名やパスは含まず、純粋なファイル内容のみを保持します。

# ファイル内容のハッシュ値を確認
echo "Hello, Git!" | git hash-object --stdin
# 結果例: af5626b4a114abcb82d63db7c8082c3c4756e51b

# 保存されたオブジェクトのタイプを確認
git cat-file -t af5626b
# 結果: blob

# 内容を確認
git cat-file -p af5626b
# 結果: Hello, Git!

Tree: ディレクトリ構造を表します。BlobやほかのTreeを参照してファイルシステムのスナップショットを構成します。

# 最新コミットのツリーを確認
git cat-file -p HEAD^{tree}
# 100644 blob a906cb2a4a904a15...    README.md
# 040000 tree 99f1a6d12cb4b6f1...    src
# 100644 blob 47c6340d6459e058...    package.json

Commit: ある時点のスナップショットです。Treeオブジェクトを指し、作成者、コミットメッセージ、親コミット情報を含みます。

# コミットの内部構造を確認
git cat-file -p HEAD
# tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0
# parent 8bd3ad5e1234567890abcdef1234567890abcdef
# author John Doe <john@example.com> 1711100000 +0900
# committer John Doe <john@example.com> 1711100000 +0900
#
# feat: add user authentication

Tag: 特定のコミットに名前を付けるオブジェクトです。リリースバージョン管理に使用されます。

# アノテーティッドタグを作成
git tag -a v1.0.0 -m "Release version 1.0.0"

# タグオブジェクトを確認
git cat-file -p v1.0.0

1.2 SHA-1ハッシュとコンテンツアドレッシング

GitはすべてのオブジェクトをSHA-1ハッシュで識別します。同一の内容は常に同一のハッシュを生成するため、重複保存が自然に防止されます。

# 同一の内容 = 同一のハッシュ
echo "same content" | git hash-object --stdin
echo "same content" | git hash-object --stdin
# 二つの結果は完全に同一

これが意味するのは重要です。100個のブランチで同じファイルを持っていても、Gitはそのファイルを一度だけ保存します。

1.3 DAG(Directed Acyclic Graph)— コミットグラフ

Gitのコミット履歴はDAG(有向非巡回グラフ)構造です。各コミットは親コミットを指し、循環はありません。

    A---B---C---D  (main)
         \
          E---F---G  (feature)
               \
                H---I  (hotfix)

この構造を理解すれば、merge、rebase、cherry-pickが実際に何をしているか直感的に分かります。

# グラフ形式でログを表示
git log --oneline --graph --all --decorate

# より見やすい出力
git log --oneline --graph --all --format="%h %s (%ar)"

1.4 .gitディレクトリの解剖

.git/
  HEAD          # 現在のブランチを指すポインタ
  config        # リポジトリ固有の設定
  refs/
    heads/      # ローカルブランチ(各ファイル = コミットハッシュ)
    tags/       # タグ
    remotes/    # リモートブランチの追跡
  objects/      # すべてのGitオブジェクト(blob, tree, commit, tag)
    pack/       # 圧縮されたオブジェクトパックファイル
  hooks/        # Gitフックスクリプト
  index         # ステージングエリア(バイナリ)
# HEADが指す先を確認
cat .git/HEAD
# ref: refs/heads/main

# mainブランチが指すコミット
cat .git/refs/heads/main
# a1b2c3d4e5f6...

# オブジェクトストアのサイズを確認
git count-objects -vH

2. ブランチング戦略比較 — チームに合ったワークフローの選択

2.1 Git Flow

2010年にVincent Driessenが提案した伝統的なブランチモデルです。

main ─────────────────────────────── (本番環境)
  └── develop ────────────────────── (開発統合)
        │        │
        │   feature/login ────────── (機能開発)
        └── release/1.0 ──────────── (リリース準備)
              └── hotfix/bug-123 ──── (緊急修正)

長所: 明確なリリース管理、本番環境の安定性を保証 短所: ブランチが多く複雑、マージコンフリクトが頻発、CI/CDと相性が悪い

# Git Flowの初期化(git-flow拡張)
git flow init

# 機能開発の開始
git flow feature start user-auth

# 機能開発の完了
git flow feature finish user-auth

2.2 GitHub Flow

GitHubが使用するシンプルなブランチモデルです。

main ────────────────────────────────
  │              │
  └── feature ───┘ (PR + マージ)

ルール: mainは常にデプロイ可能な状態。機能ブランチで作業後、PRを通じてマージ。

# 1. ブランチ作成
git checkout -b feature/add-search

# 2. 作業とコミット
git add .
git commit -m "feat: add search functionality"

# 3. プッシュ
git push -u origin feature/add-search

# 4. PR作成(GitHub CLI)
gh pr create --title "Add search functionality" --body "..."

# 5. レビュー後マージ
gh pr merge --squash

2.3 Trunk-Based Development(トランクベース開発)

Google、Metaなど大規模チームで使用される方式です。すべての開発者がmain(トランク)に直接、または非常に短命なブランチを通じて頻繁に統合します。

main ──A──B──C──D──E──F──G──H──I──
            \─/     \─/
         (1-2日) (1-2日)

核心原則:

  • ブランチの寿命は最大1〜2日
  • 一日に複数回mainに統合
  • Feature Flagで未完成の機能を管理
  • 強力なCI/CDパイプラインが必須

2.4 戦略比較表

項目Git FlowGitHub FlowTrunk-Based
複雑さ高い低い中程度
ブランチ寿命長い(週〜月)中程度(日〜週)短い(時間〜日)
リリース周期定期リリース随時デプロイ継続的デプロイ
チーム規模10人以上2〜15人制限なし
CI/CD依存度低い中程度高い
推奨場面モバイルアプリ、パッケージSaaS、Webアプリ大規模組織

2.5 ブランチ命名規則

# 機能開発
feature/JIRA-123-add-login
feature/user-profile-page

# バグ修正
bugfix/JIRA-456-fix-null-pointer
fix/login-redirect-loop

# ホットフィックス
hotfix/security-patch-xss
hotfix/v1.2.1

# リリース
release/1.0.0
release/2026-q1

# 実験/メンテナンス
experiment/new-search-algo
chore/update-dependencies

3. リベースマスタークラス

3.1 Rebase vs Merge — いつどちらを使うか

Merge: 二つのブランチの履歴を保持しながら統合します。

git checkout main
git merge feature/login
# マージコミットが作成される
    A---B---C---D---M  (main、マージコミットM)
         \         /
          E---F---G  (feature)

Rebase: コミットを別のベースの上に再適用します。

git checkout feature/login
git rebase main
# featureのコミットがmainの上に再適用される
    A---B---C---D  (main)
                 \
                  E'---F'---G'  (feature、再適用済み)

3.2 Interactive Rebase(対話型リベース)完全ガイド

# 最近5つのコミットを対話的に編集
git rebase -i HEAD~5

エディタが開くと、次のような画面が表示されます。

pick a1b2c3d feat: add user model
pick d4e5f6g fix: typo in user model
pick h7i8j9k feat: add user controller
pick l0m1n2o WIP: debugging
pick p3q4r5s feat: add user routes

使用可能なコマンド:

コマンド省略形説明
pickpコミットをそのまま使用
rewordrコミットメッセージのみ変更
editeコミットを修正(ファイル変更可能)
squashs前のコミットと結合し、メッセージを編集
fixupf前のコミットと結合し、メッセージを破棄
dropdコミットを削除

実践例 — 散らかった履歴の整理:

pick a1b2c3d feat: add user model
fixup d4e5f6g fix: typo in user model
pick h7i8j9k feat: add user controller
drop l0m1n2o WIP: debugging
pick p3q4r5s feat: add user routes

結果:5つのコミットがきれいな3つのコミットに整理されます。

3.3 Autosquashワークフロー

fixup!プレフィックスを使うと自動的に整理されます。

# 元のコミット
git commit -m "feat: add user model"

# 後で修正が必要な時
git commit --fixup HEAD
# または特定のコミットを指定
git commit --fixup a1b2c3d

# 自動的に整理
git rebase -i --autosquash main

3.4 リベースの黄金律

絶対に共有ブランチ(main、develop)をリベースしないでください。 リベースはコミットハッシュを変更するため、他の人のローカルリポジトリとコンフリクトが発生します。

# 安全なリベース(個人のfeatureブランチ)
git checkout feature/my-task
git rebase main

# 危険なリベース(絶対にやらないで!)
git checkout main
git rebase feature/something  # 禁止!

4. 実務シナリオ20個 — 問題発生時の解決法

シナリオ1:コミットメッセージを間違えた時

# 直前のコミットメッセージを修正(まだプッシュしていない場合)
git commit --amend -m "feat: add user authentication"

# エディタでメッセージを修正
git commit --amend

シナリオ2:間違ったブランチにコミットした時

# 状況:mainにコミットすべきものをfeatureブランチにした
# 方法1:cherry-pick
git checkout main
git cherry-pick abc1234
git checkout feature/wrong-branch
git reset --hard HEAD~1

# 方法2:stash活用
git reset --soft HEAD~1
git stash
git checkout correct-branch
git stash pop
git commit -m "correct commit message"

シナリオ3:プッシュ後の取り消し — revert vs reset

# 安全な方法:revert(新しいコミットで戻す、履歴保存)
git revert abc1234
git push

# 危険な方法:reset + force push(履歴変更)
git reset --hard HEAD~1
git push --force-with-lease
# force-with-leaseは他の人のコミットを上書きしないよう保護

revert vs reset比較:

項目revertreset
履歴保存(新コミット追加)変更(コミット削除)
安全性安全危険
共有ブランチ使用可能使用禁止
取り消しrevertのrevert可能reflogでのみ回復

シナリオ4:マージコンフリクトの解決戦略

# コンフリクト発生時
git merge feature/login
# CONFLICT (content): Merge conflict in src/auth.js

# コンフリクトファイルの確認
git status

# コンフリクトマーカーの構造
# <<<<<<< HEAD
# 現在のブランチのコード
# =======
# マージしようとしているブランチのコード
# >>>>>>> feature/login

# 手動解決後
git add src/auth.js
git commit -m "resolve merge conflict in auth module"

マージコンフリクトを最小化する戦略:

# 1. mainを頻繁に取り込んで同期
git fetch origin
git rebase origin/main

# 2. 小さな単位で頻繁にコミットしてマージ
# 3. チーム内のファイル所有権を明確にする(CODEOWNERS)
# 4. マージツールの設定
git config --global merge.tool vimdiff
git mergetool

シナリオ5:特定のコミットでバグ追跡 — git bisect

# bisect開始
git bisect start

# 現在(バグあり)をbadとしてマーク
git bisect bad

# バグがなかったコミットをgoodとしてマーク
git bisect good v1.0.0

# Gitが中間のコミットをチェックアウト — テスト後判断
git bisect good  # または git bisect bad

# 繰り返すとバグを導入した正確なコミットが見つかる
# 結果: abc1234 is the first bad commit

# bisect終了
git bisect reset

自動bisect(テストスクリプト活用):

# テストスクリプトが失敗するとbad、成功するとgood
git bisect start HEAD v1.0.0
git bisect run npm test
# 自動的にバグコミットを見つけてくれます!

シナリオ6:大容量ファイルを誤ってコミットした時

# 方法1:git-filter-repo(推奨)
pip install git-filter-repo
git filter-repo --path large-file.zip --invert-paths

# 方法2:BFG Repo-Cleaner
java -jar bfg.jar --delete-files large-file.zip
git reflog expire --expire=now --all
git gc --prune=now --aggressive

# 予防:.gitignore設定
echo "*.zip" >> .gitignore
echo "*.tar.gz" >> .gitignore
echo "node_modules/" >> .gitignore

シナリオ7:ファイルの一部だけステージング — git add -p

# ファイルの変更をhunk単位で選択的にステージング
git add -p src/utils.js

# 各hunkに対して:
# y - このhunkをステージング
# n - このhunkをスキップ
# s - より小さなhunkに分割
# e - 手動で編集
# q - 終了

シナリオ8:作業中の緊急ホットフィックス — stash + worktree

# 方法1:stash
git stash push -m "WIP: feature work"
git checkout main
git checkout -b hotfix/critical-bug
# ホットフィックス作業...
git checkout feature/my-work
git stash pop

# 方法2:worktree(より良い方法!)
git worktree add ../hotfix-workspace main
cd ../hotfix-workspace
git checkout -b hotfix/critical-bug
# ホットフィックス作業...
cd ../main-workspace
git worktree remove ../hotfix-workspace

シナリオ9:複数のコミットを一つにまとめる

# 方法1:interactive rebase
git rebase -i HEAD~4
# 最初をpick、残りをsquashに変更

# 方法2:soft reset
git reset --soft HEAD~4
git commit -m "feat: complete user authentication"

# 方法3:merge --squash
git checkout main
git merge --squash feature/user-auth
git commit -m "feat: add user authentication system"

シナリオ10:サブモジュール管理

# サブモジュールの追加
git submodule add https://github.com/org/shared-lib.git libs/shared

# クローン時にサブモジュールを含める
git clone --recurse-submodules https://github.com/org/project.git

# サブモジュールの更新
git submodule update --remote --merge

# すべてのサブモジュールでコマンド実行
git submodule foreach 'git checkout main && git pull'

シナリオ11:削除したブランチの復元

# reflogで削除されたブランチの最後のコミットを探す
git reflog
# abc1234 HEAD@{5}: checkout: moving from deleted-branch to main

# ブランチの復元
git checkout -b recovered-branch abc1234

シナリオ12:特定のファイルだけ別のブランチから取得

# mainブランチの特定ファイルを現在のブランチに取得
git checkout main -- src/config.js

# 特定コミットのファイルを取得
git checkout abc1234 -- src/config.js

シナリオ13:コミット日付の変更

# 最後のコミットの日付を現在時刻に変更
GIT_COMMITTER_DATE="$(date)" git commit --amend --date="$(date)"

# 特定の日付に変更(リベース中)
GIT_COMMITTER_DATE="2026-03-22T10:00:00" git commit --amend --date="2026-03-22T10:00:00"

シナリオ14:git blameでコード追跡

# ファイルの各行を誰が最後に修正したか確認
git blame src/auth.js

# 特定の行範囲のみ確認
git blame -L 10,20 src/auth.js

# 空白変更を無視
git blame -w src/auth.js

# コード移動も追跡
git blame -M src/auth.js
git blame -C src/auth.js

シナリオ15:git logの高度な活用

# 特定ファイルの変更履歴
git log --follow -p -- src/auth.js

# 特定の文字列が追加/削除されたコミットを探す(pickaxe)
git log -S "API_KEY" --oneline

# 特定の著者のコミットのみ
git log --author="John" --oneline --since="2026-01-01"

# 統計情報を含む
git log --stat --oneline -10

# コミット間のdiff
git log -p --oneline -3

シナリオ16:リモートリポジトリ管理

# 複数のリモートリポジトリを追加
git remote add upstream https://github.com/original/repo.git
git remote add deploy git@deploy-server:app.git

# upstreamの同期(フォークプロジェクト)
git fetch upstream
git rebase upstream/main

# リモートブランチの整理
git remote prune origin
git fetch --prune

シナリオ17:Gitタグでリリース管理

# アノテーティッドタグの作成
git tag -a v2.0.0 -m "Release 2.0.0: new payment system"

# 特定のコミットにタグ
git tag -a v1.5.0 abc1234 -m "Hotfix release"

# タグのプッシュ
git push origin v2.0.0
git push origin --tags

# タグの削除
git tag -d v2.0.0-beta
git push origin --delete v2.0.0-beta

シナリオ18:Gitフックで自動化

# .husky/pre-commit
#!/bin/sh
npx lint-staged

# .husky/commit-msg
#!/bin/sh
npx commitlint --edit "$1"

# .husky/pre-push
#!/bin/sh
npm test

シナリオ19:パッチファイルの作成と適用

# パッチの作成
git diff > my-changes.patch
git format-patch -3  # 最近3つのコミットをパッチファイルに

# パッチの適用
git apply my-changes.patch
git am *.patch  # format-patchで作成されたパッチを適用

シナリオ20:git reflog — 最後の砦

# reflogを確認(HEADの移動履歴)
git reflog

# 誤ってreset --hardした場合の復元
git reflog
# abc1234 HEAD@{2}: commit: important work
git reset --hard abc1234

# 誤って削除したstashの復元
git fsck --unreachable | grep commit
git stash apply abc1234

5. Conventional Commits + Semantic Versioning

5.1 Conventional Commitsの形式

type(scope): description

[optional body]

[optional footer(s)]

タイプ一覧:

タイプ説明
feat新機能feat: add login page
fixバグ修正fix: resolve null pointer in auth
docsドキュメント変更docs: update API documentation
styleコードスタイル(フォーマットなど)style: fix indentation
refactorリファクタリングrefactor: extract auth middleware
perfパフォーマンス改善perf: optimize database queries
testテスト追加/修正test: add unit tests for auth
buildビルドシステム変更build: update webpack config
ciCI設定変更ci: add GitHub Actions workflow
choreその他の雑務chore: update dependencies

Breaking Changeの表記:

feat(api)!: change authentication endpoint

BREAKING CHANGE: /auth/login is now /api/v2/auth/login

5.2 Commitlint + Huskyの設定

# パッケージのインストール
npm install -D @commitlint/cli @commitlint/config-conventional husky

# commitlintの設定
echo "module.exports = { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js

# Huskyの初期化
npx husky init
echo 'npx commitlint --edit "$1"' > .husky/commit-msg

5.3 自動Changelog生成

# conventional-changelogのインストール
npm install -D conventional-changelog-cli

# CHANGELOG.mdの生成
npx conventional-changelog -p angular -i CHANGELOG.md -s
{
  "scripts": {
    "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
    "release": "standard-version"
  }
}

5.4 Semantic Release — 完全自動化

npm install -D semantic-release
{
  "release": {
    "branches": ["main"],
    "plugins": [
      "@semantic-release/commit-analyzer",
      "@semantic-release/release-notes-generator",
      "@semantic-release/changelog",
      "@semantic-release/npm",
      "@semantic-release/github",
      "@semantic-release/git"
    ]
  }
}

コミットタイプに応じて自動的にバージョンが決定されます:

  • fix: -> PATCH(1.0.0 -> 1.0.1)
  • feat: -> MINOR(1.0.0 -> 1.1.0)
  • BREAKING CHANGE -> MAJOR(1.0.0 -> 2.0.0)

6. GitHub Actions CI/CD

6.1 基本ワークフロー

name: CI Pipeline

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18, 20, 22]

    steps:
      - uses: actions/checkout@v4

      - name: Use Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'

      - run: npm ci
      - run: npm run lint
      - run: npm test
      - run: npm run build

6.2 PRチェックワークフロー

name: PR Checks

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  lint-and-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'

      - run: npm ci

      - name: Lint
        run: npm run lint

      - name: Type Check
        run: npx tsc --noEmit

      - name: Unit Tests
        run: npm test -- --coverage

      - name: Build
        run: npm run build

      - name: Upload coverage
        uses: codecov/codecov-action@v4
        with:
          file: ./coverage/lcov.info

6.3 自動ラベリング

name: Auto Label

on:
  pull_request:
    types: [opened, edited]

jobs:
  label:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/labeler@v5
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}
# .github/labeler.yml
frontend:
  - changed-files:
      - any-glob-to-any-file: 'src/components/**'

backend:
  - changed-files:
      - any-glob-to-any-file: 'src/api/**'

documentation:
  - changed-files:
      - any-glob-to-any-file: 'docs/**'

tests:
  - changed-files:
      - any-glob-to-any-file: '**/*.test.*'

6.4 Dependabotの設定

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: 'npm'
    directory: '/'
    schedule:
      interval: 'weekly'
      day: 'monday'
    open-pull-requests-limit: 10
    labels:
      - 'dependencies'
    groups:
      dev-dependencies:
        dependency-type: 'development'
      production-dependencies:
        dependency-type: 'production'

  - package-ecosystem: 'github-actions'
    directory: '/'
    schedule:
      interval: 'weekly'

6.5 デプロイワークフロー

name: Deploy

on:
  push:
    tags:
      - 'v*'

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 20

      - run: npm ci
      - run: npm run build

      - name: Deploy to Production
        run: |
          echo "Deploying version $GITHUB_REF_NAME"
          # 実際のデプロイコマンド

7. Monorepo戦略

7.1 Monorepo vs Multirepo

項目MonorepoMultirepo
コード共有簡単パッケージ公開が必要
依存関係管理統合管理個別管理
CI/CD複雑(選択的ビルド)シンプル(リポジトリごと)
コードレビュー全体のコンテキスト把握可能リポジトリごとに分散
権限管理複雑リポジトリごとに設定
代表事例Google、Meta、MicrosoftNetflix、Spotify

7.2 ツール比較 — Nx vs Turborepo vs Lerna

# Nxの初期化
npx create-nx-workspace@latest my-workspace

# Turborepoの初期化
npx create-turbo@latest

# プロジェクト構造の例
my-monorepo/
  apps/
    web/          # Next.js Webアプリ
    mobile/       # React Nativeアプリ
    api/          # Express APIサーバー
  packages/
    ui/           # 共有UIコンポーネント
    utils/        # 共有ユーティリティ
    config/       # 共有設定
  turbo.json
  package.json

7.3 CODEOWNERSの設定

# .github/CODEOWNERS

# プロジェクト全体のデフォルトレビューア
* @team-lead

# フロントエンド
/apps/web/        @frontend-team
/packages/ui/     @frontend-team

# バックエンド
/apps/api/        @backend-team
/packages/utils/  @backend-team

# DevOps
/.github/         @devops-team
/docker/          @devops-team
*.yml             @devops-team

7.4 選択的ビルドとテスト

{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    },
    "test": {
      "dependsOn": ["build"]
    },
    "lint": {}
  }
}
# 変更されたパッケージのみビルド
npx turbo run build --filter=...[HEAD^1]

# 特定のアプリのみビルド
npx turbo run build --filter=web

# 依存関係を含めてビルド
npx turbo run build --filter=web...

8. Gitパフォーマンス最適化

8.1 Shallow Clone(浅いクローン)

# 最新1つのコミットのみクローン(CI/CDで有用)
git clone --depth 1 https://github.com/org/repo.git

# 後で完全な履歴が必要になったら
git fetch --unshallow

8.2 Partial Clone(部分クローン)

# Blobなしでクローン(必要な時にダウンロード)
git clone --filter=blob:none https://github.com/org/repo.git

# Treeも除外(最速のクローン)
git clone --filter=tree:0 https://github.com/org/repo.git

8.3 Sparse Checkout(スパースチェックアウト)

# sparse checkoutを有効化
git sparse-checkout init --cone

# 特定のディレクトリのみチェックアウト
git sparse-checkout set apps/web packages/ui

# ディレクトリを追加
git sparse-checkout add apps/api

# 設定を確認
git sparse-checkout list

8.4 Git LFS(Large File Storage)

# Git LFSのインストールと初期化
git lfs install

# 大容量ファイルの追跡
git lfs track "*.psd"
git lfs track "*.zip"
git lfs track "assets/videos/*"

# .gitattributesを確認
cat .gitattributes
# *.psd filter=lfs diff=lfs merge=lfs -text

# LFSの状態を確認
git lfs ls-files
git lfs status

8.5 Git Maintenance(自動メンテナンス)

# 自動メンテナンスを有効化
git maintenance start

# 手動でガベージコレクション
git gc --aggressive

# オブジェクトの圧縮状態を確認
git count-objects -vH

# 不要な参照の整理
git remote prune origin
git reflog expire --expire=30.days

8.6 Scalar — 大規模リポジトリ管理(Microsoft)

# Scalarに登録(Git 2.38+に含まれる)
scalar register

# または新規クローン
scalar clone https://github.com/org/massive-repo.git

# Scalarが自動的に設定するもの:
# - Partial clone
# - Sparse checkout
# - Background maintenance
# - Filesystem monitor
# - Commit graph

9. AI + Git(2025〜2026年)

9.1 AIコミットメッセージ生成

# Claude Codeで自動コミットメッセージ生成
claude commit

# GitHub Copilot CLI
gh copilot suggest "write a commit message for these changes"

# aicommitsツール
npm install -g aicommits
aicommits

9.2 AIコードレビュー

GitHub Copilot for Pull RequestsはPRを自動的に分析してレビューコメントを生成します。コードの潜在的なバグ、パフォーマンス問題、セキュリティ脆弱性を発見します。

# GitHub Copilot自動レビューの有効化(リポジトリ設定で)
# Settings > Code review > Copilot code review > Enable

9.3 Claude CodeとGitワークフロー

Claude CodeはGit操作を直接サポートします。

# ステージされた変更のレビューを依頼
claude "review my staged changes"

# コミットメッセージの作成
claude "write a conventional commit message for my changes"

# PR説明文の生成
claude "write a PR description for the current branch"

# マージコンフリクトの解決
claude "help me resolve the merge conflicts in src/auth.js"

9.4 自動PR説明文生成

name: Auto PR Description

on:
  pull_request:
    types: [opened]

jobs:
  describe:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Generate PR description
        uses: anthropics/claude-code-action@v1
        with:
          prompt: |
            Analyze the diff of this PR and generate a clear description
            including what changed, why, and any risks.

実力チェッククイズ

クイズ1:Gitオブジェクト

Q: Gitでファイル名はどのオブジェクトに保存されますか?Blobでしょうか、Treeでしょうか?

A: Treeオブジェクトに保存されます。

Blobはファイルの純粋な内容のみを保存し、ファイル名とパス情報はTreeオブジェクトが管理します。この設計のおかげで、ファイル名が変更されても内容が同じなら同じBlobを再利用できます。

# Treeオブジェクトでファイル名を確認
git cat-file -p HEAD^{tree}
# 100644 blob a906cb...    README.md  <-- ファイル名はTreeに!

クイズ2:リベースの安全性

Q: 次のうち安全なリベース操作はどれでしょうか?(A: main上でfeatureをリベース、B: feature上でmainをリベース、C: 両方安全)

A: Bが安全です。

リベースの黄金律は「共有されたブランチをリベースしない」です。mainは共有ブランチなので、main上でリベースしてはいけません。一方、featureは個人ブランチなので、mainの最新コミットの上にfeatureのコミットを再適用するのは安全です。

クイズ3:Resetモード

Q: git resetの三つのモード(--soft、--mixed、--hard)の違いは何ですか?

A:

  • --soft:HEADのみ移動。ステージングエリアと作業ディレクトリはそのまま。コミットだけ取り消したい時に使用。
  • --mixed(デフォルト):HEAD移動 + ステージングエリアのリセット。作業ディレクトリはそのまま。コミットとステージングを取り消す時に使用。
  • --hard:HEAD移動 + ステージングエリア + 作業ディレクトリすべてリセット。すべての変更を破棄する時に使用。(危険!)
# 例:最近3つのコミットを取り消すがコードは保持
git reset --soft HEAD~3
# 変更はステージされた状態で残っている

クイズ4:Cherry-pickのコンフリクト

Q: cherry-pick中にコンフリクトが発生した場合、どう解決しますか?

A: マージコンフリクトと同じ方法で解決します。

git cherry-pick abc1234
# CONFLICTが発生

# 1. コンフリクトファイルを修正
# 2. ステージング
git add resolved-file.js

# 3. cherry-pickを続行
git cherry-pick --continue

# またはcherry-pickを中断
git cherry-pick --abort

クイズ5:MonorepoでのCI

Q: Monorepoでフロントエンドのコードだけ変更した場合、バックエンドのテストも実行する必要がありますか?

A: 依存関係によります。

フロントエンドがバックエンドパッケージに依存していなければ、バックエンドのテストを実行する必要はありません。これがNxやTurborepoのような「影響分析(affected analysis)」の核心的な価値です。

# Nx:変更に影響を受けるプロジェクトのみテスト
npx nx affected --target=test

# Turborepo:変更されたパッケージと依存パッケージのみビルド
npx turbo run build --filter=...[HEAD^1]

ただし、共有パッケージ(utils、configなど)が変更された場合は、そのパッケージに依存するすべてのプロジェクトのテストを実行する必要があります。


参考資料

公式ドキュメント

  1. Git公式ドキュメント — 最も正確なリファレンス
  2. GitHub Docs — GitHub機能ガイド
  3. Pro Git Book(日本語) — 無料オンライン書籍

ブランチ戦略

  1. Trunk Based Development — TBD公式サイト
  2. GitHub Flow Guide
  3. A successful Git branching model — Git Flow原文

CI/CD

  1. GitHub Actions公式ドキュメント
  2. Semantic Release — 自動バージョン管理
  3. Conventional Commits — コミット規約

Monorepo

  1. Nx公式ドキュメント
  2. Turborepo公式ドキュメント
  3. Monorepo Tools — ツール比較

パフォーマンス

  1. Git LFS — 大容量ファイル管理
  2. Scalar — 大規模リポジトリ
  3. git-filter-repo — 履歴の整理

深掘り

  1. Oh Shit, Git!?! — Gitミス復旧ガイド
  2. Learn Git Branching — ビジュアルGit学習
  3. Git Internals (PDF) — Git内部構造

まとめ

Gitは単なるツールではなく、開発文化を形成するコアインフラです。きれいなコミット履歴はチームの協業能力を反映し、効果的なブランチ戦略はデプロイの安定性を決定します。

この記事で扱った内容を一度にすべて覚える必要はありません。まず日常的に使うコマンドの動作原理を理解し、徐々に上級テクニックを適用してみてください。特にinteractive rebaseとbisectは、一度覚えると生産性が大幅に向上するツールです。

覚えておいてください:良いコミット履歴は、未来の自分と同僚への手紙です。 今日からConventional Commitsを始めてみませんか?