よわよわエンジニアが考える最低限必要なGit・GitHubの知識

## この記事の目的
- 初心者の友人向けに説明した内容を起こしたものです
- ざっくりとまとめているので、間違っている点などがある場合は教えていただければ幸いです

## 1. GitとGitHubの違い

::: note info
GitとGitHubは似た名前ですが、実は全く異なるものです。簡単に言えば、Gitはツール、GitHubはそのツールを使うためのウェブサービスです。
:::

### Gitとは？

Gitは、プログラムのソースコードなどの変更履歴を記録・追跡するためのシステムです。

- 文書作成ソフトの「変更履歴」機能の高性能版のようなもの
- あなたのプロジェクトの「タイムマシン」として機能します

Gitでできること：
1. ファイルの変更を細かく記録する
2. 過去のどの時点の状態にも簡単に戻れる
3. 複数人で同じプロジェクトを並行して作業できる

### GitHubとは？

GitHubは、Gitで管理しているプロジェクトを保存・共有するためのウェブサービスです。

- Gitプロジェクトのための「クラウドストレージ」のようなもの
- プログラマーのための「SNS」的な側面も持っています

GitHubの主な機能：
1. リポジトリの共有：自分のプロジェクトをインターネット上に公開できる
2. プルリクエスト：他の人の提案した変更を確認し、取り入れることができる
3. イシュー管理：プロジェクトの課題や改善点を管理できる

::: note warn
GitHubの多くの機能は無料で使えますが、公開されたプロジェクトは誰でも見ることができますが、無料プランでは利用できない機能もあるので注意が必要です。
:::

### GitとGitHubの関係

1. Gitはあなたのパソコン上で動く「ローカル」のツール
2. GitHubはインターネット上にある「リモート」のサービス
3. Gitで管理したプロジェクトをGitHubにアップロードして共有する

## 2. Gitの仕組みで最低限必要なこと

### 用語説明

1. リポジトリ（Repository）
   - プロジェクトのすべての履歴を含むデータベース
   - ローカルリポジトリ（自分のPC上）とリモートリポジトリ（GitHubなど）がある

2. コミット（Commit）
   - 変更の保存単位
   - 「いつ」「誰が」「何を」変更したかを記録する

3. ブランチ（Branch）
   - 並行して開発を進めるための機能
   - メインの開発ラインから分岐して作業できる

### 基本的なコマンドと使用例

1. git init
   - 説明：新しいGitリポジトリを作成する
   - 使用例：
     ```
     $ mkdir my_project
     $ cd my_project
     $ git init
     Initialized empty Git repository in /path/to/my_project/.git/
     ```

2. git add
   - 説明：変更をステージングエリアに追加する
   - 使用例：
     ```
     $ touch README.md
     $ git add README.md
     ```

3. git commit
   - 説明：ステージングエリアの変更をコミットする
   - 使用例：
     ```
     $ git commit -m "Add README file"
     [main (root-commit) f7f3f6d] Add README file
      1 file changed, 0 insertions(+), 0 deletions(-)
      create mode 100644 README.md
     ```

   ::: note warn
   コミットメッセージは具体的かつ簡潔に書くことが重要です。
   例：「ファイルを更新」ではなく「ユーザー登録機能を追加」
   :::

4. git merge
   - 説明：ブランチの変更を統合する
   - 使用例：
     ```
     $ git checkout main
     $ git merge feature-branch
     Updating f7f3f6d..1a2b3c4
     Fast-forward
      README.md | 2 ++
      1 file changed, 2 insertions(+)
     ```

5. git checkout
   - 説明：ブランチを切り替える、または新しいブランチを作成する
   - 使用例：
     ```
     # 既存のブランチに切り替え
     $ git checkout develop

     # 新しいブランチを作成して切り替え
     $ git checkout -b feature-login
     Switched to a new branch 'feature-login'
     ```

### 実際の利用シナリオ

以下は、新しい機能を追加する一般的なワークフローです：
```
# 新しいブランチを作成
$ git checkout -b feature-user-profile

# ファイルを編集...

# 変更をステージングに追加
$ git add user_profile.py

# 変更をコミット
$ git commit -m "Add user profile page"

# メインブランチに戻る
$ git checkout main

# 機能ブランチの変更をメインブランチにマージ
$ git merge feature-user-profile

# 機能ブランチを削除（オプション）
$ git branch -d feature-user-profile
```

## 3. GitHubにPushする方法

### 用語説明

1. リモートリポジトリ
   - GitHubなどのサーバー上にあるリポジトリ
   - ローカル（自分のPC）のリポジトリと区別するために使われる

2. ステージング
   - コミットする前に、変更したファイルを準備エリアに追加すること

3. プッシュ（Push）
   - ローカルの変更をリモートリポジトリに送信すること

### コマンドの説明と使い方

1. git remote add
   - 説明：ローカルリポジトリにリモートリポジトリを追加する
   - 使用例：
     ```
     $ git remote add origin https://github.com/username/repository.git
     ```

2. git push
   - 説明：ローカルの変更をリモートリポジトリに送信する
   - 使用例：
     ```
     # 初回プッシュ時
     $ git push -u origin main

     # 2回目以降
     $ git push
     ```

### 実際のイメージ

以下は、新しい変更をGitHubにプッシュするまでの一般的なワークフローです：

```
# 1. ファイルを編集する
$ echo "# My Project" > README.md

# 2. 変更をステージングに追加
$ git add README.md

# 3. 変更をコミット
$ git commit -m "Add README file"

# 4. GitHubにリポジトリを作成し、URLをコピー

# 5. ローカルリポジトリにリモートを追加
$ git remote add origin https://github.com/username/my-project.git

# 6. 変更をGitHubにプッシュ
$ git push -u origin main

Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 226 bytes | 226.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/username/my-project.git
 * [new branch]      main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.
```

::: note info
最初のプッシュ時に `-u` オプションを使用すると、以降は単に `git push` だけでプッシュできるようになります。
:::

このワークフローを通じて、ローカルで行った変更をGitHubのリモートリポジトリに反映させることができます。GitHubのウェブサイトで確認すると、プッシュした内容が反映されているはずです。

::: note warn
公開リポジトリにプッシュする際は、機密情報や個人情報を含めないよう注意しましょう。
:::

## 4. GitHubから取得する方法

### 用語説明

1. プル（Pull）
   - リモートリポジトリの変更を取得し、ローカルのブランチに統合すること
   - `git fetch` と `git merge` を一度に行う操作

2. フェッチ（Fetch）
   - リモートリポジトリの変更を取得するだけで、ローカルのブランチには統合しない操作
   - 変更内容を確認してから統合したい場合に使用する

### コマンドの説明と使い方

1. git pull
   - 説明：リモートの変更を取得し、現在のブランチに統合する
   - 使用例：
     ```
     $ git pull origin main
     ```

2. git fetch
   - 説明：リモートの変更を取得するが、ローカルブランチには統合しない
   - 使用例：
     ```
     $ git fetch origin
     ```

### 実際のイメージ

#### git pull の使用例

```
# リモートの main ブランチから変更を取得し、ローカルの現在のブランチに統合
$ git pull origin main

remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/username/repository
 * branch            main       -> FETCH_HEAD
   a1b2c3d..e4f5g6h  main       -> origin/main
Updating a1b2c3d..e4f5g6h
Fast-forward
 README.md | 2 ++
 1 file changed, 2 insertions(+)
```

この例では、リモートの変更がローカルのブランチに直接統合されています。

#### git fetch の使用例

```
# リモートの変更を取得するが、まだ統合はしない
$ git fetch origin

remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/username/repository
   a1b2c3d..e4f5g6h  main       -> origin/main

# 変更内容を確認
$ git diff origin/main

# 変更を確認した後、必要に応じて統合
$ git merge origin/main

Updating a1b2c3d..e4f5g6h
Fast-forward
 README.md | 2 ++
 1 file changed, 2 insertions(+)
```

この例では、まず変更を取得し、その後で変更内容を確認してから統合しています。

::: note info
`git fetch` は変更を安全に確認したい場合に便利です。一方、`git pull` は素早く変更を反映したい場合に適しています。
:::

::: note warn
`git pull` を使用する前に、ローカルの変更をコミットまたはスタッシュしておくことをお勧めします。そうしないと、コンフリクトが発生する可能性があります。
:::

## 4. GitHubから取得する方法

### 用語説明

1. プル（Pull）
   - リモートリポジトリの変更を取得し、ローカルのブランチに統合すること
   - `git fetch` と `git merge` を一度に行う操作

2. フェッチ（Fetch）
   - リモートリポジトリの変更を取得するだけで、ローカルのブランチには統合しない操作
   - 変更内容を確認してから統合したい場合に使用する

### コマンドの説明と使い方

1. git pull
   - 説明：リモートの変更を取得し、現在のブランチに統合する
   - 使用例：
     ```
     $ git pull origin main
     ```

2. git fetch
   - 説明：リモートの変更を取得するが、ローカルブランチには統合しない
   - 使用例：
     ```
     $ git fetch origin
     ```

### 実際のイメージ

#### git pull の使用例

```
# リモートの main ブランチから変更を取得し、ローカルの現在のブランチに統合
$ git pull origin main

remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/username/repository
 * branch            main       -> FETCH_HEAD
   a1b2c3d..e4f5g6h  main       -> origin/main
Updating a1b2c3d..e4f5g6h
Fast-forward
 README.md | 2 ++
 1 file changed, 2 insertions(+)
```

この例では、リモートの変更がローカルのブランチに直接統合されています。

#### git fetch の使用例

```
# リモートの変更を取得するが、まだ統合はしない
$ git fetch origin

remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/username/repository
   a1b2c3d..e4f5g6h  main       -> origin/main

# 変更内容を確認
$ git diff origin/main

# 変更を確認した後、必要に応じて統合
$ git merge origin/main

Updating a1b2c3d..e4f5g6h
Fast-forward
 README.md | 2 ++
 1 file changed, 2 insertions(+)
```

この例では、まず変更を取得し、その後で変更内容を確認してから統合しています。

::: note info
`git fetch` は変更を安全に確認したい場合に便利です。一方、`git pull` は素早く変更を反映したい場合に適しています。
:::

::: note warn
`git pull` を使用する前に、ローカルの変更をコミットまたはスタッシュしておくことをお勧めします。そうしないと、コンフリクトが発生する可能性があります。
:::

## 5. GitHubからクローンする方法

### クローン（git clone）の説明
クローンとは、リモートリポジトリの完全なコピーをローカル環境に作成することです。

### 使用例
```
$ git clone https://github.com/username/repository.git
Cloning into 'repository'...
remote: Enumerating objects: 100, done.
remote: Counting objects: 100% (100/100), done.
remote: Compressing objects: 100% (80/80), done.
remote: Total 100 (delta 20), reused 90 (delta 10), pack-reused 0
Receiving objects: 100% (100/100), 50.00 KiB | 1.00 MiB/s, done.
Resolving deltas: 100% (20/20), done.
```

::: note info
クローンすると、自動的にリモートリポジトリが「origin」という名前で追加されます。
:::

## 発展的な内容

::: note warn
以下の発展的なトピックは、基本的な操作に慣れてから挑戦することをおすすめします。
:::

### 6. コンフリクト

#### コンフリクトとは
- 複数の人が同じファイルの同じ部分を異なる方法で変更した場合に発生する衝突

#### コンフリクトの解決方法
1. コンフリクトが発生したファイルを開く
2. コンフリクトマーカー（<<<<<<<, =======, >>>>>>>）を探す
3. 競合している部分を適切に編集
4. 変更をステージングし、コミットする

#### コンフリクトを避けるためのベストプラクティス
- 頻繁に小さな変更をプッシュする
- 作業前に最新の変更を取り込む
- 異なるファイルや異なる部分を編集するよう、チーム内で調整する

### 7. スタッシュ

#### スタッシュの使用シーン
- 作業途中の変更を一時的に保存したい場合
- ブランチを切り替える前に現在の変更を保存したい場合

#### 基本的なスタッシュコマンド
```
# 変更をスタッシュに保存
$ git stash

# スタッシュから変更を復元し、スタッシュから削除
$ git stash pop
```

### 8. コミットをまとめる

#### リベース（git rebase -i）の使用方法
1. リベースを開始: `git rebage -i HEAD~3`（最新の3つのコミットを編集）
2. エディタでコミットの順序や操作を編集
3. 変更を保存してエディタを閉じる
4. 必要に応じてコミットメッセージを編集

#### コミットの整理とクリーンアップ
- 複数の小さなコミットを1つの意味のあるコミットにまとめる
- 不要なコミットを削除する
- コミットメッセージを改善する

::: note alert
リベースは履歴を書き換えるため、共有ブランチでの使用には注意が必要です。
すでにプッシュされたコミットをリベースすると、他の開発者に影響を与える可能性があります。
:::