Git/Githubのルールはちゃんと決めていますか？

# 動機
入社先企業の新人研修の中でGit/Githubを使用しているのですが、その中である程度厳密なルール設定をすることで円滑な開発ができるようになると学びました。今回はどんなルールが適切か、自分なりに言語化し、理由を併せて説明していきます。

# 目次
- [ルール](#ルール)
- [きれいなコミットを push するために心がけること](#きれいなコミットを-push-するために心がけること)

# §. ルール
## ブランチ名

ブランチ名を統一することでそのブランチでどんな作業をしているか他の人が一目で理解できるようにするため、ブランチ名のルールは設定する必要があると考えています。例えば `cherry-pick` というとても便利なサブコマンドがGitにありますが、ブランチ名やコミット名がごちゃごちゃだと `cherry-pick` が大変になったりします。そのためまずは[GitHubでブランチの命名規則を制限する方法](https://qiita.com/taclose/items/dc9eb04b97f2fbcb6fb1)とか[【github】mainブランチに対して直接pushを禁止する保護ルールを設定をする](https://zenn.dev/json_hardcoder/articles/f9b534377103a4)とかを参考に、ブランチルールやを設けることを推奨します。私なら以下のルールを設定します。ブランチ名に以下の条件を満たす物以外は `push` することもできません。

```bash
main
development
feat/**/*
fix/**/*
docs/**/*
```

それぞれどんな意味を持たせるべきか説明します。

- `main`: 基本的にはPRを出すルールとして `main` にPRを出せるのは `development` からでしかできないものとしましょう。PRのレビュワーもそこは意識してチェックしてください。
- `development`: 基本的にはこのブランチにみんなPRをだします。PRを出すことを`merge` 先を `development` に合わせるようにしてください。また`main`と同等の保護ルールをかけることを推奨します。そうしないと、GitHubの設定次第では`main`にmergeすると`development`が消えます。
- `feat/**/*`: まずこの `/**/*` ってなんなんやねんという感じですが、それはあとで解説します。`feat` は機能やページ、コンポーネントを新規追加した場合に使用するブランチです。
- `fix/**/*`: バグ修正をした場合に使用するブランチです。
- `docs/**/*`: ドキュメントのみをリポジトリに追加した場合に使用するブランチです。

良いブランチ名の例を以下に挙げます。ブランチ名は相対パスのような記述ができて(本当に何らかのディレクトリ構造が生成されるわけではない)、`feat/**/*`は`/` を2回までなら使えるという意味です。

- `feat/add-header`…〇ルールを満たす。かつ何をしているか分かりやすい。
- `feat/addHeader/navigation`…〇ルールを満たす、かつ何をしているか分かりやすい。
- `feat/header/settingIcon`…〇同上
- `feat/header/page/icon`…×`/**`を3回使用した記法は許可されていません。
- `Taro20250430react`…×`feat`から始まらないブランチは `push` できないはず。かつそもそも何をブランチなのか不明。

## コミット名

これは特に制約を掛けていないことですが、誰から見ても何をしたかわかるようなコミット名に設定しましょう。設定を設ける場合には[コミットメッセージのスタイルを統一する](https://qiita.com/pasca-l/items/40bb1d4e9afa3033db2e)の記事を参考にしてください。

- `feat: ...`：ページやコンポーネント、機能を新規追加した場合に使用するコミットです。
- `fix: ...`：バグ修正をした場合に使用するコミットです。
- `docs: ...`：ドキュメントのみをリポジトリに追加した場合に使用するコミットです。

## 他人のPRをレビューする側が気を付けること

1. merge先は`development`かどうか？(※開発の状況によっては`feat/**/*`などをmerge先とすることもある。)
2. 不自然なPRやコミットをしないこと。例えば…
   - コミット名は妥当か？
   - PR名、コミット名に関して、変更内容が一目で分かるかどうか？
   - 人名、日付が入っていないか？
  これらに該当する場合はPRをリジェクトしてほしい。Fileを編集した人名と日付はコミットログを見れば分かる。例えば `feat/Taro0615`はよくない。
1. `File Changes`は正当か。
   - `./node_modules`や`PW`、`IPAキー`などが記載された`docs`ファイルなど不必要なファイルが入っている場合はリジェクトしてほしい。
   - 変なコメントアウトがないかを確認する。例えば 
   ```python
   # 2025/04/30に変更しました(Taro)
   ```
   などは見れば分かることなので、そういった不要なコメントアウトがある場合はPRをリジェクトしてほしい。

# §. きれいなコミットを `push` するために心がけること


:::note warn
**はじめのうちコミットは小さい機能をこまめにコミットし、こまめにPRを作成しても良いかもしれません。ページ単位・コンポーネント単位・機能単位の粒度が良いかもしれません。全員がドガっとPRを出すと、`File change`が多すぎて、全員が不幸になる可能性があります。何かとこまめにコミット/PR作成をしましょう。**
:::

## 初級編

この初級編は難しい操作は一切ないので、全員しましょう。

### エイリアスの作成

まず以下のエイリアスを作成してください。エイリアスは「ショートカットキー」のようなもので、わざわざ `git status` だとか `git log --oneline` だとかを打たなくても、`git st` だとか `git logo` だとかって打てばOK…というのがエイリアスです。これがあると作業速度がほんのちょっと向上します。

1. `.gitconfig`ファイルを編集する。グローバルに導入したくない場合はリポジトリでのみ適用するよう設定することも可能である([参考](https://qiita.com/shionit/items/fb4a1a30538f8d335b35))。
    ```bash
    vim ~/.gitconfig
    ```

2. `vim` が起動したら以下の内容をコピペ。例えば `status = st` と設定すると、`git status`と打たなくても`git st`と打てば正しく出力される。もし各々こだわりがあればエイリアスを設定して下さい。
   ```bash
   [alias]
    al = config --get-regexp ^alias\.
    logo = log --oneline
    b = branch
    sw = switch
    cm = commit -m
    rb = rebase
    rbi = rebase -i
    chp = cherry-pick
    ```

3. `vim`から離脱したら、ローカルリポジトリまで移動して `git st` と打って何かしたら出たら成功。

一応備考…`i` で編集モード、`Esc`→`：wq`で保存終了。

### きれいなコミットを作るコツ


1. まず細かく `st`, `logo` などを確認する。息をするように `git st`, `git logo` をチェック。変なファイルを`add`しないか？変なコミットログになっていないか？などを確認する。
2. 機能ごとに意味のあるコミットを作成する。`git st`を確認しながらばいいが、安易に`git add .`をしてはいけない(※余談だが、同様に`git restore .`も安易にしない。爆死することがある。頑張って編集したファイルがすべて消える。)


## 中級編

個人的に、この中級編までは全員できてほしいと思っています。

### もし`origin/development`の`HEAD`が`local`の先を行っていた場合

何も考えずに `push` するとコンフリクトがとんでもないことになる可能性があるので、いったん以下の操作をしてみてください。今、仮にブランチ `feat/test`で作業していたとします。

```bash
git sw development  
git pull origin development // origin/developmentのHEADまでの情報をlocalに取得・反映。  
git sw feat/test  
git b feat/testBK // 今からいろいろコミットを破壊する恐れのある操作をするため、バックアップ(BK)ブランチを作成しておく。これ忘れると痛い目を見る可能性がある。
git rb development
```

これで**rebase**という操作ができ、手元でいろいろコンフリクトを解消してあげると、`origin/development` の `HEAD` から `feat/test` を生やし直すことができます(Gitのコミットログは`tree`構造！)。もし大失敗したら、`feat/test`を削除して、`feat/testBK`からバックアップ情報を持ってきたら良い。

### もし不要なコミットログを生まれてしまった場合

例えば`feat/test`ブランチにおいて`git logo`をしてみると、
```bash
40d404 feat: Bを修正2  // これはHEAD
afh29a feat: Bを修正  
8c8fcf feat: Aを修正
```
のようなコミットログが出力されたとする。HEADのコミットは明らかに汚い。そんな時は
```bash
git rebase -i HEAD~2
```
と打つと、`vim`が起動するのでコミットログをきれいにしてあげれば良い。ここら辺の操作をすると、もしかするとリモートリポジトリの `development` の `HEAD` がずれる可能性があるので、その場合は
```bash
git push origin feat/test -f
```
などをしてあげること。

## その他きれいなコミットを作るコマンド
- `git cherry-pick <コミットのHASH値>`…他のブランチのコミットをそのまま持ってくる。
- `git commit --amend`…直前のコミットを修正する。コミットメッセージを直せる。
- `git reset --mixed <コミットのHASH値>`…コミットを消して、stagingまで落とす。