「originってどこにいるの？」.gitフォルダの中身からGitの仕組みを紐解く

# はじめに
前回gitignoreの使い方や設定時の注意点をまとめました。

https://qiita.com/channnnsm/items/8e92a01c9d653ed396df

当初gitとつくから、`.gitフォルダ`に入っているもんだと思っていましたが、整理した中で、`.gitフォルダ`と`.gitignoreファイル`の役割の違いを理解しました。

普段何気なく使っていた`git push origin ブランチ名`のoriginがどこにいるのかが明らかになって、はれてgitコマンドの意味を語れるようになりました。

また、Git履歴を消して新規リポジトリとして管理したいケースがあり、その手順も残します。

最初にまとめを貼っておきます！
![](https://storage.googleapis.com/zenn-user-upload/dd79f8042dd3-20250302.png)

# `.gitフォルダ`と`.gitignoreファイル`ってどう違うんだっけ
## まずGitフォルダを表示する
そもそもGitフォルダは、`.`で始まる隠しファイルで、初期設定だと表示されません。
Windows環境でCursorに`.gitフォルダ`を表示するには、以下の方法を試しました。

1. Cursor Settings > General > AppearanceのOpen editor settings.を開く
![](https://storage.googleapis.com/zenn-user-upload/89716c076558-20250301.png)

2. 検索バーに「files.exclude」と入力
3. `.gitフォルダ`が除外されている場合、リストから削除する
![](https://storage.googleapis.com/zenn-user-upload/9c90e43737ba-20250301.png)

他のエディタでの表示方法については、各エディタのドキュメントをご参照ください。

## **Gitの基本構造と`.gitignore`の役割**
Gitの基本的な仕組みや「.git」ディレクトリの役割、fetchやremotesの概念を整理します。
（※ディレクトリもフォルダも同じ意味合いで使っています）

### **1. `.git` ディレクトリ**
- `git init`を実行すると、カレントディレクトリに **`.git`** という隠しフォルダが作成される
- **このフォルダがGitの「履歴管理」のすべてを保持**しており、以下のようなものが含まれる
  - **`hooks`**: Gitフックのサンプルスクリプト（Git操作の前後に自動的にアクションを実行できる）
  - **`info`**: リポジトリに関する追加情報
  - **`objects`**：コミットデータやファイルのスナップショット
  - **`refs`**：ブランチやタグの情報
      - **`heads`**：ローカルのブランチの情報
      - **`remotes`**：リモートのブランチの情報 ※初期状態では存在しないが、リモートリポジトリを追加するとここに格納
          - **`origin`**：よく使うoriginはremotesの配下にいる！

**→ `.git` を削除するとGitの管理情報が失われ、追跡が解除される。**

📅※2025年3月3日時点で、`git init`したときの初期状態のディレクトリ構成
```bash
.git
├── hooks  # Gitフックのスクリプトが格納されるディレクトリ
│   ├── applypatch-msg.sample  # applypatch-msgフック
│   ├── commit-msg.sample  # commit-msgフック
│   ├── fsmonitor-watchman.sample  # fsmonitor-watchmanフック
│   ├── post-update.sample  # post-updateフック
│   ├── pre-applypatch.sample  # pre-applypatchフック
│   ├── pre-commit.sample  # pre-commitフック
│   ├── pre-merge-commit.sample  # pre-merge-commitフック
│   ├── pre-push.sample  # pre-pushフック
│   ├── pre-rebase.sample  # pre-rebaseフック
│   ├── pre-receive.sample  # pre-receiveフック
│   ├── prepare-commit-msg.sample  # prepare-commit-msgフック
│   ├── push-to-checkout.sample  # push-to-checkoutフック
│   ├── sendemail-validate.sample  # sendemail-validateフック
│   ├── update.sample  # updateフック
├── info  # Gitの補助情報を格納するディレクトリ
│   ├── exclude  # グローバルな.gitignoreのような機能を持つファイル
├── objects  # Gitオブジェクト（コミット・ツリー・ブロブ）を格納するディレクトリ
│   ├── info  # オブジェクト関連のメタデータを格納するディレクトリ
│   ├── pack  # Gitのパックファイル（圧縮されたオブジェクト）を格納するディレクトリ
├── refs  # ブランチやタグの参照情報を格納するディレクトリ
│   ├── heads  # 各ローカルブランチの参照情報
│   ├── tags  # タグの参照情報
├── config  # リポジトリの設定ファイル（ユーザー名、リモート設定など）
├── description  # リポジトリの説明（Gitwebなどのインターフェースで使用される）
└── HEAD  # 現在のブランチを指し示すファイル
```

### **2. ローカル環境 と リモート環境 の関係性**
- **リモート (GitHub等)** にある最新の情報を取得するには`git fetch`を実行する必要がある。
- `fetch`しただけでは、`remotes/origin/main`は更新されるが、main（ローカルブランチ、ローカルの作業ディレクトリ）はそのままで反映されず、`git merge`や`git pull`を使って統合する必要がある。
- `remotes/origin/`にあるデータは、サーバーから取得した状態のもので、ローカルの`heads`とは別管理。
- `.github`ディレクトリは、GitHub Actions（CI/CDの設定）などが含まれており、`.git`とは役割が異なる。

![](https://storage.googleapis.com/zenn-user-upload/4b906c68ad4d-20250302.png)

![](https://storage.googleapis.com/zenn-user-upload/409197255173-20250302.png)

### **3. `.gitignore` の役割**
- **Gitで管理したくないファイルやフォルダを指定するための設定ファイル**
- `.gitignore`に書かれたパターンに一致するファイルは、`git add`してもステージングされない

#### **📌 `.gitignore` によく含まれるもの**
| 分類 | 例 |
|------|----|
| **環境依存のファイル** | `.DS_Store`（Mac）、`Thumbs.db`（Windows） |
| **ログファイル** | `*.log` |
| **ビルド成果物** | `dist/`, `build/`, `*.o` |
| **依存パッケージ** | `node_modules/`, `venv/` |
| **個人情報や設定ファイル** | `.env`, `config.yml`, `*.pem` |

**→ すでにGit管理下にあるファイルは、`.gitignore` に追加しても無視されないので、`git rm --cached <ファイル名>` する必要がある。**
- 例えば、誤ってsecrets.txtというファイルをGit管理下に追加してしまった場合、`.gitignore`にsecrets.txtを追記しただけでは、まだGitの管理対象のままです。
- この状態から管理対象を外すには、`git rm --cached secrets.txt`を実行する必要があります。
- その後、コミットすることで、変更が`.gitignore`に反映され、secrets.txtはGitの管理対象から外れます。

## **Gitフォルダとgitignoreの違いのまとめ**
- `.git` はリポジトリの履歴や管理情報を保持するフォルダで、削除するとGitの管理が解除される
- `git fetch` はリモートの状態をローカルに反映するが、ローカルの作業ディレクトリは変更されない
- `.gitignore` はGitで管理したくないファイルを指定するもので、すでに管理されているファイルには効果がない
- `.github` はGitHub用の設定ファイルを含むフォルダで、`.git` とは別物

# Git履歴を消して新規リポジトリとして管理する手順
クローンしたリポジトリの過去の履歴を消して、ローカルで新しいプロジェクトとして作業したいケースがあります。

そうすることのメリットは、
・過去の履歴を完全に削除し、クリーンな状態で作業できる
・不要なコミット履歴や`.gitフォルダ`の肥大化を防げる
・履歴に含まれてしまった秘密情報（APIキーなど）を完全に削除できる

**手順：**
1. GitHubで新しいリポジトリを作成を済ませておく

2. GitHub からコピーしたい元のリポジトリをクローン
    ```sh
    git clone <コピーしたい元のリポジトリのURL>
    cd <リポジトリ名>
    ```
    
3. `.gitフォルダ`を削除
    ```sh
    rm -rf .git  # macOS/Linux
    rd /s /q .git  # Windows (PowerShell)
    ```
    この時点で、過去の履歴は完全に消えています。
    ※`rm -rf .gitコマンド`は、`.gitフォルダ`を完全に削除する強力なコマンドです。
    実行すると元に戻せませんので、十分注意して実行してください。
    
4. 新しいGitリポジトリとして初期化
    ```sh
    git init
    ```
    このコマンドで新しい .git フォルダが作成され、Gitの管理がリセットされます。

5. ファイルをステージング＆コミット
    ```sh
    git add .
    git commit -m "Initial commit"
    ```

6. 事前に作っていた新しいリポジトリのリモートに追加
    ```sh
    git remote add origin <新しいリポジトリのURL>
    ```

7. 初回プッシュ
    ```sh
    git push -u origin main
    ```
    ※main はブランチ名です。ご利用のブランチ名に合わせて変更してください。

代替案として「Gitの履歴を特定の状態にリセットする」`git rebase -i HEAD~n`や`git filter-branch`という方法もあります。

# おわりに
Gitの基本構造や、gitフォルダの中にどんなファイルが格納されているのか理解できました。
また、流れを図解したことで、直感的にもイメージがしやすくなりました。

最後に、今回参考にした記事を載せておきます！

https://git-scm.com/docs/git-init

https://git-scm.com/book/ja/v2/Git-%e3%81%ae%e5%9f%ba%e6%9c%ac-%e5%a4%89%e6%9b%b4%e5%86%85%e5%ae%b9%e3%81%ae%e3%83%aa%e3%83%9d%e3%82%b8%e3%83%88%e3%83%aa%e3%81%b8%e3%81%ae%e8%a8%98%e9%8c%b2#r_ignoring