【Git】超初心者向け Gitをつかってみる その１（git init から git commitまで）

# はじめに
[Git Advent Calendar 2023 1日目](https://qiita.com/advent-calendar/2023/git)の投稿です。よろしくおねがいします。
新入社員のころGitを使うプロジェクトに配属された際に、わけもわからず黒い画面で`add`して`commit`だけしていました。また、みんなのソースコードをぶっ壊したらどうしようとおびえながらマージをしていました。
そんな過去の自分に向けてGitが怖くなくなるように、何日かにかけてGitについてハンズオン形式で使ってみたいと思います。

この記事と次の記事で目指すところは、Gitを知らない新入社員が入ってきたプロジェクトで「Gitについてはとりあえずこの記事よんで触っといて」と渡せるような説明を書くことです。
あとは、年末年始の暇つぶしとして読んでいただければうれしいです:relaxed:
（まあ、[公式](https://git-scm.com/doc)でドキュメントがそろってるしネットにもこういう記事はありふれてるんですけど、アウトプットすると身につくっていうし、自分の頭の整理でもあります。）

# 環境
Windowsを使用して、Gitのバージョンは下記を使います。
```batch
$ git --version
git version 2.22.0.windows.1
```
また、Git Bashを使っています。

# そもそもGitって？
GitはLinuxカーネルの開発をサポートする目的で、Linus Torvaldsによって作成された**分散バージョン管理システム**です。

バージョン管理システムには他にもSubversionとかMercurialとかいろいろあるのですが、Linusはもともと使っていたバージョン管理システムBitKeeperの代わりを探した果てに自分で作ることを選んだようです。
よく、「大規模プロジェクトを効率的に取り扱いできること」や「分散開発を容易にすること」などがGitのメリットとして言われますが、新入社員のころの私にいってもピンとこないので割愛します。**ここでは、便利なんだな～程度の理解で十分**です。とりあえずGitの使い方に慣れましょう。

ちなみに「git」とはイギリス語のスラングで「あほ、まぬけ」を意味します。これは、Linusの命名の付け方が自分自身にちなんだ名前を付けるから…という意図があるとかないとか。

# Gitを使ってみる
さっそくGitを使っていきます。
インストーラを[ここ](https://git-scm.com/downloads)から入手して自身の端末にインストールしておきます。

# git init
まず、フォルダをGitのリポジトリとして認識させるために打つコマンドが`git init`です。
**「リポジトリ」とはファイルやディレクトリの状態を記録していく場所のこと**です。
リポジトリに記録していくことで、「あの時のファイルの中身ってどうなってるんだろな～」って思った時に**過去のある時点に戻れたり**、「いま何を修正したんだっけ」となった時に**過去と今のファイル間の差分を取れたりする**ようになります。

ではでは、さっそくリポジトリを作ってみましょう。
まずデスクトップに「git/sample」フォルダを用意します（初心者向けなので具体的な場所を指定していますが、別にどこでもいいです）。
次にGit Bashを開いて「git/sample」フォルダまで移動します。
ここで`git init`します。
```batch
~/Desktop/git/sample
$ git init
```
すると、、
```batch
~/Desktop/git/sample
$ git init
Initialized empty Git repository in 『フォルダ名』

~/Desktop/git/sample (master)
$
```
メッセージを訳すと「空のGitリポジトリとして初期化」のコメントが表示されて、ディレクトリの後ろに`(master)`と付いたことがわかります。いったん`(master)`は気にしなくて大丈夫です。

これで、このフォルダはGitのリポジトリとして認識されて、ファイルやディレクトリの状態を記録していくことができるようになりました。

ここで、「git/sample」フォルダを見てみましょう。
![git_init後のフォルダ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526202/25505291-ad11-8262-4c40-555807b8ba5b.png)
「.git」フォルダが生成されていることがわかります。このフォルダは**Gitが管理するフォルダ**なので、中身をいじらないでください。
Gitのファイルやディレクトリの状態や設定などすべての情報をここで管理しています。Gitのコマンドを打つとこの「.git」フォルダの中身が更新されてGit君は状況を管理しています。

[アドベントカレンダー 3日目](https://qiita.com/advent-calendar/2023/git)で「.git」に触れますので、そこでコマンドによって中身がどう変わるか見てみてください。

# git config
実はリポジトリに作業していくためには、名前とメールアドレスの登録が必要です（細かく言うとコミットするためにコミット作成者の設定が必須です。だれがファイルを修正したかGitが把握できないからですね）。

設定には`git config`コマンドを使います。
```batch
~/Desktop/git/sample (master)
$ git config user.name "hogehoge"

~/Desktop/git/sample (master)
$ git config user.email "fugafuga"
```
上のコマンドを打つことで、「hogehoge」という名前で「fugafuga」というメールアドレスをもつ作業者であることをGitが認識します。

また、設定内容を確認したい場合は`git config --list`でいけます。
```batch
~/Desktop/git/sample (master)
$ git config --list
core.symlinks=false
…
user.name=hogehoge
user.email=fugafuga
```
ちなみに同一の設定内容がある場合は下のものが有効になります。

# git addとgit commit
では、次にファイルをリポジトリに管理させてみましょう。
ファイルをリポジトリに登録して管理させるには`git add`と`git commit`コマンドを使います。

Gitでファイルを管理する場合、リポジトリに変更を登録する前に**インデックス**という作業内容を一時的に登録する領域へリポジトリに登録する内容を集めます。そして、インデックスに集まった作業内容をひとまとまりの変更としてコミットします（インデックスのことをステージング領域という人もいます）。

**インデックスに登録する**には`git add`を、**インデックスに登録した内容をリポジトリに登録する**には`git commit`を使います。

- リポジトリと`git add` `git commit`の関係
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526202/b76addcb-4656-8fd3-49dd-faf6f950ae30.png)

また、ここでは「ステージする」と言ったらインデックスにファイルを登録すること、「コミットする」と言ったらインデックスに登録されてる修正内容をリポジトリに登録することを指します。

要は、**Gitは段階を踏んでリポジトリに登録して管理させることを行います。**
最初使っているころは、`add`なんていらないだろと億劫さを感じますが、`add`には以下の意味があると思ってます。
- コミットせずに複数の作業をした場合に1つのコミットに1つの作業内容をまとめられる。
- コミットの前に冷静に修正内容を確認できる。

この辺は使っているうちに感じるようになると思いますし、賢い人が考えたシステムなので他にもいろいろなメリットがあるんだと思います。初心者の内はコミットにまとめたい内容を`add`してコミットする内容を確認してから`commit`する、と覚えておけば十分かなと思ってます。

ってことで、やっていきましょう。
まず、Gitのリポジトリで空ファイル「sample.txt」を作ります。
![から.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526202/b9af51ab-95ee-be97-740d-cd6be80916ab.png)
ここでGitに戻り、`git status`を打ちます。
`git status`コマンドでは、作業フォルダとインデックスの状況を確認できます。
```batch
~/Desktop/git/sample (master)
$ git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        sample.txt

nothing added to commit but untracked files present (use "git add" to track)
```
日本語に訳してみると、「コミットするために`add`されているものはなく、未追跡ファイルがあるよ（追跡するには`git add`を用いよ）」とのことから、未追跡ファイル（Untracked files）に「sample.txt」があるとGitが認識してることがわかります。

- 今の状態
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526202/986fb5e1-e3de-a37d-fa6b-3e202686cdc9.png)

ここで未追跡ファイルとは何なのか説明しておきます。

Gitではファイルを３つのグループに分けて管理します。
- **追跡**（tracked）
    - **既にリポジトリかインデックスに登録されたファイル**のこと。履歴が管理されてる。
    - １度コミットもしくはステージしたファイルはこの状態になっています。
- **無視**（ignored）
    - **リポジトリで管理しないことが明示的に宣言されているファイル**のこと。
    - 各々の環境に依存する設定ファイルなんかはこの状態にします。
- **未追跡**（untracked）
    - **上の２つのグループに属さないファイル**のこと。履歴を管理していない。
    - 初めて作成されたファイルはこの状態です。

未追跡ファイルは`git commit`で一度リポジトリに登録するとファイルを追跡するようになります。

では、`git add`と`git commit`を通じて、リポジトリに作業内容（今回で言ったら空ファイルの作成）を登録しましょう。

- これからやること
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526202/f9fe7244-200f-f18c-48d5-d6ad17fb006d.png)

まずは、`git add`です。`git add ファイル名`で登録できます。
特に何もコンソールには表示されないと思いますが、続けて`git status`をしてインデックスの状態を確認しましょう。変化がわかると思います。
```batch
~/Desktop/git/sample (master)
$ git add sample.txt

~/Desktop/git/sample (master)
$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

        new file:   sample.txt

```
「コミットされる変更」として、新しく「sample.txt」がインデックスに登録されました。

- くどいかもしれませんが、一応今の状況の図
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526202/de5097ce-25a4-64c1-7a3e-b4efacc2b6a5.png)

ちなみに、ここで作業フォルダのファイルを変更するとどうなるでしょうか（`git add`した後にソースコードの誤りに気付いてファイルを編集することは往々にしてありそうです）。

「sample.txt」を開いて適当に文字を打ちましょう。
- 「sample.txt」に"hello"と入力して保存
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526202/24de4772-fe3a-cd48-dd3e-d65656fa106c.png)

ここで`git status`をしてインデックスと作業フォルダの状態を確認してみます。
```batch
~/Desktop/git/sample (master)
$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

        new file:   sample.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   sample.txt
```

コミットされる変更（Changes to be committed）として「sample.txt」が、ステージされていない変更（Changes not staged for commit）として「sample.txt」があります。
- 今の状況
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526202/0c7d7a31-d59f-9f86-99f4-7b62b87fb7e7.png)

このまま続けて`git commit`をすると、**コミットされるのはあくまでもインデックスに登録した変更内容**になります。先ほどの修正内容をリポジトリに登録したい場合は、再度`git add`をする必要があります。

今は適当にとりあえず`git add`しちゃいましょう（実務でしたら、再度修正した内容をコミットに含むべきかどうか（`git add`すべきかどうか）考えましょう）。

- `git add`後はこうなる
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526202/89871c71-61bb-2e2c-2b03-613b35986606.png)


最後にインデックスに登録した作業内容を`git commit`してリポジトリに登録します。
```batch
~/Desktop/git/sample (master)
$ git commit
```
これを打つとデフォルトの設定では黒い画面が出てきます。これは**vi**と呼ばれるエディタでここでコミットメッセージを入力して作業内容がなんなのか後で見返せるようになります。
**初心者向けにviで覚えておくべきは以下の4つ**かなと思います（Gitを使う上でとりあえずの4つ）。

- **i**：コマンドモードから入力モードに移動
- **Escキー**：入力モードからコマンドモードに移動
- **:q!⇒Enterキー**：保存せず終了（コマンドモード）
- **:wq⇒Enterキー**：保存して終了（コマンドモード）

まずは`i`を押して入力モードにして１行目にコミットメッセージ、必要に応じて詳細なコメントを３行目以降に書いて`Esc`キーでコマンドモードへ、`:wq`で`Enter`キーを押して登録できます。
また、まれによくコミットしたくなくなる時があります。そんな時に使うのが`:q!`コマンドです。
今回はコミットメッセージに「はじめてのコミット」と入力して、リポジトリに作業内容を登録しましょう。
- コミットメッセージを入力
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526202/a2b24576-cbaa-1c3c-8c14-bb5f8e597d02.png)
↑の中にも書いてありますが、`#`で始まるのはコミットメッセージとして無視されるので問題ありません。

「コミットメッセージを間違えた、、」なんて方は`git commit --amend`を使いましょう。このコマンドは直前のコミットを修正するために使います。`git commit --amend`をすると再度エディタが表示されますのでここでメッセージを変更しましょう。
- `git commit`後
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526202/a3746d43-0173-5d79-fdc2-23b95b5ab929.png)

以上でリポジトリに登録する作業が完了です。作業フォルダの内容がリポジトリに登録されましたね。


# 今回のまとめ
今回は`git init`をしてリポジトリの作成をして、`git add`と`git commit`を通じてリポジトリにファイルを管理させるところまで行いました。まだまだGitの何がうれしいのか伝わらないかもしれませんがとりあえず使ってみることが出来れば幸いです。
間違いがあればコメントでご指摘いただけるとうれしいです:pray: