良いコミットから良いコードにしていく

## これは何？
⚠ **これは自分への戒めと宣言を込めた記事です。**

どんなに素晴らしいプロダクトでも、その基盤となるのは日々の小さな積み重ねです。
ソフトウェア開発において、その積み重ねの最も小さな単位の一つが**コミットメッセージ**なのではないでしょうか。

コードを書き終えた後に軽い気持ちで「fix issue」や「update」といった適当なコミットメッセージをつけていませんか？  
（自分は「fix rubocop」とかやっちゃうことあります…）

実は、この些細に見える一手間が、**チームやプロダクトの未来を大きく変える力を持っています**。  
良いコミットメッセージを書くことは、コードの品質を向上させるだけでなく、設計への意識を高め、結果として優れたプロダクトを生み出すための第一歩です。

この記事では、「なぜコミットメッセージが重要なのか」「どうすれば良いコミットを実現できるのか」について深掘りし、その実践方法を具体的にご紹介します。


## 自動コミットメッセージ生成ツールの便利さと限界
最近は[auto-commit](https://github.com/m1guelpf/auto-commit)や[opencommit](https://github.com/di-sukharev/opencommit)などの自動コミットメッセージ生成ツールを使って、コミットメッセージを自動生成することが可能になっています。

これらのツールは、**使用者の文章生成の手間を大幅に削減**し、大変便利です。特に、**美しく設計された実装**においてはその価値を存分に発揮します。

ただし、**設計が不十分な場合には限界がある**ことも理解しておく必要があります。

- **目的やスコープが抽象的なメッセージとなって履歴の役割を真っ当できない**:
  - 同じ目的の範囲にない変更を1つのコミットにまとめたり、抽象度が高すぎる目的を設定すると、後で履歴を追うのが困難になります。
  
- **影響範囲が大きくなり、取り消しにくくなる**:
  - 意図が曖昧なコミットだと、何か問題があった時に影響範囲が広がり、リバート作業が複雑化します。

だからこそ、**コミットメッセージを単なる形式的なものとしてではなく、実装の意図や設計を考えるきっかけとして活用するべき**なのです。

## 最初にコミットメッセージを考えるアプローチ
実装を始める前に、「このコミットで何を達成したいのか」を明確に言語化することは、設計を意識した実装を可能にします。

例えば、「ログイン処理にOAuth2を導入し、トークンリフレッシュ機能を追加する」場合を考えてみます。
あらかじめ実装ステップを分解しておくとコミットメッセージは以下のように考えられます。


1.現行の認証コードを整理し、OAuth2の導入に対応しやすい基盤を作る。
```
refactor(auth): introduce unified interface for authentication
- Add strategy pattern for authentication
- Extract common logic for error handling
- Prepare placeholder for OAuth2 integration
```

2.OAuth2ログイン機能を実装する。
```
feat(auth): add OAuth2 login flow

- Implement OAuth2 login process
- Add error handling for OAuth-specific issues
- Update user session management for token-based auth
```

3.トークンリフレッシュ機能を実装する。
```
feat(auth): implement token refresh mechanism

- Add background token refresh process
- Handle token expiration gracefully
- Update documentation for session management
```

1つ1つのコミットの目的、スコープが限定されていてわかりやすいですね。

## コミットメッセージの規約を導入して基準を作ろう
良いコミットメッセージを習慣化するためには、チーム全体で統一された規約を導入することが効果的です。以下のようなメリットがあります。

1. コードレビューが効率化
意図が明確であるため、レビュワーが「何を」「なぜ変更したのか」を一目で理解できます。結果として、レビューの質とスピードが向上します。

2. 履歴がドキュメント代わりになる
過去の変更を追いやすくなり、特にバグ修正時やリファクタリング時に役立ちます。

3. チーム全体の品質向上
規約を守ることで、設計意識が高まり、全員が一貫性のあるコードを作る文化が醸成されます。

## コミットメッセージ規約の例
- **Angular Commit Message Guidelines**:  
  Angularプロジェクトで採用されているコミットメッセージ規約です。  
  コミットメッセージを以下の形式で記述することを推奨しています:
```
type(scope): subject
body
footer
```

- **type例**: `feat`（新機能）、`fix`（バグ修正）、`refactor`（リファクタリング）など。
- **scope例**: 変更対象のモジュールやコンポーネント名。
- **subject**: 変更内容を簡潔に記述（50文字以内）。

詳細: [Angular Commit Message Guidelines](https://github.com/angular/angular/blob/main/CONTRIBUTING.md#-commit-message-guidelines)


- **Conventional Commits**:  
こちらは、広く採用されている規約で、以下のような形式を推奨しています:
```
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
```
- **type例**: `feat`、`fix`、`docs`（ドキュメントの変更）など。
- **description**: 簡潔に変更内容を記述。
- **footer**: 必要に応じてBREAKING CHANGEやIssue番号を記載。

詳細: [Conventional Commits](https://www.conventionalcommits.org/)


## 負債をコミットしないためにpre-commitに入れるべきもの
ここまで読んでくださったみなさんは「コミット頑張ろう🔥」となっていることでしょう。
しかし、仕組み化しないと、人は忘れます。
[pre-commit](https://pre-commit.com/)を使ってなるべく変なコミットをしないようにしておきましょう。

1. コミットメッセージの検証
メッセージが規約に従っているかをチェック。
例: [commitlint](https://commitlint.js.org/)を使用する
2. コードスタイルの自動修正
誤ったコードフォーマットを直し、可読性を上げる。
例: [rubocop](https://github.com/rubocop/rubocop) (Ruby), [prettier](https://prettier.io/) (JavaScript/TypeScript)を活用して自動フォーマット。
3. 静的解析
型エラーや依存関係の問題を防ぐ。
例: [sorbet](https://sorbet.org/)（Ruby）
4. テストコードチェック
アプリケーションコードの変更時に、テストコードの変更がない場合はエラーを出す。
5. Typoチェック
スペルミスを検出し、未然に修正。
例: [cspell](https://cspell.org/)

## 良いコミットの習慣を今日から始めよう
良いコミットメッセージは、コードベースを進化させる原動力です。設計を意識したコミットの積み重ねが、プロダクトの品質を高め、チーム全体の効率を向上させます。
ここまで書いた自分も、これらを遵守したエンジニアになると誓います。
この記事を読んだ皆さんも、ぜひ1つのコミットメッセージを意識することから始めてみてください！
自身を含め、未来に携わるエンジニアが感謝してくれるはずです！

## 参考文献
- [Angular Commit Message Guidelines](https://github.com/angular/angular/blob/main/CONTRIBUTING.md#-commit-message-guidelines)
- [Conventional Commits](https://www.conventionalcommits.org/)
- [auto-commit](https://github.com/m1guelpf/auto-commit)
- [opencommit](https://github.com/di-sukharev/opencommit)
- [pre-commit](https://pre-commit.com/)
- [commitlint](https://commitlint.js.org/)
- [rubocop](https://github.com/rubocop/rubocop)
- [prettier](https://prettier.io/)
- [sorbet](https://sorbet.org/)
- [cspell](https://cspell.org/)
- [【Git】コミット直前に自動でファイルを整形する「pre-commit」が便利すぎたので紹介したい](https://dev.classmethod.jp/articles/introduce-pre-commit/)