Git入門に向けた基礎知識整理

# 本書の目的
　本記事の目的は、Gitに関する基礎知識を習得することを目的としている。また、基礎知識に合わせて基本的なGit操作もできるようになることを目指す。
　先生はChatGPTさん

## 作業環境
| 項目 | 値 |
| :---: | :---:|
| OS | Windows11 |
| CPU | X Core |
| 実装RAM | X GB |
| Disk | X GB |

## 必要なもの
* GithubいじれるPC
* Githubのアカウント
* gitbash

## 必要な知識
* 基本的なIT知識

# 基本知識
## Gitについて
[Wikipedia引用](https://ja.wikipedia.org/wiki/Git)
>Gitは、プログラムのソースコードなどの変更履歴を記録・追跡するための分散型バージョン管理システムである。
>Linuxカーネルのソースコード管理に用いるためにリーナス・トーバルズによって開発され、それ以降ほかの多くのプロジェクトで採用されている。 

Wikiにも記載の通り、作ったプログラムファイルとか、ミドルウェアのコンフィグファイルとか、構成管理ツールのファイルとか、いろんな情報が詰まったファイルのバージョンを管理することのできるツールです。

## バージョン管理って？
　作成したファイルに対して「作ったとき」、「変更を加えたとき」などのタイミングで、バージョン管理システムにファイルを入れることで、入れたタイミングの情報を記録する。
バージョン管理ツールの利用者は、この入れたタイミングの情報から、過去の好きなバージョンに戻すことができるようになる。
なので、「うっかりファイルを削除しちゃいました。」とか「設計ミスで動かなくなっちゃいました」って時に、動作確認が取れているバージョンに戻すことですぐに復旧ができたりするわけ。


進み方はこんな感じかな？？といったイメージをMermaidで書いてみた。
https://mermaid.js.org/syntax/gitgraph.html

### イメージ図
```mermaid
gitGraph
  commit id: "New Ripository"
  commit id: "NewRelease Project-A Start"
      branch Develop
      checkout Develop
      commit id: "Developer New Release"
          branch Develop-1
          branch Develop-2
          checkout Develop-1
          commit id: "Develop 1.1"
          checkout Develop-2
          commit id: "Develop 2.1"
          checkout Develop-1
          commit id: "Develop 1.2"
          checkout Develop-2
          commit id: "Develop 2.2"
          checkout Develop-2
          commit id: "Develop 2.3"
          checkout Develop
          merge Develop-1
          merge Develop-2
      commit id: "Develop Release Done"
      checkout Develop

      branch Staging
      checkout Staging
      commit id: "Staging New Release"
          branch Staging-1
          branch Staging-2
          checkout Staging-1
          commit id: "Staging 1.1"
          checkout Staging-2
          commit id: "Staging 2.1"
          checkout Staging-1
          commit id: "Staging 1.2"
          checkout Staging-2
          commit id: "Staging 2.2"
          checkout Staging
          merge Staging-1
          merge Staging-2
          commit id: "Staging Reelase Done"
      branch Production
      checkout Production
      commit id: "Production New Release"
          commit id: "Production Update LastFixed"
      checkout main
      merge Production
  commit id: "Project-A Release Finished"
```

## Gitの基礎情報
### リポジトリ
* ファイルを格納するための場所
* リポジトリにファイルを格納することで、そのファイルの記録を残していく。
* ファイルを格納することをチェックインという。
* 取り出すときはチェックアウトというらしい

* リモートリポジトリ
    * 自身の端末以外のサーバやクラウドにリポジトリを用意し、リモート上でファイルを管理する方式
    * 会社で用意している仮想環境上やクラウドサービス上にあることが多い気がする。
    * 複数名で利用するリポジトリで、ルールが決まっていない場合とか運用が大変になっちゃう。
        * 知り合いのベテランによると、商用環境のリポジトリ勝手にいジった人がいて、障害発生したケースがあるとか、、、

* ローカルリポジトリ
    * 自分自身の端末にリポジトリを用意した環境
    * 自分一人で更新するリポジトリはこっち

### 作業環境
3つの領域があるらしい。

* ワークツリー / ディレクトリツリー
→ 実際に作業しているディレクトリ（現在のファイルの状態）
ステージ/インデックス ※ ここがわかりずらい
→ git add した変更が一時的に保存される領域（コミット前の準備エリア）
リポジトリ
→ git commit した内容が保存される領域（.git ディレクトリ内）

:::note info
Info なぜステージ（インデックス）があるのか？

　Gitでは、ワークツリーの変更を直接コミットせず、一度「ステージ」に置くことで、コミットする内容を細かく調整できるようになっています。

　file1.txt と file2.txt を修正したけど、file1.txt だけコミットしたい場合は以下のようになる。

```
git add file1.txt  # file1.txt だけステージング
git commit -m "Fix file1"
```

⇒ file2.txt の変更はワークツリーに残ったまま。

このように、「コミットする内容を選択できる」ことが Git の強み
:::

このあたり、ちゃんと理解しないと作業効率落ちそうな気がする。。

| 領域 | 説明 | コマンド |
| :---: | :---: | :---: |
| ワークツリー | 作業中のファイルがある場所 | git status |
| ステージ（インデックス） | git add したファイルが入る領域 |git add / git status|
| リポジトリ	| git commit すると保存される | git commit / git log |

## 細かい仕組み
1. ローカルにあるリポジトリにあるファイルを更新する。
2. `git add`を実行する。
    1.  指定したファイルのスナップショット（SHA-1 ハッシュで圧縮されたBlobオブジェクト）が `.git/objects/` に保存される。
    2. ステージング情報（どのファイルが追加されたか）は `.git/index`に記録される。
3. `git commit`を実行する。
    1. `.git/objects/<git addで保存されたblobデータ格納先>`に、新たにTreeオブジェクトとCommitオブジェクトが作成される。


| 領域 | 保存場所 | 役割 |
| :---: | :---: | :---: |
| ワークツリー | 実際のディレクトリ | 作業中のファイル |
| ステージ（インデックス） | .git/index | git add した変更が一時保存される |
| リポジトリ	| .git/objects/ | git commit すると SHA-1 で管理されたデータが保存される |


### `.git`内のフォルダ構成はこんな感じ
```bash
.
└── .git/
    ├── HEAD            # 現在のブランチ情報
    ├── config          # リポジトリの設定
    ├── description     # 説明ファイル（通常空）
    ├── hooks/          # フックスクリプト（カスタム処理）
    ├── index           # ステージの情報
    ├── info            # 追加情報（無視するファイルのリストなど）
    ├── logs/           # 操作履歴のログ
    ├── objects/        # コミットデータやファイルのスナップショット/
    │   ├── info/       # 
    │   └── pack/       # 
    └── refs/           # ブランチやタグの情報/
        ├── heads/      # 各ブランチの最新コミット情報
        ├── remotes/    # リモートリポジトリの情報
        └── tags/       # タグ情報
```

### こんな感じらしい。
```bash
.
└── .git/
    └── objects/        # コミットデータやファイルのスナップショット/
        ├── 1a/         # ハッシュ値上2桁で作られたディレクトリ名
        │   └── 79a7d3c4e22b2f02b4e8d82a12a4c1b9f9c60c    # blob
        └── f2/         # ハッシュ値上2桁で作られたディレクトリ名
            └── b73e4b29d03451cf344b16fa2fbb8e90d77b24    # blob
```

### 変更管理するのに必要なファイルは以下の通り
| オブジェクト | 役割 |
| :---: | :---: |
|Blob | ファイルの中身（圧縮されたバージョン）|
|Tree | ファイルやディレクトリの構成情報 |
|Commit | 変更のスナップショットとメタデータ |
|Tag | 特定のコミットに名前をつける | 

# おしまい
とりあえず長くなってきたのでここで切る。
次は実際に操作する。