Git運用 レッスン2

コミットの作法

意味のある単位でコミットを分割し、読み手に伝わるコミットメッセージを書く作法を学ぶ

意味のある単位でコミットする(Atomic Commit)

1つのコミットには、1つの論理的な変更だけを 含めるようにします。これを「アトミックなコミット」と呼びます。 複数の目的が混ざったコミットは、後から特定の変更だけを取り消したり、 原因を特定したりする作業を難しくします。

避けたいコミット

「ログイン機能を追加 + 無関係なタイポ修正 + フォーマッターの一括適用」を 1つのコミットにまとめてしまう

望ましいコミット

「ログイン機能を追加」「タイポを修正」「フォーマッターを適用」を それぞれ独立したコミットに分ける

ポイント

コミットを分けておくと、git bisectで バグ混入コミットを特定しやすくなり、git revertで 特定の変更だけをピンポイントに取り消せるようになります。

良いコミットメッセージの構造

コミットメッセージは、将来の自分やチームメンバーが履歴を読んだときに、 「何を・なぜ変更したか」が伝わるように書きます。 多くのチームでConventional Commitsに似た接頭辞(prefix)を使う運用が採用されています。

<type>: <要約(何をしたか、命令形で簡潔に)>

<本文(任意・なぜその変更が必要だったかの背景)>

<フッター(任意・関連Issue番号など)>

# 例:
feat: 注文履歴のページネーションを追加

一覧表示が1000件を超えると読み込みが遅くなっていたため、
20件ずつのページネーションに変更した。

Closes #482
feat: 新機能
fix: バグ修正
refactor: リファクタリング
docs: ドキュメント
test: テスト追加・修正
chore: 雑務・設定変更

コミットメッセージのアンチパターン

避けたい例

  • 修正 - 何を?
  • wip - 作業中の内容が不明
  • fix bug - どのバグ?

言い換えた例

  • fix: カート合計金額が税込で計算されない問題を修正
  • feat: 検索結果のページネーションを追加
  • refactor: UserRepositoryをインターフェースベースに変更

インタラクティブrebaseでコミットを整理する

作業中は「wip」「typo修正」のような細かいコミットを積み重ねてしまうこともあります。 プルリクエストとして提出する前に、git rebase -iで コミットを整理し、意味のある単位にまとめ直すことができます。

# 直近5コミットをインタラクティブrebaseで整理する
git rebase -i HEAD~5

# エディタが開き、各コミットに対して操作を選べる
pick a1b2c3d feat: ログインフォームを追加
squash e4f5g6h wip
squash h7i8j9k typo修正
pick k0l1m2n test: ログインフォームのテストを追加

# squash を指定したコミットは直前のコミットに統合される

ポイント

rebaseによる履歴の書き換えは、まだ他の人と共有していない自分専用のブランチで 行うのが原則です。すでにpushして他の人が使っている履歴を書き換えると、 チームメンバーの作業と食い違いが生じます。

ポイント

  • • 1コミットには1つの論理的な変更だけを含める(Atomic Commit)
  • • コミットメッセージは「何を・なぜ」変更したかが伝わるように書く
  • • type接頭辞(feat/fix/refactor等)を使うとコミットの種類が一目で分かる
  • • プルリクエスト提出前にインタラクティブrebaseでコミットを整理できる
  • • 履歴の書き換え(rebase)は、まだ共有していない自分専用のブランチで行う

確認クイズ

1 / 3

アトミックなコミットの利点として正しいものはどれか?