【Git/GitHub】禁忌：git push ( -f ) origin mainを防ぐ

## 概要

先日、TwitterでGitの取り扱いについてプチバズしていたツイートを発見してその引用RTやリプで

```
$ git push origin main
$ git push -f origin main
```

は危険です！と投稿していた人が数人いました。
（`-f`オプションは強制（force）pushを意味します）

もちろん危険なのは言わずもがなですが、**ヒューマンエラーは防ぎようがないし、「そもそもちゃんと設定すれば防げるのにいいいい！」**と思ったのでサクッとまとめます。

※そのツイートの引用RTやリプでも設定に関して言及しているので現役エンジニアからすると当たり前のことだと思います。 

## 結論

**GitHubで簡単に設定できます👌**

※色々ググってみるとローカルの`.git/hooks`以下に`pre-push`というファイルを作成してローカル側でリモート（GitHub）のmain（master）ブランチへのpushを禁止する方法が多くヒットしました。が、GitHubで設定できるのでとりあえずGitHubにお任せすれば良いのではないかと思います。

参考までに

- [特定ブランチのgit push origin masterを禁止する](https://qiita.com/justin999/items/5f0f3daaf6cd4882f9cf)
- [gitでmasterへのpushを禁止する](https://qiita.com/ryoichi-u/items/7b20f9af6fc247a3fa99)
- ['git push origin master'禁止にする設定](https://qiita.com/akymrk/items/b46b03b313850e3ae418)

この辺の記事を書いている当時はGitHub側での設定機能は無かったみたいですね。

## GitHubで禁忌：git push origin (-f) mainを防ぐ設定

### 1.設定場所に行く

- GitHubの`Settings`タブの`Branches`を選択する
- `Add rule`ボタンをクリック

![スクリーンショット 2021-03-13 9.39.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512695/b5663ef4-6a46-d68c-b3de-4c27eead14c6.png)

### 2.設定項目を入力する

![スクリーンショット 2021-03-13 9.45.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512695/6dc8820a-a0a0-6a39-6a42-2de1a7993522.png)

#### Branch name pattern

保護設定を適用するブランチ名を入力するので`main`と入力。

一応パターンなので`feature/*`にすると`feature/○○`のブランチ全てに適用できるっぽい。

#### Require pull request reviews before merging

マージ前にPR（プルリク）のレビューを必須にするかどうかを選択します。
ここにチェックが必要ですね。

#### Required approving reviews

PRを承認するレビュワーの人数を設定します。（一例として2名にしてます）

※今回の趣旨とは違いますが、参考程度に。

#### Dismiss stale pull request approvals when new commits are pushed

承認済みのPRに新たにcommitがpushされた時にそのPRの承認を却下します。

※今回の趣旨とは違いますが、大事な設定だと思ったのでピックアップしました。

#### Include administrators

管理者というかリポジトリのオーナー（今回でいうと私）もこの設定内容を適用するかどうかを選択します。

![スクリーンショット 2021-03-13 9.45.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512695/50c366c0-5979-1a14-bd3a-687582f46b12.png)

#### Allow force pushes

force pushを許可するかどうかを選択します。チェックは付けないようにしましょう。
（`$ git push origin -f main`が可能に...）

#### Create

ブランチの保護設定を作成して有効にします。

### 3.作成（設定）後

![スクリーンショット 2021-03-13 10.01.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512695/99bd4105-82f7-fc0c-eb78-9020b756cd09.png)

## 試してみる

### git push origin (-f) main実行

- git push origin main
![スクリーンショット 2021-03-13 10.04.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512695/28799dbd-2de3-aab3-4cdd-d1bae5a065ca.png)

- git push -f origin main
![スクリーンショット 2021-03-13 10.04.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512695/87f01f2d-a12f-079a-387d-71ff9117c894.png)

どちらも警告が出てpushできません。 ⇒ OK(☝︎ ՞ਊ ՞)☝︎

```
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Writing objects: 100% (3/3), 302 bytes | 302.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote: error: GH006: Protected branch update failed for refs/heads/main.
remote: error: At least 2 approving reviews are required by reviewers with write access.
To https://github.com/shimotaroo/test.git
 ! [remote rejected] main -> main (protected branch hook declined)
error: failed to push some refs to 'https://github.com/shimotaroo/test.git'
```

## 参考：PR（プルリク）発行

以下コマンドでPRを発行してみる。

```
$ git switch -c feature/test
$ git add .
$ git commit -m "README.md修正"
$ git push origin feature/test

Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Writing objects: 100% (3/3), 302 bytes | 302.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote:
remote: Create a pull request for 'feature/test' on GitHub by visiting:
remote:      https://github.com/shimotaroo/test/pull/new/feature/test
remote:
To https://github.com/shimotaroo/test.git
 * [new branch]      feature/test -> feature/test
```

ちゃんとpushできたので、GitHub側でPRを作成。

![スクリーンショット 2021-03-13 10.12.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512695/ce9628bf-1279-f9e3-d117-093419d90e05.png)

先程設定した通りになっていますね。

- mainにmergeするためにはPRのレビューが必須になっている
- レビュワーを2名選択しないといけないようになっている

## まとめ

ちゃんとGitHubでmainへのpushは禁止しようね。