11. タグ管理

リリースバージョンなど、特定のコミットに目印を付けるタグ機能。 軽量版タグと注釈付きタグの違いも解説します。

タグの作成

タグには軽量版タグと注釈付きタグの2種類があります。 リリース用としては注釈付きタグを推奨します。

注釈付きタグ(推奨)

# 注釈付きタグを作成
git tag -a v1.0.0 -m "Release version 1.0.0"

# 現在のコミットにタグを付ける
git tag -a v1.0.1 -m "Bug fix release"

# 特定のコミットにタグを付ける
git tag -a v1.0.0 abc123 -m "Version 1.0.0"

# エディタで詳細なメッセージを入力
git tag -a v1.0.0

軽量版タグ

# 軽量版タグを作成(メッセージなし)
git tag v1.0.0

# 特定のコミットに軽量版タグ
git tag v1.0.0 abc123

# 軽量版タグの特徴
# - タグ名のみを保存
# - 作成者や日時などのメタデータなし
# - 一時的な目印用

タグの一覧と確認

リポジトリ内のタグを確認する方法です。

# すべてのタグを一覧表示
git tag

# パターンでタグを絞り込み
git tag -l "v1.*"
git tag --list "v2.0.*"

# タグの詳細情報を表示
git show v1.0.0

# タグを作成日順でソート
git tag --sort=-creatordate

# 最新のタグを表示
git describe --tags
git describe --tags --abbrev=0  # タグ名のみ

タグのプッシュ

デフォルトではタグはpushされません。明示的にプッシュする必要があります。

# 特定のタグをpush
git push origin v1.0.0

# すべてのタグをpush
git push origin --tags
git push --tags

# コミットとタグを一緒にpush
git push --follow-tags

# デフォルトで--follow-tagsを使用する設定
git config --global push.followTags true

タグの削除

ローカルとリモートのタグを削除する方法です。

# ローカルタグを削除
git tag -d v1.0.0
git tag --delete v1.0.0

# リモートタグを削除
git push origin --delete v1.0.0
git push origin :refs/tags/v1.0.0  # 古い書き方

# 複数のタグを削除
git tag -d v1.0.0 v1.0.1 v1.0.2
git push origin --delete v1.0.0 v1.0.1 v1.0.2

タグを使ったチェックアウト

特定のタグの状態にチェックアウトする方法です。

# タグをチェックアウト(detached HEAD状態)
git checkout v1.0.0

# タグから新しいブランチを作成
git checkout -b hotfix-1.0.1 v1.0.0
git switch -c hotfix-1.0.1 v1.0.0

# タグ間の差分を確認
git diff v1.0.0 v1.1.0
git log v1.0.0..v1.1.0

タグのベストプラクティス

リリース運用で推奨されるタグの付け方です。

# タグ命名規則の例
v1.0.0        # Semantic Versioning
v2.1.3-rc.1   # リリースキャンディデート
v1.0.0-beta.2 # ベータ版
release-2024-01 # 日付ベース

# 推奨されるプラクティス
# ✅ 注釈付きタグを使用
# ✅ Semantic Versioningに従う
# ✅ 詳細なリリースノートを記載
# ✅ タグ作成後は変更しない
# ❌ 軽量版タグを公開リリースに使用

12. Cherry-pick(特定コミットの適用)

他のブランチから特定のコミットだけを現在のブランチに取り込む機能。 バグ修正のバックポートなどに役立ちます。

基本的なCherry-pick

特定のコミットを現在のブランチに適用します。

# 特定のコミットを適用
git cherry-pick abc123

# 複数のコミットを適用
git cherry-pick abc123 def456 ghi789

# コミット範囲を適用
git cherry-pick abc123..def456
git cherry-pick abc123^..def456  # abc123も含む

# 最新のコミットを適用
git cherry-pick feature-branch

オプション付きCherry-pick

より柔軟なCherry-pick操作です。

# コミットせずにステージングのみ
git cherry-pick --no-commit abc123
git cherry-pick -n abc123
# 変更内容を確認して手動でコミット

# メッセージを編集
git cherry-pick -e abc123
git cherry-pick --edit abc123

# 元のコミット者情報を保持(デフォルト)
git cherry-pick abc123

# 空のコミットも適用
git cherry-pick --allow-empty abc123

コンフリクトの解決

Cherry-pick中にコンフリクトが発生した場合の対処法です。

# Cherry-pickでコンフリクトが発生
git cherry-pick abc123
# CONFLICT...

# 1. コンフリクトを解決
# エディタで修正

# 2. 解決したファイルをステージング
git add conflicted-file.txt

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

# Cherry-pickを中断して元に戻す
git cherry-pick --abort

# 現在のコミットをスキップ
git cherry-pick --skip

実用例

Cherry-pickの実践的な使用例です。

バグ修正のバックポート

# シナリオ: mainで修正したバグをreleaseブランチにも適用

# 1. mainでバグ修正
git checkout main
git commit -m "Fix critical bug"
# コミットSHA: abc123

# 2. releaseブランチに切り替え
git checkout release-1.0

# 3. 修正を適用
git cherry-pick abc123
git push origin release-1.0

特定の機能だけを取り込む

# シナリオ: featureブランチから特定のコミットだけがmainに欲しい

# 1. 必要なコミットSHAを確認
git log feature-branch --oneline

# 2. mainに切り替え
git checkout main

# 3. 必要なコミットだけを適用
git cherry-pick abc123 def456

注意点

Cherry-pickの使いどころと注意事項です。

# Cherry-pickの注意点

# ⚠️ コミット履歴が複雑になる
# - 同じ変更が複数のブランチに存在
# - 履歴の追跡が困難になる

# ✅ 使うべきケース
# - バグ修正のバックポート
# - 緊急のホットフィックス
# - 特定の機能だけを取り込む

# ❌ 避けるべきケース
# - 通常のブランチマージ
# - 大量のコミットの移動
# - 依存関係のあるコミット群

13. サブモジュール

他のGitリポジトリをプロジェクトに組み込むサブモジュール機能。 ライブラリ管理や共通コードの共有に便利です。

サブモジュールの追加

外部リポジトリをサブモジュールとして追加します。

# サブモジュールを追加
git submodule add https://github.com/user/library.git lib/library

# 特定のブランチを追跡
git submodule add -b main https://github.com/user/library.git lib/library

# サブモジュール追加後のコミット
git add .gitmodules lib/library
git commit -m "Add library as submodule"

サブモジュールを含むリポジトリのクローン

サブモジュールを含むプロジェクトをクローンする方法です。

# サブモジュールも含めてクローン
git clone --recurse-submodules https://github.com/user/project.git

# 既にクローン済みの場合
git submodule init
git submodule update
# または一行で
git submodule update --init --recursive

# 全サブモジュールを初期化して更新
git submodule update --init --recursive

サブモジュールの更新

サブモジュールを最新の状態に更新します。

# 全サブモジュールを更新
git submodule update --remote

# 特定のサブモジュールを更新
git submodule update --remote lib/library

# サブモジュール内で作業
cd lib/library
git checkout main
git pull
cd ../..

# 親リポジトリでサブモジュールの変更をコミット
git add lib/library
git commit -m "Update library submodule"

# 全サブモジュールでコマンドを実行
git submodule foreach 'git pull origin main'
git submodule foreach 'git checkout main'

サブモジュールの状態確認

サブモジュールの現在の状態を確認する方法です。

# サブモジュールの状態を表示
git submodule status

# 詳細なサブモジュール情報
git submodule

# サブモジュールの設定を確認
cat .gitmodules

# サブモジュールの概要を表示
git submodule summary

サブモジュールの削除

サブモジュールをプロジェクトから削除する方法です。

# サブモジュールを削除(Git 2.13以降)
git submodule deinit lib/library
git rm lib/library
git commit -m "Remove library submodule"

# .git/modulesも削除する場合
rm -rf .git/modules/lib/library

# 古いGitの場合の手順
git submodule deinit lib/library
git rm lib/library
rm -rf .git/modules/lib/library
git commit -m "Remove library submodule"

サブモジュールの注意点

サブモジュールの利点と運用上の注意です。

# サブモジュールの特徴

# ✅ 利点
# - 外部ライブラリのバージョン管理
# - 複数プロジェクトでのコード共有
# - 独立したリポジトリとして管理

# ⚠️ 注意点
# - サブモジュールは特定のコミットに固定される
# - 更新は手動で行う必要がある
# - チーム全員がサブモジュールを理解する必要がある
# - 初心者には複雑に感じるかもしれない

# サブモジュールの代替手段
# - npm/yarnなどのパッケージマネージャー
# - Git Subtree(よりシンプル)
# - モノレポ構成

14. ワークツリー

同じリポジトリで複数のブランチを同時に操作できるワークツリー機能。 異なる機能を並行で開発する際に便利です。

ワークツリーの作成

新しいワークツリーを作成して、複数のブランチで作業できるようにします。

# 新しいブランチでワークツリーを作成
git worktree add ../project-feature feature-branch

# 新しいブランチを作成してワークツリーを作成
git worktree add -b new-feature ../project-new-feature

# 特定のコミットからワークツリーを作成
git worktree add ../project-hotfix abc123

# detached HEADでワークツリーを作成
git worktree add --detach ../project-temp abc123

ワークツリーの一覧と確認

現在のワークツリーを確認する方法です。

# ワークツリーの一覧を表示
git worktree list

# 詳細情報付きで表示
git worktree list --porcelain

ワークツリーでの作業

複数のワークツリーで並行作業する方法です。

# メインの作業ディレクトリ
cd ~/project
git worktree add ../project-feature feature-a

# feature-aで作業
cd ../project-feature
# ... 作業 ...
git add .
git commit -m "Work on feature A"

# メインに戻って別の作業
cd ~/project
# ... mainブランチで作業 ...

# 両方の変更が独立して管理される

ワークツリーの削除

不要になったワークツリーを削除します。

# ワークツリーを削除
git worktree remove ../project-feature

# ロックされているワークツリーを強制削除
git worktree remove --force ../project-feature

# 手動でディレクトリを削除した場合のクリーンアップ
rm -rf ../project-feature
git worktree prune

# 古い・無効なワークツリー情報を削除
git worktree prune

ワークツリーの移動

ワークツリーを別の場所に移動する方法です。

# ワークツリーを移動
git worktree move ../project-feature ../new-location/project-feature

# ロックされているワークツリーを強制移動
git worktree move --force ../project-feature ../new-location/

実用例

ワークツリーの実践的な使用例です。

緊急のバグ修正

# シナリオ: 機能開発中に緊急のバグ修正が必要に

# 1. 現在の作業を続けながら、別ディレクトリでhotfix
cd ~/project  # featureブランチで作業中
git worktree add ../project-hotfix -b hotfix/critical-bug main

# 2. hotfixで作業
cd ../project-hotfix
# ... 修正 ...
git commit -m "Fix critical bug"
git push origin hotfix/critical-bug

# 3. 元の作業に戻る
cd ~/project
# featureブランチの作業を続ける

レビュー用環境

# シナリオ: PRのレビューを現在の作業を中断せずに行う

# 1. レビュー用ワークツリーを作成
git worktree add ../project-review pr-branch

# 2. レビュー
cd ../project-review
# ... コードを確認、テスト ...

# 3. レビュー後に削除
cd ~/project
git worktree remove ../project-review

ワークツリーの利点

ブランチ切り替えとの違いと、運用時の注意点です。

# ワークツリー vs ブランチ切り替え

# ✅ ワークツリーの利点
# - 作業を中断せずに別ブランチで作業可能
# - stashが不要
# - IDE/エディタの状態を保持
# - ビルド成果物を保持
# - 複数のブランチで同時にテスト実行

# ⚠️ 注意点
# - ディスク容量を消費する
# - 複数のディレクトリを管理する必要がある
# - node_modulesなどの依存関係が複数作成される

15. バグの特定(Bisect)

バグが混入したコミットを二分探索で特定するBisect機能。 大規模なコミット履歴から効率的に問題箇所を見つけられます。

手動Bisect

手動でテストしながらバグの原因を特定します。

# 1. Bisectを開始
git bisect start

# 2. 現在のコミット(バグあり)をbadとマーク
git bisect bad

# 3. 正常に動作していたコミットをgoodとマーク
git bisect good abc123

# 4. Gitが自動的に中間のコミットをチェックアウト
# Bisecting: 5 revisions left to test after this

# 5. テストして結果を報告
# バグがある場合
git bisect bad
# バグがない場合
git bisect good

# 6. 繰り返すと原因のコミットが特定される
# xyz789 is the first bad commit

# 7. Bisectを終了
git bisect reset

自動Bisect

テストスクリプトを使用して自動的にバグを特定します。

# 自動Bisectを開始
git bisect start HEAD abc123

# テストスクリプトで自動実行
git bisect run npm test

# テストスクリプトの終了コード
# 0: 成功(good)
# 1-127(125除く): 失敗(bad)
# 125: スキップ

# 自作スクリプトの例
# test.sh
#!/bin/bash
make && make test
exit $?

git bisect run ./test.sh

Bisectの高度な使い方

より柔軟なBisect操作です。

# 特定のパスを変更したコミットだけを対象にテスト
git bisect start HEAD abc123 -- path/to/file.js

# コミットをスキップ
git bisect skip

# 複数のコミットをスキップ
git bisect skip v2.5..v2.6

# 現在のBisectの状態を表示
git bisect log

# Bisectの状態を視覚化
git bisect visualize
gitk bisect/bad --not bisect/good

# Bisectを一時停止して別の作業
git bisect reset  # 一旦終了
# ... 作業 ...
git bisect start
git bisect good abc123
git bisect bad def456  # 再開

実用例

Bisectの実践的な使用例です。

パフォーマンス問題の特定

# シナリオ: いつからかパフォーマンスが悪化した

# ベンチマークスクリプトを作成(終了コード 0=good, 非0=bad)
# benchmark.sh
#!/bin/bash
npm run benchmark
exit $?

# Bisectで原因を特定
git bisect start HEAD v1.0.0
git bisect run ./benchmark.sh

ビルドエラーの特定

# シナリオ: いつからかビルドが失敗するようになった

git bisect start HEAD v2.0.0
git bisect run sh -c "npm install && npm run build"

Bisectのベストプラクティス

効率的にBisectを行うためのヒントです。

# 効果的なBisectのためのヒント

# ✅ 準備
# - 明確なgoodコミットを特定
# - 再現可能なテスト手順を用意
# - 自動テストがあれば活用

# ✅ 効率化
# - ビルドエラーがあるコミットはskip
# - 特定のファイルに絞って検索
# - タグやリリースを基準にする

# ⚠️ 注意
# - ビルド環境を清潔に保つ
# - キャッシュをクリアする
# - 環境変数や設定の影響に注意

16. 高度な操作

さらに高度なGitコマンドを紹介。 reflog、clean、blame、grepなど、特定の状況で役立つコマンドを学びます。

Reflog(リファレンスログ)

HEADや各ブランチの移動履歴を記録するログ。誤って削除したコミットを復元できます。

# Reflogを表示
git reflog
git reflog show HEAD

# 特定のブランチのreflog
git reflog show main

# 詳細なreflog
git reflog show --all

# 誤って削除したコミットを復元
git reflog
# abc123 HEAD@1: commit: Important work
git checkout abc123
git branch recovered-work

# 誤ってresetした場合の復元
git reset --hard HEAD@1

# Reflogの有効期限(デフォルト: 90日)
git config --global gc.reflogExpire "90 days"

Clean(未追跡ファイルの削除)

未追跡ファイルやディレクトリを削除して、作業ディレクトリを清潔にします。

# ドライラン(実際には削除しない)
git clean -n
git clean --dry-run

# 未追跡ファイルを削除
git clean -f
git clean --force

# 未追跡ディレクトリも削除
git clean -fd

# .gitignoreのファイルも削除
git clean -fdx

# 対話的に削除
git clean -i
git clean --interactive

# 特定のパターンを除外して削除
git clean -fdx -e '*.log'  # *.log 以外の未追跡ファイルを削除

Blame(各行の最終変更者)

ファイルの各行がいつ、誰によって変更されたかを確認できます。

# ファイルの各行の最終変更者を表示
git blame file.txt

# 特定の行範囲を表示
git blame -L 10,20 file.txt
git blame -L 10,+10 file.txt  # 10行目から10行分

# メールアドレスを表示
git blame -e file.txt

# コミットSHAを短く表示
git blame -s file.txt

# 特定のコミット時点でのblame
git blame abc123 file.txt

# 空白やインデントの変更を無視
git blame -w file.txt

Grep(コード検索)

Gitの履歴を通じてコードを検索します。

# 現在の作業ディレクトリで検索
git grep "function_name"

# 行番号を表示
git grep -n "function_name"

# ヒット数をカウント
git grep -c "TODO"

# 複数のパターンを検索
git grep -e "pattern1" --and -e "pattern2"
git grep -e "pattern1" --or -e "pattern2"

# 特定のファイルタイプで検索
git grep "function" -- "*.js"

# 特定のコミットで検索
git grep "pattern" abc123

# 前後の行も表示
git grep -C 3 "pattern"  # 前後3行
git grep -B 2 -A 1 "pattern"  # 前2行、後1行

Archive(アーカイブ作成)

リポジトリのスナップショットをアーカイブファイルとして作成します。

# ZIPアーカイブを作成
git archive --format=zip --output=project.zip HEAD

# tar.gzアーカイブを作成
git archive --format=tar.gz --output=project.tar.gz HEAD

# 特定のタグでアーカイブ
git archive --format=zip --output=v1.0.0.zip v1.0.0

# 特定のディレクトリのみアーカイブ
git archive --format=zip --output=src.zip HEAD:src/

# プレフィックス付きでアーカイブ
git archive --format=tar --prefix=project-1.0/ HEAD | gzip > project-1.0.tar.gz

Bundle(リポジトリのバックアップ)

Gitリポジトリ全体を1つのファイルにバンドルします。

# 全ブランチをバンドル
git bundle create repo.bundle --all

# 特定のブランチをバンドル
git bundle create repo.bundle main develop

# バンドルからクローン
git clone repo.bundle project

# バンドルの内容を確認
git bundle verify repo.bundle
git bundle list-heads repo.bundle

# バンドルからfetch
cd existing-repo
git fetch ../repo.bundle main:refs/remotes/bundle/main

Fsck(リポジトリの整合性チェック)

リポジトリの破損や問題を検出します。

# リポジトリの整合性チェック
git fsck

# 詳細なチェック
git fsck --full

# 失われたオブジェクトを検出
git fsck --lost-found

# ガベージコレクションを実行
git gc
git gc --aggressive --prune=now

Show(オブジェクトの表示)

様々なGitオブジェクトの内容を表示します。

# コミットの詳細を表示
git show abc123

# 特定のファイルの内容を表示
git show abc123:path/to/file.txt

# タグの詳細を表示
git show v1.0.0

# 差分のみ表示(メッセージなし)
git show --no-patch abc123
git show -s abc123

# 特定のファイルの変更のみ表示
git show abc123 -- path/to/file.txt