Gitまとめ

# 初めに
この記事は**新しいLinuxの教科書**の備忘録です。
メモ程度に記録していきます。
**非常にわかりやすいのでぜひ手に取ってみることをお勧めします。**
**ここではバージョン管理システムであるGitについてまとめます。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1878034/f5f1a666-83f0-6182-7cec-c5818fa27bdd.png)

# Gitとは
`Git`はファイルの変更履歴を保存し管理するためのバージョン管理システムのことです。
`Git`はバージョン管理システムとして広く使われているためほとんどのディストリビューションで提供されています。
**※Ubuntuの場合は初めからインストールされていました。（ちなみにMacも）**
インストールされているかは`git --version`などで確認してみてください。インストールされていればバージョンが表示されるはずです。
```
$ git --version
git version 2.32.1 (Apple Git-133)
```

インストールする場合は`git-core`というパッケージをインストールします。
```
$ sudo apt-get install git-core
```

Windowsの場合は以下のリンクを参考にインストールしてみてください。

https://prog-8.com/docs/git-env-win


Gitの主な機能は二つです。
* ファイルに対して`いつ` `誰が` `どのような目的で` `どのような変更を加えたのか`を記録し閲覧できる。
* 必要に応じてファイルを過去の状態に戻す。

# Gitの初期設定
Gitを使う為の初期設定として、**ユーザー名**と**メールアドレス**の設定を行います。
初期設定には`git config`コマンドを使います。

```
$ git config --global user.name '<ユーザー名>'
$ git config --global user.email '<メールアドレス>'
```
ここではGitを使っている人の情報を設定しており、ファイルに変更を加えた際に**誰が**変更したのかを参照します。

設定した情報は`~/.gitconfig`ファイルに保存されます。
```:~/.gitconfig
[user]
        name = <ユーザー名>
        email = <メールアドレス>
```

# リポジトリの作成
そもそもリポジトリとは？
>Gitがファイル変更を保存している場所のことです。ファイルの変更履歴はすべてこのリポジトリに登録されます。過去のファイルの状態に巻き戻す時にもこのリポジトリから内容を取り出します。

## git init
リポジトリの作成にはバージョン管理をしたいディレクトリで`git init`コマンドを実行します。
ちなみにバージョンを管理したいディレクトリを**ワークツリー**と言います。Gitはワークツリー内のディレクトリやファイルの変更を管理します。

```
$ git init
```
実行したら実行したディレクトリ内に`.git`というディレクトリが生成されます。
この`.git`ディレクトリが**Gitリポジトリの実体**です。
リポジトリ(`.git`)に保存されたファイルはGitによって特別な形式に変換されているため、エディタなどで**直接変更することはできません**。

# リポジトリへ追加
ファイルに何かしら変更を加えたら次にリポジトリへ変更を追加していきます。変更を追加するには`git add`と`git commit`の二つのコマンドを用います。

## git add
`git add`はどのファイルをリポジトリに履歴として追加するかを指定するコマンドです。
```
$ git add <ファイル名>
```
すべてのファイルを追加したい場合は`.`を指定します。
```
$ git add .
```
変更したすべてのファイルをまとめて追加したい場合は`-u`オプションを用いると便利です。
ただし新規作成して一度もコミットしていないファイルは含まれません。
```
$ git add -u
```
新規作成したファイルも含めて編集したファイルをすべて追加したい場合は`-A`オプションを使います。
```
$ git add -A
```

**この時点ではまだリポジトリに変更が登録されていません。**
リポジトリへの登録待ちといった状況でしょうか。

## git commit
`git add`で変更履歴を追加するファイルを指定したら、`git commit`コマンドで実際にリポジトリに変更を追加（反映）します。
`git commit`する際は`-m`オプションで**修正に対するメッセージ**を入力します。
```
$ git commit　-m <修正のメッセージ>
```
**ここでGitリポジトリにファイルを変更した内容が登録されます。**

## 深掘り
`git add`コマンドは追加するファイルを指定するコマンドでしたが、指定するだけではなく**インデックス**と呼ばれるワークツリーとはまた別の領域に編集したファイルを配置・登録するためのコマンドです。

`git commit`は`git add`によって登録されたインデックスの内容をリポジトリに登録するためのコマンドなのです。

![リポジトリ説明.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1878034/b3909faa-c634-1326-3880-07c2d5d483d3.png)


インデックスはいわば**ワークツリーとリポジトリを結ぶ橋渡し的な領域**といったとこでしょうか。

# 差分の表示
## git status
これは現在のワークツリーの状態を表示するためのコマンドです。
```
$ git status
```
変更が加わっているファイルには修正を意味する`modified:`と表示されます。

## git diff
これは変更の差分を確認するためのコマンドです。
差分は`diff`コマンドのユニファイド形式で表示されます。
```
$ git diff
```


# 変更履歴の確認
変更履歴は`git log`コマンドで確認することができます。
```
$ git log
```
変更履歴は以下の4つが表示されます。
* commit:コミットを特定する一意のコミットのオブジェクト名（40文字の文字列）
* Author:変更を加えたユーザ名
* Date:変更を加えた日時
* コミットメッセージ

`-p`オプションを加えることで差分も合わせて確認することができます。
```
$ git log -p
```

また`git diff`コマンドでコミットのオブジェクト名を指定するとその時の差分を確認することができます。
```
$ git diff <コミットのオブジェクト名>
```

# 復旧
`Git`の主な機能として、`必要に応じてファイルを過去の状態に戻す`という機能がありました。
ここでは復旧を行うコマンドについて紹介します。

## ワークツリーの復旧
ワークツリー特定のファイル・フォルダの復旧には`checkout`コマンドを使います。`checkout`コマンドはブランチ移動にも使われるコマンドであるためコマンドの後に`-- ファイル名(orフォルダ名)`と指定することで変更を無かったことにできる。

```
$ git checkout --ファイル名
$ git checkout --フォルダ名
```

ワークツリーの復旧にはワークツリーの一番上のディレクトリに移動し以下のコマンドを実行します。
```
$ git checkout HEAD .
```
これにより、ファイルの編集や削除した状態がすべて元に戻ります。またインデックスに追加した内容も取り除かれるので、まだコミットしていない差分が取り除かれ、ワークツリーがリポジトリと同じ状態になります。

## コミットの復旧
誤った内容をコミットしてしまった場合は以下のコマンドを実行します。
```
$ git revert <取り消したいコミットのオブジェクト名>
```
これにより**コミットを打ち消す内容をコミットする**ことになります。つまり差分を見て手作業で修正を取り除いてコミットすることと同じことをおこなっています。

# ブランチ
Gitでは同じファイルを並行して作業を行える機能もあります。片方で新しい機能を開発し、片方でバグの修正を行うようにそれぞれ別の領域で作業を行えます。
Gitのブランチは枝分かれのように表現されます。
![スクリーンショット 2023-02-27 21.53.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1878034/1fad312e-e812-ef1b-3c50-b626ea7bbaf5.png)

大元のブランチを`master`や`main`ブランチと呼びます。基本的にはこの`master`や`main`ブランチにコミットが反映されます。
派生したブランチは任意の名前をつけることができます。
なおGitのブランチは**分岐した履歴の先頭にあるコミットを指し示すラベルのこと**です。

## ブランチの確認
ブランチの一覧を見たい場合は`git branch`コマンドを使用します。

```
$ git branch
* master
```
`*`がついているブランチ名が今いるブランチです。

## ブランチの生成
新しくブランチを作成したい場合はブランチ名を指定することで作成できます。
生成したブランチでテストを行ったり修正をしたりします。
```
$ git branch <ブランチ名>
```

## ブランチの切り替え
ブランチを切り替えたい場合は`git checkout`コマンドを使います。
```
$ git checkout <ブランチ名>
```

## ブランチの取り込み
分岐させたブランチの内容を別のブランチに取り込むことができます。ブランチの取り込みを**マージ**と呼びます。
ブランチをマージするには以下の手順で行います。
1. マージしたいブランチに`git checkout`で移動
1. `git merge`コマンドでマージ

```:マージ先ブランチに移動
$ git checkout <マージ先ブランチ名>
```

```:ブランチをマージ
$ git merge <マージするブランチ名>
```

## ブランチの削除
ブランチの削除には`git branch`コマンドに`-d`オプションをつけることで削除できます。

```
$ git branch -d <削除したいブランチ名>
```



# バックアップ
Gitでは変更の履歴はすべてリポジトリに保存されていますが、このリポジトリを間違えて削除してしまった場合はどうすることもできません。このような万が一のために備えてGitではリポジトリのバックアップをとることができます。

バックアップは以下の手順で行います。
1. バックアップ用のリポジトリの作成
1. 変更履歴をバックアップ用リポジトリに送る

## バックアップ用リポジトリの作成
まずは`mkdir`コマンドなどを用いてバックアップ用のフォルダを作成します。場所はどこでも良いです。
**フォルダ名には最後に`.git`をつけてください。**
```
$ mkdir -p .../example.git
```

作成したフォルダに`cd`コマンドで移動し、`git init`コマンドを実行します。
**この時`--bare`オプションを忘れないようにしてください。**

```
$ cd .../example.git
$ git --bare init
```
`--bare`オプションはベアリポジトリを作成するためのオプションで、ベラリポジトリは簡単にいうと複製のためのリポジトリのこと。細かくいうと作業ディレクトリを持たないリポジトリのことです。

## 変更履歴をバックアップ用リポジトリに送る
バックアップ用のリポジトリを作成したら、そのリポジトリに元のリポジトリの内容を送ります。
まずは元のリポジトリに戻ります。
元のリポジトリは`.git`フォルダでしたね。移動先は`.git`フォルダがあるディレクトリ(ワークツリー)です。

```
$ cd <元のリポジトリのパス>
```

移動できたら変更の履歴を`git push`コマンドを用いて送ります。
```
$ git push <送信先リポジトリ> <送信元ブランチ>:<送信先ブランチ>
```
送信先リポジトリは先ほど作成したバックアップ用のリポジトリのパスを指定します。
送信元ブランチはバックアップしたいブランチを指定します。
送信先ブランチは送られた送信元ブランチをどのブランチに保存するのかを指定します。

送信元ブランチと送信先ブランチが同じ場合は`:`を省略できます。
```
$ git push <送信先リポジトリ> <ブランチ名>:
```

## バックアップ用リポジトリから復元
バックアップしたリポジトリからファイルを復元したい場合は`git clone`コマンドを使います。
```
$ git clone <複製元リポジトリ>
```

## リポジトリパスに名前を割り当てる
リポジトリパスは非常に長くなる場合があります。そんな場合リポジトリパスに別の名前をつけることでパスの入力を楽にすることができます。
リポジトリパスに別名をつけるには`git remote add`コマンドを使います。
```
$ git remote add <別名> <リポジトリパス>
```
別名のところには`origin`という名前を慣習となっています。

割り当てた名前は`git remote -v`コマンドで確認できます。
```
$ git remote -v
```

別名に置き換えたことで変更履歴をバックアップ用リポジトリに送るコマンドがかなりスッキリします。
```:別名割り当てる前
$ git push <送信先リポジトリ> <送信元ブランチ>:<送信先ブランチ>
```

```:別名割り当て後
$ git push origin master
```
※masterブランチをバックアップする場合。

ここまでのGitコマンドが理解できればGitHubにアップロードする時に使うコマンドの意味がスッと理解できます。
```
$ git init
$ git add README.md
$ git commit -m "first commit"
$ git branch -M main
$ git remote add origin <GitHubのリポジトリURL>
$ git push -u origin main
```
以下解説。
```
$ git init
$ git add README.md
$ git commit -m "first commit"
```
ここでは自分のローカル環境のgitリポジトリに変更を反映させています。

```
$ git branch -M main
```
ここでは今いるブランチの名前を`-M`オプションで強制的に`main`という名前に変更しています。
オプションについては[こちら](https://tracpath.com/docs/git-branch/)を参考してください。

```
$ git remote add origin <GitHubのリポジトリURL>
```
ここではバックアップ用のリポジトリである`GitHubのリポジトリURL`のリポジトリ名を`origin`という名前に変更しています。

```
$ git push -u origin main
```
最後に変更をGitHubのリポジトリに`push`して反映させています。


# リポジトリの共有
これまではGitを使って自分だけのファイル管理を行なっていましたが、実際の業務ではチーム開発のように複数人で開発することがあります。このように共同作業を行う場合にはリポジトリの共有を行い、それぞれのファイル変更を共有して開発を進めます。

![スクリーンショット 2023-02-28 23.38.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1878034/5e9709d6-13e1-48cf-4601-e31e9e4fa31a.png)

共有リポジトリは先ほど説明したバックアップ用のリポジトリににています。バックアップ用のリポジトリのリポジトリ名が共有されているといった状況です。
基本は各ユーザが自分専用のリポジトリを持っており、ファイル変更を加えたり、テストを行なったりして、ある程度作業が落ち着いたら`git push`コマンドで共有リポジトリに変更を反映させていきます。

逆に他の人が変更した内容を取り込み自分のリポジトリに反映させるには以下の手順を行います。
1. `git fetch`コマンドで他のリポジトリの変更内容を取り込む
1. `git merge`コマンドで自分のリポジトリに変更を反映させる

## git fetch
`git fetch`コマンドは指定したリポジトリの変更を取得できるコマンドです。
```
$ git fetch <リポジトリ名>
```
この時取得された履歴はリモート追跡ブランチというブランチに保存されます。このブランチは自分で作成したブランチとは別のブランチで、`リモート名/ブランチ名`という名前で自動的に作られます。
リモートブランチを表示するには以下のコマンドを実行します。

```
$ git branch -r
```

**この時まだワークツリーやローカルブランチには反映されていません。**

取得した変更を自分のワークツリーやブランチに反映するには`git merge`コマンドを実行します。

```
$ git checkout <マージ先のブランチ名>
$ git merge <リモート名>/<ブランチ名>
```

## git pull

1. `git fetch`コマンドで他のリポジトリの変更内容を取り込む
1. `git merge`コマンドで自分のリポジトリに変更を反映させる

先ほど説明した上記の手順はセットでよく使われるためこれを一つにまとめたコマンドが`git pull`です。

```
$ git pull <リモートリポジトリ名> <リモートリポジトリのブランチ名>
```

本格的に共同開発を行う場合は共有リポジトリは同じファオルシステム内に置かないで、ネット上で管理します。
オンライン上でリポジトリを管理するサービスが**GitHub**なのです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1878034/bb84b266-24e4-673c-e23d-640edfad9899.png)


# 参考
新しいLinuxの教科書　三宅英明・大角祐介　著

https://www.amazon.co.jp/%E6%96%B0%E3%81%97%E3%81%84Linux%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E4%B8%89%E5%AE%85-%E8%8B%B1%E6%98%8E-ebook/dp/B072K1NH76/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=IYU3QOSVEDDV&keywords=%E6%96%B0%E3%81%97%E3%81%84linux&qid=1677597368&s=digital-text&sprefix=%E6%96%B0%E3%81%97%E3%81%84linux%E3%81%AE%2Cdigital-text%2C264&sr=1-1