【Git初心者向け】今更ながらGitをフレンチコースに見立てて解説してみた

# 概要 
嫁さん(初心者)にお酒を飲みながらGitを教えてたらこれってフレンチのコース料理に例えられるのでは！？と閃いたので作ってみました。
初学者の方にGitを難しいものと思わず、何か掴めるきっかけになれるよう解説していきます。

# おことわり
- ブランチの運用については明記しません。
- mainブランチと作業ブランチのみで構成されているとします。
- すでにリポジトリがある状態からの話です（リポジトリ作成には踏み込みません）。
- 頭の中でのイメージ重視ですのでXXXについての記述が抜けてる！とかありますが必要があれば自分で付け加えて覚えてください。

概念的にコマンドの意味を知れますが、実際の現場では運用方法等が違うかもしれませんので詳しくは先輩に聞いてください。。。


# 前提条件

## あらすじ

|料理|シェフである私が新作コース「季節のお楽しみディナー」を考案中。|
|:--|:--|
|Git|コーダーの私があるサイトに「お問い合わせフォーム」を追加したい。|

|料理|オーナーに試食してもらい合格が出たらお店に並べたいと思っています。|
|:--|:--|
|Git|先輩にプルリクエストを出し問題がなければ本番環境にリリースしたいと思っています。|

## レストラン
### お品書き
```
# 季節のお楽しみディナー
オードブル
スープ
ポワソン
ソルベ
アントレ
デセール
カフェ・ブティフール
```

### 店内の図
![79027724-8F50-499C-8E39-BD519106277C.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162539/e6e72006-00fe-d6c7-f397-8f054f05bb01.png)


# 1. 料理検討会を開く

新しいコースメニューをお店に並べる前に並べて良いかオーナーに確認が必要です。

|料理|料理検討会を開きましょう。|
|:--|:--|
|Git|作業用のブランチを切りましょう。|

```bash
git checkout -b <ブランチ名>
```

<details><summary><b>実際の流れ(開く)</b></summary>

ブランチを切るもとのブランチに今自分がいるか確認。
（main からブランチを切りたいとする）
```bash
$ git branch
* main
```
ブランチを切ります。
ブランチを切ると自動的にそのブランチに移ります。
```bash
$ git checkout -b seasonal_delight_dinner/20230412
Switched to a new branch 'seasonal_delight_dinner/20230412'
```
正しいブランチに移れたか念の為確認します。
```bash
$ git branch
  main
* seasonal_delight_dinner/20230412
```
</details>

:::note
ブランチ = 料理検討会
:::

# 2.料理を作る  

|料理|厨房の中で料理を模索。|
|:--|:--|
|Git|(Gitで管理している)ディレクトリでコードを書く。|

詳しくみると、厨房(PC)には厨房台(ディレクトリ)があって、そこに食材(ファイル)が並んでいます。
その食材を調理（変更・コーディング）してお皿に盛り付けることで料理が完成すると考えます。
（混ぜるだけで料理はできないよ！という批判は無しで。。。）


:::note
変更(コーディング) = 調理
PC = 厨房
ディレクトリ = 厨房台
ファイル = 食材
:::


  
# 3. いざ料理を提供する
## 3.1. 食材の調理の確認  

|料理|1つの食材が正しく調理されているか確認。|
|:--|:--|
|Git|1つのファイルが正しく変更（追加）されているか確認。|

正しく料理できたか確認しますよね。（見た目の確認、海苔忘れてないかとか）  
この作業ができていない人が多いと感じます。  
料理を食べる人（オーナー、Gitで言えば先輩 = レビュワー）に迷惑かけたくないですよね。  
正しい差分が入っているか、入れ忘れがないか、タイプミスがないか確認しましょう。  

まずは今の厨房台の状況を確認しましょう。  
```
$ git status
```
食材（差分ありのファイルの中身）を確認しましょう。 
```
$ git diff <ファイル名>

# 引数にファイル名をつけないと全ファイルの差分が見れます
$ git diff
```

:::note
git diff = 調理の確認
:::

※ 実際の流れは 3.2. でまとめて紹介します


## 3.2. お皿に盛り付け

|料理|1品ごとにお皿に盛り付け。|
|:--|:--|
|Git|1機能分に必要な変更ファイルをステージングエリアにあげる。|

3.1. で調理内容を確認して正しければ食材をお皿の上へ置きましょう。
```
$ git add <ファイル名>
```
このときにお皿が置いてあるところが配膳前のデシャップ台（ステージングエリア）です。
盛り付けが微妙だったらさらに食材を調理しなおして盛りつけ直すことができます。
`git add` は何度でも行うことができます。

<details><summary><b>実際の流れ(開く)</b></summary>


### 編集から git add まで
トマトケチャップと玉ねぎのみじん切りを新規に作成
```
$ touch chopped_onion.txt
$ touch tomato_sauce.txt
$ echo "適度に切る." > chopped_onion.txt
$ echo "トマト缶を利用." > tomato_sauce.txt
```
現状の確認。
```
$ git status
On branch seasonal_delight_dinner/20230412

Untracked files:  # 厨房台（新たな食材）
	chopped_onion.txt
	tomato_sauce.txt
```
デシャップ台に玉ねぎのみじん切りを追加
```
$ git add chopped_onion.txt
$ git status               
On branch seasonal_delight_dinner/20230412

Changes to be committed:  # デシャップ台
	new file:   chopped_onion.txt

Untracked files:  # 厨房台（新たな食材）
	tomato_sauce.txt
```

### git add した後にさらに差分（修正）がある場合
料理名を決める（commit）前にさらに玉ねぎのみじん切りに手を加えたい場合

手を加える
```bash
$ echo "荒く5mm程度の大きさ." > chopped_onion.txt
```
現状の確認。
```bash
$ git status
On branch seasonal_delight_dinner/20230412

Changes to be committed:  # デシャップ台
	new file:   chopped_onion.txt

Changes not staged for commit:  # 厨房台（すでにある食材に対しての変更）
	modified:   chopped_onion.txt

Untracked files:  # 厨房台（新たな食材）
	tomato_sauce.txt
```
差分を確認
```bash
$ git diff  chopped_onion.txt
diff --git a/chopped_onion.txt b/chopped_onion.txt
index f0ff485..40c7ee7 100644
--- a/chopped_onion.txt
+++ b/chopped_onion.txt
@@ -1 +1 @@
-適度に切る.
+荒く5mm程度の大きさ.
```

上記の差分が必要な場合
変更をデシャップ台のものに適用する。
```
$ git add chopped_onion.txt
```

上記の差分が不要な場合  
変更を無かったことにする。（破棄する）
```
$ git checkout chopped_onion.txt
```
</details>



:::note
ステージングエリアにあげる = お皿に盛り付け
:::


## 3.3. お皿に料理名をつける

お皿に盛り付けが完了したら料理名をつけてあげましょう。

その前にくどいようですが念のため確認を。。。
|料理|ちゃんと食材が全て入っているか再度確認しましょう。|
|:--|:--|
|Git|必要なファイルがステージングされていることを確認しましょう。|
```
$ git status
```
正しければ
|料理|お皿に料理名をつけましょう。<br>（季節感じるエビの和風パスタとか）|
|:--|:--|
|Git|コミット名をつけましょう。|

```
$ git commit -m "<料理名>"
```

:::note
コミット = 料理
:::

### 注意点
このお皿の単位を作るときに気をつけたいことは下記になります。  
- なるべく変更点が少ないようにコミットする
- 複数の作業を混ぜない

お口直しのソルベの中にフォアグラが入ってたら嫌ですよね。（嫌じゃなくても嫌と言うことにしてください）  

  
### メニュー名を間違えた時は...  
あわてて料理名噛むことありますよね。  
```
$ git commit -m "スズキのポワレ"
```
としたかったとき  
```
$ git commit -m "佐々木のポワレ"
```
と言ってしまうかもしれません。訂正したいですよね。
```
$ git commit --amend
```
と打つとエディターが開きますのでコメント名を修正することができます。



# 4. テーブルへ配膳  
料理が１品できて満足してはいけません。作った料理を配膳しましょう。  
配膳しておかないと、間違えて廃棄してしまう（PCが壊れて何をしていたか忘れてしまう）可能性があります！

|料理|ウエイターを使ってテーブルへ料理を配膳。|
|:--|:--|
|Git|インターネット経由（SSH or HTTP）でリモートブランチへコミットを送信。|

```
$ git push origin <ブランチ名>
```

:::note
リモートブランチ = テーブル
git push = （テーブルへ）配膳
:::



# 5. コースの配膳が完了  

|料理|2-4を繰り返し全部の料理を配膳し終わりました。|
|:--|:--|
|Git|作成（修正）したい項目の作業が全て終わりました。|

次に  

|料理|オーナーを呼び、コースの評価をしてもらうためにチェックシートを渡し食べてもらいましょう。|
|:--|:--|
|Git|先輩に変更内容が正しいか確認してもらうためにプルリクエストを作りレビューしてもらいましょう。|

提供する予定ではなかった料理を配膳していないでしょうか。
評価してもらう前に一呼吸おいて自分でも一度確認しましょう。

GitHub を使っていれば下記のようになります。  

https://github.com/ryotafull/french_restaurant/pull/1
  
|料理|チェックシートを元に合格が出たら、晴れてそのコースはお客様に提供できます。|
|:--|:--|
|Git|プルリクエストがapproveされたら、mainブランチにマージしリリースできる。|

万が一NGが出た場合は修正して再度プルリクエストを見てもらいましょう。

:::note
プルリクエスト = オーナーが評価するためのチェックシート
approve = 合格
mainブランチにマージ = お店に並べる（厳密に言えばリリース作業が入ります）
:::

  
### 注意点

|料理|オーナーも100品連続で食べた後だと流石に1品目覚えていない。|
|:--|:--|
|Git|プルリクエストも全体で見ればコミットの一つなのでできる限り小さい方がレビューしやすく喜ばれます。|





# 6. コースの合格が出た後日談  
このようにしてコースが出来上がり  
```
... ->  季節のお楽しみディナー -> お手軽コース -> XXXコース -> ...
```
とコースが増えていきそのお店がより良くなっていくことでしょう。  
ただし、直送野菜が届かなくなったときはコースを取り下げるかもしれません。  
そのような変更もできてしまうのが Git です。  
詳しくは調べていただきたいですが下記のようなコマンドがあったりします。
```
$ git revert <commit番号>
```
このほかにも便利 or 高度なコマンドがありますが必要に応じて調べて使ってみてください。  

# その他. テクニック
## 厨房を綺麗に保つ

厨房汚いと嫌ですよね。必要な包丁も食材も見つからないかもしれませんし、  
他のコースで使う食材も混ざってしまってるかもしれません。

まずは 

|料理|自分がどのコースの料理検討会を行っているか逐一確認しましょう。|
|:--|:--|
|Git|自分がどのブランチで作業しているか逐一確認しましょう。|


```
$ git branch
  main
* seasonal_delight_dinner/20230412
```
「*」マークがあるブランチ名で作業していることになります。


また、逐一下記をしましょう。困ったらこれです。

|料理|厨房の中の厨房台・デシャップ台・食材庫のなかを確認。|
|:--|:--|
|Git|正しい変更が行われているかWorking Tree・ステージングエリア・Untracked fileを確認|


```
$ git status
```

今作業中の厨房台に乗っている食材（ファイル）とデシャップ台（ステージングエリア）に乗っている食材が確認できます。

<details><summary><b>サンプルコード(開く)</b></summary>

```bash
$ git status
On branch main

Changes to be committed:  # デシャップ台
	new file:   chopped_onion.txt

Changes not staged for commit:  # 厨房台（すでにある食材に対しての変更）
	modified:   chopped_onion.txt

Untracked files:  # 厨房台（新たな食材）
	tomato_sauce.txt
```
</details>




## 料理のレシピをメモしておく

料理作っているときに、あれ、他の方法も試してみたいとなる時ありますよね。  
そんな時は今作っていた料理のレシピをメモして別の作業をしても良いのです。

コマンドで言うと  
```
$ git stash save "<料理名(仮)>"
```
となります。これを実行した後はまっさらな状態になりますので新たな作業が始められます。

```
$ git status
```
しても何もないはずです。


このレシピ本（保存した変更履歴）を確認するのは下記となります。  
```
$ git stash list
```  
料理を再度作成する（ローカルに保存した時点の状態を再現する）コマンドが下記となります。
```
$ git stash apply <stash番号>

# 例) 最新のstashを戻す
$ git stash apply stash@{0}
```
この時、厨房台（ローカルリポジトリ）が綺麗な状態で実行しないと変更が正しく反映されないこともあります。また、過去に履歴を保存した時点と現在の時点が異なっている場合「コンフリクト」が起こる場合があります。  
※コンフリクトについて説明すると長くなるので起きたときに調べてください。


# Gitとフレンチの相対表
ここまでの流れを元に GitHub に実際にリポジトリを作ってみました。

https://github.com/ryotafull/french_restaurant

## お店に並ぶメニュー

https://github.com/ryotafull/french_restaurant/commits/main

```
レストランのメニュー = mainブランチに含まれている変更内容

- 季節のお楽しみディナー = プルリクエスト後に作成されたmainブランチへのコミット
- お手軽コース = プルリクエスト後に作成されたmainブランチへのコミット
```
※プルリクエストがmainブランチにsquash mergeされている様子


## お品書き
お問い合わせフォームの作成をお品書きに沿って並べてみると（空想）
```
# 季節のお楽しみディナー = お問い合わせフォーム作成
オードブル = 大枠デザインのコミット
スープ = バックグラウンドのコミット
ポワソン = フロントデザインのコミット
ソルベ = 文言修正のコミット
アントレ = テスト追加のコミット
デセール = テスト修正のコミット
カフェ・ブティフール = リファクタのコミット
```


## 店内の図
git に置き換えたら何になるかを記載しました。
![DAC76EAD-1212-4039-B990-DBF00A6961F7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162539/f511951a-72b0-bf83-83a2-148e583cbcea.png)




# おわりに  
Git と言われてもどうとっかかっていいものかわからないと思います。
なので頭にイメージがあればそのコマンドがどの役割をしているか考えやすいと思いますのでこのような例を挙げてみました。
参考になりましたら幸いです。

# full dict
[私自身のサイト](https://home.ryotafull.com/)でも日々思いついたこと学んだことをフランクに配信しています！