【勉強用】Gitのコマンドを実際に動かしてみた①（基本操作編）

# はじめに
今回はGitのコマンドを実際に動かして、バージョンの確認や変更について理解を深めたいと思います。参考図書はこちらの[**動かして学ぶ！Git入門**](https://www.shoeisha.co.jp/book/detail/9784798170855)を使用しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3523467/927467bd-3ee8-bff3-c016-81d24c7d4cb0.png)


# Gitとは
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3523467/8fb4543b-ce60-3f80-66d8-f6b4f69214e6.png)

Git（ギット）は、分散型バージョン管理システム（DVCS）の一つで、コードやプロジェクトの変更履歴を効果的に管理し、複数の開発者が協力してソフトウェアの開発やプロジェクトの管理を行うためのツールです。

Gitダウンロードは[**こちら**](https://git-scm.com/)から

# コマンド
実行には**Git Bash**を使用しています。
（ここでは"git/test"というディレクトリをトップのディレクトリとしています。）
### 1. git config --global
**git config**は、Gitの設定ファイルにある変数の値を設定するコマンドです。Gitの設定ファイルには3種類あります。

>**・そのマシン全体に対する設定：/etc/gitconfig**
>**・ユーザごとの設定：~/.gitconfig**
>**・プロジェクトごとの設定：.git/config**

**--global**オプションは~/.gitconfigに設定するという意味です。
Gitを使い始めるには、**user.name**と**user.emai**を設定します。これらの変数は各コミットに書き込まれる名前とメールアドレスです。
```Git:Git Bash
$ git config --global user.name "HANAKO"
$ git config --global user.email "hanako@example.com"
```

名前とメールアドレスが設定されたか確認してみましょう。確認には~/.gitconfigを直接調べても良いのですが、**git config --global -l**を使用するほうが便利です。

```Git:Git Bash
$ git config --global -l

core.editor=code --wait
core.autocrlf=input
user.name=HANAKO　　　　　　　 #名前
user.email=hanako@example.com #メールアドレス
difftool.sourcetree.cmd=''
mergetool.sourcetree.cmd=''
mergetool.sourcetree.trustexitcode=true
merge.tool=code --wait "$MERGED"
push.default=simple
init.defaultbranch=main

```
### 2. git init
既に開発プロジェクトが進んでいて、ファイルやディレクトリがあるときに、Gitでバージョン管理を始めるには、その開発プロジェクトのトップのディレクトリで**git init**コマンドを実行します。すると.gitディレクトリが作成され、空のリポジトリがその中に作成されます。

```Git:Git Bash
$ git init
Initialized empty Git repository in C:/Users/user/git/test/.git/
```

### 3. git add
**git add**コマンドは、作業ツリーにあるファイルやディレクトリをステージングするコマンドです。例えば、`hello.txt`というファイルをステージングするには、次のコマンドを実行します。

```Git:Git Bash
$ git add hello.txt
```
それでは`hello.txt`がステージングされたか確認してみましょう。確認には**git status**を使用します。

```Git:Git Bash
$ git status
On branch main

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   hello.txt
```
**git status**はコマンドは、HEADが指すコミットと、ステージ、作業ツリーの差を表示します（これは後の項目で解説します）。しっかりとステージングされていますね。次はステージングしたファイルをコミットしていきましょう。


### 4. git commit
ステージングしたファイルをコミットするには**git commit**コマンドを使用します。
```Git:Git Bash
git commit
```

実行すると、コミットに関するメッセージを書くために、エディタが立ち上がります。#はメッセージに含まれません。適当な箇所にメッセージを書いていきましょう。

```git:エディタ
first commit
#以下は最初から表示されているメッセージ
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch main
#
# Initial commit
#
# Changes to be committed:
#	new file:   hello.txt
#
```
実行が終わると以下のメッセージが表示されます。

```Git:Git Bash
$ git commit
[main (root-commit) e6e9a3b] first commit
 1 file changed, 1 insertion(+)
 create mode 100644 hello.txt
```
これでコミットは完了です。補足として、以下のコマンドでも同じ処理を行うことが出来ます。
```Git:Git Bash
$ git commit -m "first commit"
[main 7321341] first commit
 1 file changed, 1 insertion(+), 1 deletion(-)
```
#### 補足：
コミットの特定には、そのコミットの**ハッシュ**を使用します。これはコミットの内容はハッシュ関数に掛けて得られる値で、`d56a6035c435f`のような形をしています。Gitはこれをコミットを識別するIDとして使います。またGitは現在のコミット（最新のコミット）を指すポインタを保持しています。このポインタを**HEAD**といいます。開発が進み、新たにコミットするとHEADはそのコミットに移動します。

### 5. git log
コミットの履歴を見るには**git log**コマンドを使用します。試しに実行してみましょう。
（他のコマンドの実行の過程で先ほどのコミットにおけるハッシュ値とは異なります。）
```Git:Git Bash
$ git log
commit e6e9a3b54ed9da71de0ba63ccd612a9bd492d98a (HEAD -> main)
Author: HANAKO <hanako@example.com>
Date:   Fri Nov 3 14:59:10 2023 +0900

    first commit
```

### 6. git status
**git status**コマンドは、HEADが指すコミットと、ステージ、作業ツリーの差を表示します。作業ツリーをステージし、コミットした直後ではこれら3つの間に差はありません。

```Git:Git Bash
$ git status
On branch main
nothing to commit, working tree clean
```
これはコミットするものがなく、作業ツリーにも変更がないといことを表しています。それでは新たに`hello.txt`の中に`Hello, everyone!`という文章を追加して、再度**git status**コマンドを実行してみましょう。
```Git:Git Bash
$ git status
On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   hello.txt

no changes added to commit (use "git add" and/or "git commit -a")
```
これは作業ツリーに変更があったことを表しています。それではこの変更をステージングをしてみましょう。
```Git:Git Bash
$ git add hello.txt
$ git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   hello.txt
```
これはステージと細心のコミットとの間に差があることを表しています（変更をステージングしたので当然と言えば当然ですが…）。最後に、このコミットして、状態を確認してみましょう。
```Git:Git Bash
$ git status
On branch main
nothing to commit, working tree clean

$ git log
commit 714ed154be5186cca4f5fc1b540526fb207ccb2a (HEAD -> main)
Author: HANAKO <hanako@example.com>
Date:   Fri Nov 3 15:30:56 2023 +0900

    check status

commit e6e9a3b54ed9da71de0ba63ccd612a9bd492d98a
Author: HANAKO <hanako@example.com>
Date:   Fri Nov 3 14:59:10 2023 +0900

    first commit
```
しっかりとコミットされ、コミット、ステージ、作業ツリーの間に差がないことが確認できました。

### 7. git diff
**git diff**コマンドはファイル間の差を指定して表示します。具体的には以下の種類のコマンドがあります。
>git diff：作業ツリーとステージとの差を表示
>git diff --staged：ステージとコミットとの差を表示
>git diff HEAD：作業ツリーとコミットとの差を表示

それでは各コマンドの動きを確認していきましょう。まず`hello.txt`に新たに`Goodbye!`という文章を追加し**git diff**を実行します。
```Git:Git Bash
$ git diff
Git touches it
diff --git a/hello.txt b/hello.txt
index 5a09d1c..7fe6306 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1,2 +1,3 @@
 hello!
-Hello, everyone!
\ No newline at end of file
+Hello, everyone!
+Goodbye!
\ No newline at end of file
```
次にステージングを実行し、**git diff --staged**を実行します。
```Git:Git Bash
$ git add hello.txt
$ git diff --staged
diff --git a/hello.txt b/hello.txt
index 5a09d1c..7fe6306 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1,2 +1,3 @@
 hello!
-Hello, everyone!
\ No newline at end of file
+Hello, everyone!
+Goodbye!
\ No newline at end of file
```
最後にコミットを実行し、**git HEAD**を実行してみましょう。

```Git:Git Bash
$ git commit -m "check diff"
[main a454aad] check diff
 1 file changed, 2 insertions(+), 1 deletion(-)

$ git diff HEAD
#ここには何も表示されません
```
コミットを行うことで、作業ツリーとコミットとの間に差がなくなったため、何も表示されませんでした。

他にもコミット間の差を表示する**git diff コミット1　コミット2**という書き方もあります。コミットには一意のハッシュ値が対応しています。まずは**git log**でコミットのハッシュ値を確認しましょう。
```Git:Git Bash
$ git log
commit a454aad60bcce0e76f9165ff6f1ece10b07219c4 (HEAD -> main)
Author: HANAKO <hanako@example.com>
Date:   Fri Nov 3 15:43:49 2023 +0900

    check diff

commit 714ed154be5186cca4f5fc1b540526fb207ccb2a
Author: HANAKO <hanako@example.com>
Date:   Fri Nov 3 15:30:56 2023 +0900

    check status

commit e6e9a3b54ed9da71de0ba63ccd612a9bd492d98a
Author: HANAKO <hanako@example.com>
Date:   Fri Nov 3 14:59:10 2023 +0900

    first commit
```
次にHEADと`check status`のコミットを比較してみましょう。
```Git:Git Bash
$ git diff HEAD 714ed15
diff --git a/hello.txt b/hello.txt
index 7fe6306..5a09d1c 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1,3 +1,2 @@
 hello!
-Hello, everyone!
-Goodbye!
\ No newline at end of file
+Hello, everyone!
\ No newline at end of file
```
コミット間の差を確認できましたね。ハッシュ値は全て入力する必要はなく、ある程度の長さであれば判別できるようです。またHEADのn個前のコミットを`HEAD~n`または`@~n`と書けます。`@`は`HEAD`と同義です。

### 8. git show
**git show**あるコミットがプロジェクトにどのような変更をしたか表示するコマンドです。具体的にはコミットのハッシュや作者、コミットメッセージ、親子ミットに対してどこを変更したかを差分の形で表示します。

```Git:Git Bash
$ git show HEAD
commit a454aad60bcce0e76f9165ff6f1ece10b07219c4 (HEAD -> main)
Author: HANAKO <hanako@example.com>
Date:   Fri Nov 3 15:43:49 2023 +0900

    check diff

diff --git a/hello.txt b/hello.txt
index 5a09d1c..7fe6306 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1,2 +1,3 @@
 hello!
-Hello, everyone!
\ No newline at end of file
+Hello, everyone!
+Goodbye!
\ No newline at end of file
```
# まとめ

今回は主にGitの始め方から、変更の方法、初歩的な確認方法などを学習しました。次回はコミットの変更や削除から学習していきます。


**次回：** [**【勉強用】Gitのコマンドを実際に動かしてみた（②コミット編）**](https://qiita.com/Yuhei0531/items/ad69b53622225bcafcac)

# 参考文献
[動かして学ぶ！Git入門](https://www.shoeisha.co.jp/book/detail/9784798170855)
[【Git】バージョン管理Gitでよく使うコマンドまとめ](https://develop.blue/2020/03/git-use-command/)